On 02/13/2018 01:09 PM, Jason Merrill wrote:
On Tue, Feb 13, 2018 at 2:59 PM, Martin Sebor <mse...@gmail.com> wrote:
On 02/13/2018 12:15 PM, Jason Merrill wrote:
On Tue, Feb 13, 2018 at 1:31 PM, Martin Sebor <mse...@gmail.com> wrote:
On 02/13/2018 09:24 AM, Martin Sebor wrote:



On 02/13/2018 08:35 AM, Martin Sebor wrote:


On 02/13/2018 07:40 AM, Jason Merrill wrote:


On Mon, Feb 12, 2018 at 6:32 PM, Martin Sebor <mse...@gmail.com>
wrote:


While testing my fix for 83871 (handling attributes on explicit
specializations) I noticed another old regression: while GCC 4.4
would diagnose declarations of explicit specializations of all
primary templates declared deprecated, GCC 4.5 and later only
diagnose declarations of explicit specializations of class
templates but not those of function or variable templates.



Hmm, the discussion on the core reflector seemed to be agreeing that
we want to be able to define non-deprecated specializations of a
deprecated primary template.



Yes, that's what Richard wanted to do.  The only way to do it
within the existing constraints(*) is to define a non-deprecated
primary, and a deprecated partial specialization.  This is in line
with that approach and supported by Clang and all other compilers
I tested (including Clang).



To clarify, this approach works for class templates (e.g., like
std::numeric_limits that was mentioned in the core discussion)
and for variable templates.  Functions have no partial
specilizations so they have to be overloaded to achieve the same
effect.

Implementations don't treat the deprecated attribute on partial
specializations consistently.

EDG accepts and honors it on class template partial specializations
but rejects it with an error on those of variables.

Clang accepts but silently ignores it on class template partial
specializations and rejects with an error it on variables.

MSVC accepts and honors it on variables but silently ignores it
on class template partial specializations.

GCC ignores it silently on class partial specializations and
with a warning on variables (I opened bug 84347 to track this
and to have GCC honor is everywhere).

This is clearly a mess, which isn't surprising given how poorly
specified this is in the standard.  But from the test cases and
from the core discussion it seems clear that deprecating
a template, including its partial specializations (as opposed
to just a single explicit specialization) is desirable and
already supported, and that the wording in the standard just
needs to be adjusted to reflect that.


Martin

[*] Except (as Richard noted) that the standard doesn't seem to
allow a template to be deprecated.  I think that's a bug in the
spec because all implementations allow it to some degree.



One other note.  While thinking about this problem during
the core discussion, another approach to deprecating a primary
template without also deprecating all of its specializations
occurred to me.

1) First declare the primary template without [[deprecated]].
2) Next declare its non-deprecated specializations (partial
   or explicit).
3) Finally declare the primary again, this time [[deprecated]].

Like this:

  template <class T> struct                S;
  template <class T> struct                S<const T> { };
  template <class T> struct [[deprecated]] S<volatile T> { };
  template <class T> struct [[deprecated]] S { };

  S<int> si;             // warning
  S<const int> sci;      // no warning
  S<volatile int> svi;   // warning

This works as expected with Intel ICC.  All other compilers
diagnose all three variables.  I'd say for [[deprecated]] it
should work the way ICC does.  (For [[noreturn]] the first
declaration must be [[noreturn]], so there this solution
wouldn't work also because of that, in addition to function
templates not being partially-specializable.)


My understanding of the reflector discussion, and Richard's comment in
particular, was that [[deprecated]] should apply to the instances, not
the template itself, so that declaring the primary template
[[deprecated]] doesn't affect explicit specializations.  Your last
example should work as you expect in this model, but you can also
write the simpler

template <class T> struct [[deprecated]] S { };
template <class T> struct S<const T> { }; // no warning


With this approach there would be no way to deprecate all of
a template's specializations) because it would always be
possible for a user to get around deprecation by defining
their own specialization, partial or explicit.

Yep.  And so he suggested that we might want to add a new way to write
attributes that do apply to the template name.

[[deprecated]] was introduced in part to make it possible for
C++ standard library implementers to add warnings for stuff
the committee has deprecated.  Most C++ deprecated features
are templates.  Declaring that [[deprecated]] isn't meant to
serve its purpose for templates and that some new form of
it is needed would make the attribute useless for standard
library implementers in the meantime, until that new form
is invented, as well as for all other template library
authors.  It would also make the current attribute useless
for existing code which almost surely intends it to apply
to all specializations of the deprecated template, implicit
or explicit.  There is no need to introduce new syntax.
What we have meets all the needs fine.  It can be used to
selectively deprecate a primary template, its partial
specializations, or its explicit specializations, or any
combination of the three.

Martin

Reply via email to