2
votes

N4567 14.5.5.1 [temp.class.spec.match]p4

In a type name that refers to a class template specialization, (e.g., A) 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.

template<class T1, class T2, int I> class A             { }; // #1
template<class T, int I>            class A<T, T*, I>   { }; // #2
A<int, int, 1>   a1; // uses #1

Does this "deduced" mean 14.8.2.5 [temp.deduct.type]?

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.

If it does, what is the P and A?

The template arguments of a specialization means the actual template arguments of the primary template int, int, 1 or the template arguments of the partial specialization T, T*, I or other?

the arguments of the primary template means the actual template arguments of the primary template int, int, 1 or the implicitly template arguments of the primary template T1, T2, I or other?

What does this sentence mean?


UPDATE:

It looks @Igor Tandetnik and @R Sahu have different answers, I need more help.

2
A would be int, int and 1. P would be T, T* and I (as usual, the deduction for each argument is performed separately). In this case, the deduction fails for the second argument (T in T* can't be deduced from int), and so the primary template, rather than specialization, is instantiated.Igor Tandetnik
@IgorTandetnik So this sentence is just repeating 14.5.5.1/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?stackcpp
Not quite repeating. p2 says "can be deduced", so it just asks a question whose answer is "true" or "false". p4 says "are deduced", so it envisions a process that actually assigns values to those parameters. But yes, they are closely related.Igor Tandetnik
@stackcpp Regarding the R Sahu's answer, I have written a comment there. Regarding your question what the phrase "the template arguments of a specialization" implies and what the phrase "the arguments of the primary template" does, my answer is here.Eugene Zavidovsky

2 Answers

0
votes

First, it should be noted that these rules are meant more as if you were implementing a C++ parser (like a compiler), so if one of these specific rules is not met, then the program should be non-conforming (and an error generated). So in the paragraph you mention:

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.

Think of it to mean that if the source being parsed does not meet the restrictions of these paragraphs, it is non-conforming so generate an error.

Directly answering the main question of:

What does “The template arguments of a specialization are deduced from the arguments of the primary template” mean?

14.5.5 is about template partial specializations, 14.5.5.1 is specifically about matching the partial specialization and paragraph 4 (where the sentence is from) is just saying that the template arguments passed to a template must match those of a specialized template.

The last sentence of paragraph 4 (the one in question), is simply saying that the arguments passed in are deduced based on the main template.

It gives an example of A<int, int, 1> when talking about this paragraph, and it's referring to the other template specializations in the example it gives in 14.5.5.1 (separated for easier reading):

// #1 (main template)
template<class T1, class T2, int I>
class A
{ };

// #2
template<class T, int I>
class A<T, T*, I>
{ };

// #3
template<class T1, class T2, int I>
class A<T1*, T2, I>
{ };

// #4
template<class T>
class A<int, T*, 5>
{ };

// #5
template<class T1, class T2, int I> 
class A<T1, T2*, I>
{ };

So, given the following code:

A<int, int, 1> a1;
A<int, char*, 5> a2;
A<int, int, 2.0f> a3;
A<int*> a4;

a1 will compile fine, and template #1 will be used (since it matches exactly to that specialization), so template #1 will compile to the following:

template<
    class T1 = int,
    class T2 = int,
    int I = 1>
class A
{ };

a2 will compile fine as well and template #4 will be used as such:

template<
    class T = char>
class A<int, T*, 5>
{ };

a3, however, doesn't match any of the template specializations, and a conforming compiler will generate an error when compiling a3 since the types of int do not match type of float; that is, a3 would generate a template of the following type:

template<
    class T1 = int,
    class T2 = int,
    int I = 2.0f>
class A
{ };

And thus should generate an error since an int is not a float. Lastly, a4 will not compile as well since it only has 1 template argument and all template specializations for A take 3 arguments.

Continuing with your questions:

Does this "deduced" mean 14.8.2.5 [temp.deduct.type]?

Yes and no, deduced is referring to the whole of 14.8.2 Template argument deduction, where paragraph 2 states:

When an explicit template argument list is specified, the template arguments must be compatible with the template parameter list and must result in a valid function type as described below; otherwise type deduction fails.

Where described below has additional points not posted here for brevities sake.

However, 14.8.2.5 specifically refers to how to deduce the type in a conforming way, and if a template specialization can't be deduced this way then it should fail (i.e. compiler should generate an error).

If it does, what is the P and A?

The P and A in this sentence are just place holder values to use for the rest of the text.

Specifically what it's trying to get at is that P is to mean a template argument and A is to mean an actual type that can be used, like an int or std::string or a user defined type like a class, struct or typedef, or function.

Take this code for example:

#1
template < class T >
struct A {
    T val;
};

#2
template<>
struct A<double>
{
    double val;
};

int main() {
    A<int> a1; // uses #1
    A<double> a2; // uses #2
    A<someVal> a3; // uses #1 but generate error since `someVal` is invalid type
}

In this code, the P val would be the template argument of class T and the A val would be int for a1, double for a2 and someVal for a3. A conforming compiler should generate an error for a3 since there is not type that will make P, after substitution of the deduced values (call it the deduced A), compatible with A, since someVal is not a valid type.

Using the example A<int, int, 2.0f> a3; from above, since there were no templates defined that could take the last argument (the 2.0f), the P val here is int and the A val is 2.0f; since 2.0f is not an int, this template deduction fails and an error is generated.

You also asked:

The template arguments of a specialization means the actual template arguments of the primary template int, int, 1 or the template arguments of the partial specialization T, T*, I or other?

The template arguments of a specialization is referring to the arguments passed into the template, so in A<int, int, 1> the template arguments of this specializations are int, int and 1.

the arguments of the primary template means the actual template arguments of the primary template int, int, 1 or the implicitly template arguments of the primary template T1, T2, I or other?

the arguments of the primary template are referring to the primary template itself, so in the A example above, the primary template would be template<class T1, class T2, int I> class A { };

I hope that can help.

-1
votes

Given your template and its specialization, using:

A<int, int*, 1>   a2;

will use the specialization.

For this usage,

The template parameters of the primary template are int, int*, and 1.
The template parameters of the template specialization are int, and 1.

The arguments of the specialization, int and 1 are deduced from the arguments of the primary template, int, int*, and 1.

In this case,

P is int, int*, and 1.
A is the specialization.

I think that's the answer you are looking for.