N4527 14.8.2.4 [temp.deduct.partial]
3 The types used to determine the ordering depend on the context in which the partial ordering is done:
(3.1) — In the context of a function call, the types used are those function parameter types for which the function call has arguments.
(3.2) — In the context of a call to a conversion function, the return types of the conversion function templates are used.
(3.3) — In other contexts (14.5.6.2) the function template’s function type is used.
4 Each type nominated above from the parameter template and the corresponding type from the argument
template are used as the types of P
and A
.
8 If A
was transformed from a function parameter pack and P
is not a parameter pack, type deduction fails.
Otherwise, using the resulting types P
and A
, the deduction is then done as described in 14.8.2.5. If P
is a function parameter pack, the type A
of each remaining parameter type of the argument template is
compared with the type P
of the declarator-id of the function parameter pack. Each comparison deduces
template arguments for subsequent positions in the template parameter packs expanded by the function
parameter pack. If deduction succeeds for a given type, the type from the argument template is considered
to be at least as specialized as the type from the parameter template.
[ Example:
template<class... Args> void f(Args... args); // #1
template<class T1, class... Args> void f(T1 a1, Args... args); // #2
template<class T1, class T2> void f(T1 a1, T2 a2); // #3
f(); // calls #1
f(1, 2, 3); // calls #2
f(1, 2); // calls #3; non-variadic template #3 is more
// specialized than the variadic templates #1 and #2
Why f(1, 2, 3);
calls #2?
I need more details including:
1 Which context is it?
2 What are the transformed froms?
e.g. the transformed from of #1 is void (U)
, void (U...)
or other form?(U
means an unique type)
14.5.6.2 [temp.func.order]/p3
To produce the transformed template, for each type, non-type, or template template parameter (including
template parameter packs (14.5.3) thereof) synthesize a unique type, value, or class template respectively
and substitute it for each occurrence of that parameter in the function type of the template.
3 What are the types of P
and A
used in deduction? e.g
template <class T> void f(T);
int a = 1;
f(a);//P = T, A = int
Why f(1, 2, 3);
calls #2?
There's a lot of questions in your question (one question per question please!), so I will stick to that one. First, we perform template deduction. #3 fails, but #1 and #2 succeed:
template<class... Args>
void f(Args... args); // #1, with Args = {int, int, int}
template<class T1, class... Args>
void f(T1 a1, Args... args); // #2, with T1 = int, Args = {int, int}
Both functions take three int
s by value, so all the normal tiebreakers in overload resolution fail to resolve the ambiguity. So we get to the very last one:
Given these definitions, a viable function F1
is defined to be a better function than another viable function F2
if for all arguments i
, ICSi(F1
) is not a worse conversion sequence than ICSi(F2
), and then
— [...]
— F1
and F2
are function template specializations, and the function template for F1
is more specialized
than the template for F2
according to the partial ordering rules described in 14.5.6.2.
The rules are:
Step 1: synthesize types [temp.func.order]:
To produce the transformed template, for each type, non-type, or template template parameter (including
template parameter packs (14.5.3) thereof) synthesize a unique type, value, or class template respectively
and substitute it for each occurrence of that parameter in the function type of the template.
So we have:
void f(Pack1... args); // #1
void f(U2 a1, Pack2... args); // #2
Step 2: perform deduction as described in [temp.deduct.partial]. The context we're in is a function call, so we use the types for which the function call has arguments.
First, we try to deduce #2 from #1. That is, we try to match (T1, Args...
) against (Pack1...)
. The first part is then P = T1, A = Pack1...
. We have:
If A was transformed from a function parameter pack and P is not a parameter pack, type deduction fails.
So deducing #2 from #1 fails, so the argument Args...
is not at least as specialized as T1, Args...
.
Next, we try to deduce #1 from #2. That is, we try to match (Args...)
against (U2, Pack2...)
. That succeeds, so T1, Args...
is at least as specialized as Args...
.
Since #2 is at least as specialized as #1 and #1 is not at least as specialized as #2, we can say that #2 is more specialized:
Function template F
is at least as specialized as function template G
if, for each pair of types used to
determine the ordering, the type from F
is at least as specialized as the type from G
. F
is more specialized
than G
if F
is at least as specialized as G
and G
is not at least as specialized as F
.
The more specialized template is preferred, so we call #2.