17 Templates [temp]

17.9 Function template specializations [temp.fct.spec]

17.9.2 Template argument deduction [temp.deduct]

17.9.2.4 Deducing template arguments during partial ordering [temp.deduct.partial]

Template argument deduction is done by comparing certain types associated with the two function templates being compared.
Two sets of types are used to determine the partial ordering.
For each of the templates involved there is the original function type and the transformed function type.
[Note
:
The creation of the transformed type is described in [temp.func.order].
end note
]
The deduction process uses the transformed type as the argument template and the original type of the other template as the parameter template.
This process is done twice for each type involved in the partial ordering comparison: once using the transformed template-1 as the argument template and template-2 as the parameter template and again using the transformed template-2 as the argument template and template-1 as the parameter template.
The types used to determine the ordering depend on the context in which the partial ordering is done:
  • In the context of a function call, the types used are those function parameter types for which the function call has arguments.142
  • In the context of a call to a conversion function, the return types of the conversion function templates are used.
  • In other contexts the function template's function type is used.
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.
If a particular P contains no template-parameters that participate in template argument deduction, that P is not used to determine the ordering.
Before the partial ordering is done, certain transformations are performed on the types used for partial ordering:
  • If P is a reference type, P is replaced by the type referred to.
  • If A is a reference type, A is replaced by the type referred to.
If both P and A were reference types (before being replaced with the type referred to above), determine which of the two types (if any) is more cv-qualified than the other; otherwise the types are considered to be equally cv-qualified for partial ordering purposes.
The result of this determination will be used below.
Remove any top-level cv-qualifiers:
  • If P is a cv-qualified type, P is replaced by the cv-unqualified version of P.
  • If A is a cv-qualified type, A is replaced by the cv-unqualified version of A.
Using the resulting types P and A, the deduction is then done as described in [temp.deduct.type].
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.
Similarly, if A was transformed from a function parameter pack, it is compared with each remaining parameter type of the parameter template.
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
end example
]
If, for a given type, deduction succeeds in both directions (i.e., the types are identical after the transformations above) and both P and A were reference types (before being replaced with the type referred to above):
  • if the type from the argument template was an lvalue reference and the type from the parameter template was not, the parameter type is not considered to be at least as specialized as the argument type; otherwise,
  • if the type from the argument template is more cv-qualified than the type from the parameter template (as described above), the parameter type is not considered to be at least as specialized as the argument type.
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.
If, after considering the above, function template F is at least as specialized as function template G and vice-versa, and if G has a trailing parameter pack for which F does not have a corresponding parameter, and if F does not have a trailing parameter pack, then F is more specialized than G.
In most cases, all template parameters must have values in order for deduction to succeed, but for partial ordering purposes a template parameter may remain without a value provided it is not used in the types being used for partial ordering.
[Note
:
A template parameter used in a non-deduced context is considered used.
end note
]
[Example
:
template <class T> T f(int);            // #1
template <class T, class U> T f(U);     // #2
void g() {
  f<int>(1);                            // calls #1
}
end example
]
[Note
:
Partial ordering of function templates containing template parameter packs is independent of the number of deduced arguments for those template parameter packs.
end note
]
[Example
:
template<class ...> struct Tuple { };
template<class ... Types> void g(Tuple<Types ...>);                 // #1
template<class T1, class ... Types> void g(Tuple<T1, Types ...>);   // #2
template<class T1, class ... Types> void g(Tuple<T1, Types& ...>);  // #3

g(Tuple<>());                   // calls #1
g(Tuple<int, float>());         // calls #2
g(Tuple<int, float&>());        // calls #3
g(Tuple<int>());                // calls #3
end example
]
Default arguments are not considered to be arguments in this context; they only become arguments after a function has been selected.