On Tue, Feb 13, 2018 at 5:20 PM, Martin Sebor <mse...@gmail.com> wrote: > 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.
This seems like a discussion to have on the reflector. Jason