3
votes

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.

2
What are you actually asking?Barry
Also, you seem to have pretty substantially changed the substance of the question since you got the answer...Barry

2 Answers

4
votes

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

No, 14.8.2.5 explains how to deduce the type, 14.3 deals with template arguments and the code you have posted fails 14.3p1:

14.3p1 ... The type and form of each template-argument specified in a template-id shall match the type and form specified for the corresponding parameter declared by the template in its template parameter-list.

template<class T, class U>
struct S<int, U> {}; 
// compiler error, template parameters not used in partial specialization

should be

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

So,

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

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

S<char, int> s; // uses #1
S<int, char> c; // uses #2 since S<int, U> matches more closely than S<T, U>

You mention that gcc rejected the template while clang accepted it. In my tests, VC++ and gcc gave a compiler error by default and did not compile the code at all, clang, however, gave a warning instead stating that this partial specialization will never be used and built the binary anyways. So in all instances it's giving the notice of non-conformity, it's just a matter of what compiler settings are on by default and how the compiler implementation handles non-conforming code.

Hope that can help.

0
votes

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).