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

Reply via email to