14
votes

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?

2
Apparently this wording has been around for a long time.Barry
@Barry Doing some Standard archeology, it appears to have been introduced in N0668 (March, 1995). So somewhere in between that and N1043 (December, 1996) that you cited, the example must have been elaborated. Unfortunately, not all working paper drafts are online. In particular, N0836 might be relevant.TemplateRex
@TemplateRex I think the first sentence of rule 4 says that in a type name that refers to a class template specialization the argument list can not use the template parameter list of the partial specialization, it shall match the template parameter list of the primary template. e.g. A<int,1> a2 is wrong. For the second sentance, I don't know the difference between it and rule 2.stackcpp
I would say that rule 3 is a clarification of rule 2. What it says is rule 2 applies not only to types, but to non-type template arguments as well. Rule 2 includes "non-type template arguments" implicitly, but rule 3 says it explicitly.zvone
@EugeneZavidovsky Maybe using simple-template-id as A and using template-name followed by implicitly template argument list as P, using rule 14.8.2.5 [temp.deduct.type]. e.g. A<int, int*, 1> a2; A<int, int*, 1> as A, A<T1, T2, I> as P.stackcpp

2 Answers

2
votes

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.

2
votes

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