Search code examples
c++templateslanguage-lawyerpartial-specialization

Which rules apply when an argument of partial specialization does not use any of its template parameters


n4567 [temp.class.spec.match]p2

A partial specialization matches a given actual template argument list if the template arguments of the partial specialization can be deduced from the actual template argument list (14.8.2).

template<class T, class U>
struct S{};

template<class U>
struct S<int, U>{};

S<char, int> s;

I know partial specialization S<int, U> do not match the actual template argument list char, int, and the second argument U can be deduced frome int accroding to 14.8.2.5.

But I don't know which rules in 14.8.2 apply for the first argument int.

14.8.2.5 [temp.deduct.type]p1

Template arguments can be deduced in several different contexts, but in each case a type that is specified in terms of template parameters (call it P) is compared with an actual type (call it A), and an attempt is made to find template argument values (a type for a type parameter, a value for a non-type parameter, or a template for a template parameter) that will make P, after substitution of the deduced values (call it the deduced A), compatible with A.

In my understanding the int in S<int, U> is not specified in terms of template parameters, so 14.8.2.5 does not apply.

I want to know which rules handle this case or you can correct me about 14.8.2.5


In other words: Intuitively, the partial specialization S<int, U> does not match char,int because char does not match int.

I want to know which rules determine char does not match int.


Solution

  • When considering what happens here:

    template<class T, class U> struct S{}; // (1)
    template<class U> struct S<int, U>{};  // (2)
    
    S<char, int> s; // (1) or (2)?
    

    To determine which specialization we use for s, we go into [temp.class.spec.match]:

    When a class template is used in a context that requires an instantiation of the class, it is necessary to determine whether the instantiation is to be generated using the primary template or one of the partial specializations. This is done by matching the template arguments of the class template specialization with the template argument lists of the partial specializations.

    In this case, we're matching <char, int> against <int, U>. What does matches mean?

    A partial specialization matches a given actual template argument list if the template arguments of the partial specialization can be deduced from the actual template argument list (14.8.2).

    Basically, we're deducing U to match int == char and U == int. Equivalently, we're looking at deducing U in:

    template <class U> void f(S<int, U> );
    f(S<char, int>{} );
    

    There is no such deduction.

    This leads us to:

    — If no matches are found, the instantiation is generated from the primary template.

    That leads us to (1).

    Let's take a more interesting case:

    S<int, char> s2;
    

    Now, <int, char> matches against <int, U>, because we can deduce U=char. Hence:

    — If exactly one matching specialization is found, the instantiation is generated from that specialization.

    That leads us to (2).