stackcpp
stackcpp

Reputation: 1285

Matching of class template partial specializations

N4527 14.5.5.1[temp.class.spec.match]

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

template<class T1, class T2, int I> class A             { }; // #1
template<class T, int I>            class A<T, T*, I>   { }; // #2
template<class T1, class T2, int I> class A<T1*, T2, I> { }; // #3
template<class T>                   class A<int, T*, 5> { }; // #4
template<class T1, class T2, int I> class A<T1, T2*, I> { }; // #5

A<int, int, 1>   a1; // uses #1
A<int, int*, 1>  a2; // uses #2, T is int, I is 1
A<int, char*, 5> a3; // uses #4, T is char
A<int, char*, 1> a4; // uses #5, T1 is int, T2 is char, I is 1
A<int*, int*, 2> a5; // ambiguous: matches #3 and #5

3 A non-type template argument can also be deduced from the value of an actual template argument of a non-type parameter of the primary template. [ Example: the declaration of a2 above. —end example ]

4 In a type name that refers to a class template specialization, (e.g., A<int, int, 1>) the argument list shall match the template parameter list of the primary template. The template arguments of a specialization are deduced from the arguments of the primary template.

In rule3, the example shows I is deduced from the third actual template argument 1, this is what the rule2 says. So as the second sentence of rule4, I think it is repeating what rule2 says.

What are the differences between them(rule2, rule3 and rule4)?

Another words, we already have rule2, what are the intents(meaning) of rule3 and the second sentence of rule4, why they are here?

Upvotes: 14

Views: 1152

Answers (2)

Eugene Zavidovsky
Eugene Zavidovsky

Reputation: 478

I think, the rule [temp.class.spec.match] 14.5.5.1\2 may be rewritten like this without changing its purport:

[temp.class.spec.match] 14.5.5.1\2 (modified)

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 according to 14.8.2.5, where P is the argument list of the partial specialization from its simple-template-id and A is the actual template argument list.

The rule [temp.deduct.type] 14.8.2.5\1 defines the process for deducing from types (I am not sure about templates though) only, so there is a need for the rule [temp.class.spec.match] 14.5.5.1\3, which adds to 14.5.5.1\2 cases with non-type template parameters of the primary template, which are not (partially) specialized in the partial specialization.

The rule [temp.class.spec.match] 14.5.5.1\4, as you noted in the comments above (1, 2), is just the clarification, that template arguments in the template-id corresponds to template parameters of the primary template, not its partial specializations, which may have different template-parameter-list s. Moreover, the second sentence of the rule most likely claims that the implicit template argument list of the primary template (14.5.5\4) is deduced (!) according to [temp.deduct.type] 14.8.2.5\9 from the actual argument list. So the phrases "implicit template argument list of the primary template" and "the template arguments of a specialization" imply one selfsame thing, and the phrases "the arguments of the primary template" and "the actual template argument list" imply another selfsame thing... But it also may be that authors intended to write this:

[temp.class.spec.match] 14.5.5.1\4 (modified)

In a type name that refers to a class template specialization the argument list shall match the template parameter list of the primary template. The template arguments of a partial specialization are deduced from the arguments of the primary template.

Whatever...

Upvotes: 2

zackery.fix
zackery.fix

Reputation: 1816

The differences between rule two and rule four is the second and third template parameter. In example three:

A<int, char*, 5> a3; // uses #4, T is char

It uses rule4 because the third parameter clearly specializes to a const int 5, and the second parameter is specialized to accept a pointer type; its a unique specialization of class A.

I look at each specialization as a specific species of the class, and each specie has a unique signature (similar to overloading functions). The compiler is going to choose the specialization that matches the signature being used.

Rule three only makes sense without rule five, so after removing rule five, the intent of rule three would be to specialize any typenames of class A that: a) do not use a const int 5 for the third parameter b) do not use a pointer or as the second parameter c) do not use a `int` in the second parameter.

Since non of your examples use the unique signature of rule3, non of them use rule3 (given we remove the ambiguous rule5).

This could be better to understand if you only look at the template<...> scheme of the specialization, and not the signature <> of the specialization. The compiler is looking at the template scheme before looking at the specialization. Also, all other specializations of class A define the rules for any new specialization. To understand the intentions of a specialization, you have to understand the intentions of all the other specializations, and intention of a specialization is not defined by the standard, its defined by whoever implemented the specialization; ie. implementation details of the specialization truly define the intent.

Upvotes: 2

Related Questions