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 Jason