17 Templates [temp]

17.8 Function template specializations [temp.fct.spec]

17.8.2 Template argument deduction [temp.deduct]

When a function template specialization is referenced, all of the template arguments shall have values. The values can be explicitly specified or, in some cases, be deduced from the use or obtained from default template-arguments. [Example:

void f(Array<dcomplex>& cv, Array<int>& ci) {
  sort(cv);                     // calls sort(Array<dcomplex>&)
  sort(ci);                     // calls sort(Array<int>&)
}

and

void g(double d) {
  int i = convert<int>(d);      // calls convert<int,double>(double)
  int c = convert<char>(d);     // calls convert<char,double>(double)
}

end example]

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. Specifically, the following steps are performed when evaluating an explicitly specified template argument list with respect to a given function template:

After this substitution is performed, the function parameter type adjustments described in [dcl.fct] are performed. [Example: A parameter type of “void (const int, int[5])” becomes “void(*)(int,int*)”. end example] [Note: A top-level qualifier in a function parameter declaration does not affect the function type but still affects the type of the function parameter variable within the function. end note] [Example:

template <class T> void f(T t);
template <class X> void g(const X x);
template <class Z> void h(Z, Z*);

int main() {
  // #1: function type is f(int), t is non const
  f<int>(1);

  // #2: function type is f(int), t is const
  f<const int>(1);

  // #3: function type is g(int), x is const
  g<int>(1);

  // #4: function type is g(int), x is const
  g<const int>(1);

  // #5: function type is h(int, const int*)
  h<const int>(1,0);
}

end example]

[Note: f<int>(1) and f<const int>(1) call distinct functions even though both of the functions called have the same function type. end note]

The resulting substituted and adjusted function type is used as the type of the function template for template argument deduction. If a template argument has not been deduced and its corresponding template parameter has a default argument, the template argument is determined by substituting the template arguments determined for preceding template parameters into the default argument. If the substitution results in an invalid type, as described above, type deduction fails. [Example:

template <class T, class U = double>
void f(T t = 0, U u = 0);

void g() {
  f(1, 'c');        // f<int,char>(1,'c')
  f(1);             // f<int,double>(1,0)
  f();              // error: T cannot be deduced
  f<int>();         // f<int,double>(0,0)
  f<int,char>();    // f<int,char>(0,0)
}

end example]

When all template arguments have been deduced or obtained from default template arguments, all uses of template parameters in the template parameter list of the template and the function type are replaced with the corresponding deduced or default argument values. If the substitution results in an invalid type, as described above, type deduction fails.

At certain points in the template argument deduction process it is necessary to take a function type that makes use of template parameters and replace those template parameters with the corresponding template arguments. This is done at the beginning of template argument deduction when any explicitly specified template arguments are substituted into the function type, and again at the end of template argument deduction when any template arguments that were deduced or obtained from default arguments are substituted.

The substitution occurs in all types and expressions that are used in the function type and in template parameter declarations. The expressions include not only constant expressions such as those that appear in array bounds or as nontype template arguments but also general expressions (i.e., non-constant expressions) inside sizeof, decltype, and other contexts that allow non-constant expressions. The substitution proceeds in lexical order and stops when a condition that causes deduction to fail is encountered. [Note: The equivalent substitution in exception specifications is done only when the noexcept-specifier is instantiated, at which point a program is ill-formed if the substitution results in an invalid type or expression. end note] [Example:

template <class T> struct A { using X = typename T::X; };
template <class T> typename T::X f(typename A<T>::X);
template <class T> void f(...) { }
template <class T> auto g(typename A<T>::X) -> typename T::X;
template <class T> void g(...) { }

void h() {
  f<int>(0);        // OK, substituting return type causes deduction to fail
  g<int>(0);        // error, substituting parameter type instantiates A<int>
}

end example]

If a substitution results in an invalid type or expression, type deduction fails. An invalid type or expression is one that would be ill-formed, with a diagnostic required, if written using the substituted arguments. [Note: If no diagnostic is required, the program is still ill-formed. Access checking is done as part of the substitution process. end note] Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure. [Note: The substitution into types and expressions can result in effects such as the instantiation of class template specializations and/or function template specializations, the generation of implicitly-defined functions, etc. Such effects are not in the “immediate context” and can result in the program being ill-formed.end note]

[Example:

struct X { };
struct Y {
  Y(X){}
};

template <class T> auto f(T t1, T t2) -> decltype(t1 + t2);     // #1
X f(Y, Y);          // #2

X x1, x2;
X x3 = f(x1, x2);   // deduction fails on #1 (cannot add X+X), calls #2

end example]

[Note: Type deduction may fail for the following reasons:

end note]

[Example: In the following example, assuming a signed char cannot represent the value 1000, a narrowing conversion would be required to convert the template-argument of type int to signed char, therefore substitution fails for the second template ([temp.arg.nontype]).

template <int> int f(int);
template <signed char> int f(int);
int i1 = f<1000>(0);            // OK
int i2 = f<1>(0);               // ambiguous; not narrowing

end example]

17.8.2.1 Deducing template arguments from a function call [temp.deduct.call]

Template argument deduction is done by comparing each function template parameter type (call it P) that contains template-parameters that participate in template argument deduction with the type of the corresponding argument of the call (call it A) as described below. If removing references and cv-qualifiers from P gives std​::​initializer_­list<P'> or P'[N] for some P' and N and the argument is a non-empty initializer list ([dcl.init.list]), then deduction is performed instead for each element of the initializer list, taking P' as a function template parameter type and the initializer element as its argument, and in the P'[N] case, if N is a non-type template parameter, N is deduced from the length of the initializer list. Otherwise, an initializer list argument causes the parameter to be considered a non-deduced context ([temp.deduct.type]). [Example:

template<class T> void f(std::initializer_list<T>);
f({1,2,3});                     // T deduced to int
f({1,"asdf"});                  // error: T deduced to both int and const char*

template<class T> void g(T);
g({1,2,3});                     // error: no argument deduced for T

template<class T, int N> void h(T const(&)[N]);
h({1,2,3});                     // T deduced to int, N deduced to 3

template<class T> void j(T const(&)[3]);
j({42});                        // T deduced to int, array bound not considered

struct Aggr { int i; int j; };
template<int N> void k(Aggr const(&)[N]);
k({1,2,3});                     // error: deduction fails, no conversion from int to Aggr
k({{1},{2},{3}});               // OK, N deduced to 3

template<int M, int N> void m(int const(&)[M][N]);
m({{1,2},{3,4}});               // M and N both deduced to 2

template<class T, int N> void n(T const(&)[N], T);
n({{1},{2},{3}},Aggr());        // OK, T is Aggr, N is 3

end example] For a function parameter pack that occurs at the end of the parameter-declaration-list, deduction is performed for each remaining argument of the call, taking the type P of the declarator-id of the function parameter pack as the corresponding function template parameter type. Each deduction deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack. When a function parameter pack appears in a non-deduced context ([temp.deduct.type]), the type of that parameter pack is never deduced. [Example:

template<class ... Types> void f(Types& ...);
template<class T1, class ... Types> void g(T1, Types ...);
template<class T1, class ... Types> void g1(Types ..., T1);

void h(int x, float& y) {
  const int z = x;
  f(x, y, z);                   // Types is deduced to int, float, const int
  g(x, y, z);                   // T1 is deduced to int; Types is deduced to float, int
  g1(x, y, z);                  // error: Types is not deduced
  g1<int, int, int>(x, y, z);   // OK, no deduction occurs
}

end example]

If P is not a reference type:

If P is a cv-qualified type, the top-level cv-qualifiers of P's type are ignored for type deduction. If P is a reference type, the type referred to by P is used for type deduction. [Example:

template<class T> int f(const T&);
int n1 = f(5);                  // calls f<int>(const int&)
const int i = 0;
int n2 = f(i);                  // calls f<int>(const int&)
template <class T> int g(volatile T&);
int n3 = g(i);                  // calls g<const int>(const volatile int&)

end example] A forwarding reference is an rvalue reference to a cv-unqualified template parameter that does not represent a template parameter of a class template (during class template argument deduction ([over.match.class.deduct])). If P is a forwarding reference and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction. [Example:

template <class T> int f(T&& heisenreference);
template <class T> int g(const T&&);
int i;
int n1 = f(i);                  // calls f<int&>(int&)
int n2 = f(0);                  // calls f<int>(int&&)
int n3 = g(i);                  // error: would call g<int>(const int&&), which
                                // would bind an rvalue reference to an lvalue

template <class T> struct A {
  template <class U>
    A(T&&, U&&, int*);          // #1: T&& is not a forwarding reference.
                                // U&& is a forwarding reference.
  A(T&&, int*);                 // #2
};

template <class T> A(T&&, int*) -> A<T>;    // #3: T&& is a forwarding reference.

int *ip;
A a{i, 0, ip};                  // error: cannot deduce from #1
A a0{0, 0, ip};                 // uses #1 to deduce A<int> and #1 to initialize
A a2{i, ip};                    // uses #3 to deduce A<int&> and #2 to initialize

end example]

In general, the deduction process attempts to find template argument values that will make the deduced A identical to A (after the type A is transformed as described above). However, there are three cases that allow a difference:

  • If the original P is a reference type, the deduced A (i.e., the type referred to by the reference) can be more cv-qualified than the transformed A.

  • The transformed A can be another pointer or pointer to member type that can be converted to the deduced A via a function pointer conversion and/or qualification conversion.

  • If P is a class and P has the form simple-template-id, then the transformed A can be a derived class of the deduced A. Likewise, if P is a pointer to a class of the form simple-template-id, the transformed A can be a pointer to a derived class pointed to by the deduced A.

These alternatives are considered only if type deduction would otherwise fail. If they yield more than one possible deduced A, the type deduction fails. [Note: If a template-parameter is not used in any of the function parameters of a function template, or is used only in a non-deduced context, its corresponding template-argument cannot be deduced from a function call and the template-argument must be explicitly specified. end note]

When P is a function type, function pointer type, or pointer to member function type:

  • If the argument is an overload set containing one or more function templates, the parameter is treated as a non-deduced context.

  • If the argument is an overload set (not containing function templates), trial argument deduction is attempted using each of the members of the set. If deduction succeeds for only one of the overload set members, that member is used as the argument value for the deduction. If deduction succeeds for more than one member of the overload set the parameter is treated as a non-deduced context.

[Example:

// Only one function of an overload set matches the call so the function parameter is a deduced context.
template <class T> int f(T (*p)(T));
int g(int);
int g(char);
int i = f(g);       // calls f(int (*)(int))

end example]

[Example:

// Ambiguous deduction causes the second function parameter to be a non-deduced context.
template <class T> int f(T, T (*p)(T));
int g(int);
char g(char);
int i = f(1, g);    // calls f(int, int (*)(int))

end example]

[Example:

// The overload set contains a template, causing the second function parameter to be a non-deduced context.
template <class T> int f(T, T (*p)(T));
char g(char);
template <class T> T g(T);
int i = f(1, g);    // calls f(int, int (*)(int))

end example]

If deduction succeeds for all parameters that contain template-parameters that participate in template argument deduction, and all template arguments are explicitly specified, deduced, or obtained from default template arguments, remaining parameters are then compared with the corresponding arguments. For each remaining parameter P with a type that was non-dependent before substitution of any explicitly-specified template arguments, if the corresponding argument A cannot be implicitly converted to P, deduction fails. [Note: Parameters with dependent types in which no template-parameters participate in template argument deduction, and parameters that became non-dependent due to substitution of explicitly-specified template arguments, will be checked during overload resolution. end note] [Example:

  template <class T> struct Z {
    typedef typename T::x xx;
  };
  template <class T> typename Z<T>::xx f(void *, T);    // #1
  template <class T> void f(int, T);                    // #2
  struct A {} a;
  int main() {
    f(1, a);        // OK, deduction fails for #1 because there is no conversion from int to void*
  }

end example]

17.8.2.2 Deducing template arguments taking the address of a function template [temp.deduct.funcaddr]

Template arguments can be deduced from the type specified when taking the address of an overloaded function. The function template's function type and the specified type are used as the types of P and A, and the deduction is done as described in [temp.deduct.type].

A placeholder type in the return type of a function template is a non-deduced context. If template argument deduction succeeds for such a function, the return type is determined from instantiation of the function body.

17.8.2.3 Deducing conversion function template arguments [temp.deduct.conv]

Template argument deduction is done by comparing the return type of the conversion function template (call it P) with the type that is required as the result of the conversion (call it A; see [dcl.init], [over.match.conv], and [over.match.ref] for the determination of that type) as described in [temp.deduct.type].

If P is a reference type, the type referred to by P is used in place of P for type deduction and for any further references to or transformations of P in the remainder of this section.

If A is not a reference type:

If A is a cv-qualified type, the top-level cv-qualifiers of A's type are ignored for type deduction. If A is a reference type, the type referred to by A is used for type deduction.

In general, the deduction process attempts to find template argument values that will make the deduced A identical to A. However, there are four cases that allow a difference:

  • If the original A is a reference type, A can be more cv-qualified than the deduced A (i.e., the type referred to by the reference)

  • If the original A is a function pointer type, A can be “pointer to function” even if the deduced A is “pointer to noexcept function”.

  • If the original A is a pointer to member function type, A can be “pointer to member of type function” even if the deduced A is “pointer to member of type noexcept function”.

  • The deduced A can be another pointer or pointer to member type that can be converted to A via a qualification conversion.

These alternatives are considered only if type deduction would otherwise fail. If they yield more than one possible deduced A, the type deduction fails.

When the deduction process requires a qualification conversion for a pointer or pointer to member type as described above, the following process is used to determine the deduced template argument values:

If A is a type cv1,0 “pointer to cv1,n1 “pointer to” cv1,n T1 and P is a type cv2,0 “pointer to cv2,n1 “pointer to” cv2,n T2, then the cv-unqualified T1 and T2 are used as the types of A and P respectively for type deduction. [Example:

struct A {
  template <class T> operator T***();
};
A a;
const int * const * const * p1 = a;     // T is deduced as int, not const int

end example]

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

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

17.8.2.5 Deducing template arguments from a type [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.

In some cases, the deduction is done using a single set of types P and A, in other cases, there will be a set of corresponding types P and A. Type deduction is done independently for each P/A pair, and the deduced template argument values are then combined. If type deduction cannot be done for any P/A pair, or if for any pair the deduction leads to more than one possible set of deduced values, or if different pairs yield different deduced values, or if any template argument remains neither deduced nor explicitly specified, template argument deduction fails. The type of a type parameter is only deduced from an array bound if it is not otherwise deduced.

A given type P can be composed from a number of other types, templates, and non-type values:

  • A function type includes the types of each of the function parameters and the return type.

  • A pointer to member type includes the type of the class object pointed to and the type of the member pointed to.

  • A type that is a specialization of a class template (e.g., A<int>) includes the types, templates, and non-type values referenced by the template argument list of the specialization.

  • An array type includes the array element type and the value of the array bound.

In most cases, the types, templates, and non-type values that are used to compose P participate in template argument deduction. That is, they may be used to determine the value of a template argument, and the value so determined must be consistent with the values determined elsewhere. In certain contexts, however, the value does not participate in type deduction, but instead uses the values of template arguments that were either deduced elsewhere or explicitly specified. If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails. [Note: Under [temp.deduct.call] and [temp.deduct.partial], if P contains no template-parameters that appear in deduced contexts, no deduction is done, so P and A need not have the same form. end note]

The non-deduced contexts are:

  • The nested-name-specifier of a type that was specified using a qualified-id.

  • The expression of a decltype-specifier.

  • A non-type template argument or an array bound in which a subexpression references a template parameter.

  • A template parameter used in the parameter type of a function parameter that has a default argument that is being used in the call for which argument deduction is being done.

  • A function parameter for which argument deduction cannot be done because the associated function argument is a function, or a set of overloaded functions ([over.over]), and one or more of the following apply:

    • more than one function matches the function parameter type (resulting in an ambiguous deduction), or

    • no function matches the function parameter type, or

    • the set of functions supplied as an argument contains one or more function templates.

  • A function parameter for which the associated argument is an initializer list ([dcl.init.list]) but the parameter does not have a type for which deduction from an initializer list is specified ([temp.deduct.call]). [Example:

    template<class T> void g(T);
    g({1,2,3});                 // error: no argument deduced for T
    

    end example]

  • A function parameter pack that does not occur at the end of the parameter-declaration-list.

When a type name is specified in a way that includes a non-deduced context, all of the types that comprise that type name are also non-deduced. However, a compound type can include both deduced and non-deduced types. [Example: If a type is specified as A<T>​::​B<T2>, both T and T2 are non-deduced. Likewise, if a type is specified as A<I+J>​::​X<T>, I, J, and T are non-deduced. If a type is specified as void f(typename A<T>​::​B, A<T>), the T in A<T>​::​B is non-deduced but the T in A<T> is deduced. end example]

[Example: Here is an example in which different parameter/argument pairs produce inconsistent template argument deductions:

template<class T> void f(T x, T y) { /* ... */ }
struct A { /* ... */ };
struct B : A { /* ... */ };
void g(A a, B b) {
  f(a,b);           // error: T could be A or B
  f(b,a);           // error: T could be A or B
  f(a,a);           // OK: T is A
  f(b,b);           // OK: T is B
}

Here is an example where two template arguments are deduced from a single function parameter/argument pair. This can lead to conflicts that cause type deduction to fail:

template <class T, class U> void f(  T (*)( T, U, U )  );

int g1( int, float, float);
char g2( int, float, float);
int g3( int, char, float);

void r() {
  f(g1);            // OK: T is int and U is float
  f(g2);            // error: T could be char or int
  f(g3);            // error: U could be char or float
}

Here is an example where a qualification conversion applies between the argument type on the function call and the deduced template argument type:

template<class T> void f(const T*) { }
int* p;
void s() {
  f(p);             // f(const int*)
}

Here is an example where the template argument is used to instantiate a derived class type of the corresponding function parameter type:

template <class T> struct B { };
template <class T> struct D : public B<T> {};
struct D2 : public B<int> {};
template <class T> void f(B<T>&){}
void t() {
  D<int> d;
  D2     d2;
  f(d);             // calls f(B<int>&)
  f(d2);            // calls f(B<int>&)
}

end example]

A template type argument T, a template template argument TT or a template non-type argument i can be deduced if P and A have one of the following forms:

T
cv-list T
T*
T&
T&&
T[integer-constant]
template-name<T>  (where template-name refers to a class template)
type(T)
T()
T(T)
T type::*
type T::*
T T::*
T (type::*)()
type (T::*)()
type (type::*)(T)
type (T::*)(T)
T (type::*)(T)
T (T::*)()
T (T::*)(T)
type[i]
template-name<i>  (where template-name refers to a class template)
TT<T>
TT<i>
TT<>

where (T) represents a parameter-type-list ([dcl.fct]) where at least one parameter type contains a T, and () represents a parameter-type-list where no parameter type contains a T. Similarly, <T> represents template argument lists where at least one argument contains a T, <i> represents template argument lists where at least one argument contains an i and <> represents template argument lists where no argument contains a T or an i.

If P has a form that contains <T> or <i>, then each argument Pi of the respective template argument list of P is compared with the corresponding argument Ai of the corresponding template argument list of A. If the template argument list of P contains a pack expansion that is not the last template argument, the entire template argument list is a non-deduced context. If Pi is a pack expansion, then the pattern of Pi is compared with each remaining argument in the template argument list of A. Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by Pi. During partial ordering, if Ai was originally a pack expansion:

  • if P does not contain a template argument corresponding to Ai then Ai is ignored;

  • otherwise, if Pi is not a pack expansion, template argument deduction fails.

[Example:

template<class T1, class... Z> class S;                               // #1
template<class T1, class... Z> class S<T1, const Z&...> { };          // #2
template<class T1, class T2>   class S<T1, const T2&> { };            // #3
S<int, const int&> s;         // both #2 and #3 match; #3 is more specialized

template<class T, class... U>            struct A { };                // #1
template<class T1, class T2, class... U> struct A<T1, T2*, U...> { }; // #2
template<class T1, class T2>             struct A<T1, T2> { };        // #3
template struct A<int, int*>; // selects #2

end example]

Similarly, if P has a form that contains (T), then each parameter type Pi of the respective parameter-type-list ([dcl.fct]) of P is compared with the corresponding parameter type Ai of the corresponding parameter-type-list of A. If P and A are function types that originated from deduction when taking the address of a function template ([temp.deduct.funcaddr]) or when deducing template arguments from a function declaration ([temp.deduct.decl]) and Pi and Ai are parameters of the top-level parameter-type-list of P and A, respectively, Pi is adjusted if it is a forwarding reference ([temp.deduct.call]) and Ai is an lvalue reference, in which case the type of Pi is changed to be the template parameter type (i.e., T&& is changed to simply T). [Note: As a result, when Pi is T&& and Ai is X&, the adjusted Pi will be T, causing T to be deduced as X&. end note] [Example:

template <class T> void f(T&&);
template <> void f(int&) { }    // #1
template <> void f(int&&) { }   // #2
void g(int i) {
  f(i);                         // calls f<int&>(int&), i.e., #1
  f(0);                         // calls f<int>(int&&), i.e., #2
}

end example]

If the parameter-declaration corresponding to Pi is a function parameter pack, then the type of its declarator-id is compared with each remaining parameter type in the parameter-type-list of A. Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack. During partial ordering, if Ai was originally a function parameter pack:

  • if P does not contain a function parameter type corresponding to Ai then Ai is ignored;

  • otherwise, if Pi is not a function parameter pack, template argument deduction fails.

[Example:

template<class T, class... U> void f(T*, U...) { }  // #1
template<class T>             void f(T) { }         // #2
template void f(int*);                              // selects #1

end example]

These forms can be used in the same way as T is for further composition of types. [Example:

X<int> (*)(char[6])

is of the form

template-name<T> (*)(type[i])

which is a variant of

type (*)(T)

where type is X<int> and T is char[6]. end example]

Template arguments cannot be deduced from function arguments involving constructs other than the ones specified above.

When the value of the argument corresponding to a non-type template parameter P that is declared with a dependent type is deduced from an expression, the template parameters in the type of P are deduced from the type of the value. [Example:

template<long n> struct A { };

template<typename T> struct C;
template<typename T, T n> struct C<A<n>> {
  using Q = T;
};

using R = long;
using R = C<A<2>>::Q;           // OK; T was deduced to long from the
                                // template argument value in the type A<2>

end example] The type of N in the type T[N] is std​::​size_­t. [Example:

template<typename T> struct S;
template<typename T, T n> struct S<int[n]> {
  using Q = T;
};

using V = decltype(sizeof 0);
using V = S<int[42]>::Q;        // OK; T was deduced to std​::​size_­t from the type int[42]

end example]

[Example:

template<class T, T i> void f(int (&a)[i]);
int v[10];
void g() {
  f(v);                         // OK: T is std​::​size_­t
}

end example]

[Note: Except for reference and pointer types, a major array bound is not part of a function parameter type and cannot be deduced from an argument:

template<int i> void f1(int a[10][i]);
template<int i> void f2(int a[i][20]);
template<int i> void f3(int (&a)[i][20]);

void g() {
  int v[10][20];
  f1(v);                        // OK: i deduced to be 20
  f1<20>(v);                    // OK
  f2(v);                        // error: cannot deduce template-argument i
  f2<10>(v);                    // OK
  f3(v);                        // OK: i deduced to be 10
}

end note]

[Note: If, in the declaration of a function template with a non-type template parameter, the non-type template parameter is used in a subexpression in the function parameter list, the expression is a non-deduced context as specified above. [Example:

template <int i> class A { /* ... */ };
template <int i> void g(A<i+1>);
template <int i> void f(A<i>, A<i+1>);
void k() {
  A<1> a1;
  A<2> a2;
  g(a1);                        // error: deduction fails for expression i+1
  g<0>(a1);                     // OK
  f(a1, a2);                    // OK
}

end example] end note]

[Note: Template parameters do not participate in template argument deduction if they are used only in non-deduced contexts. For example,

template<int i, typename T>
T deduce(typename A<T>::X x,    // T is not deduced here
         T t,                   // but T is deduced here
         typename B<i>::Y y);   // i is not deduced here
A<int> a;
B<77>  b;

int    x = deduce<77>(a.xm, 62, b.ym);
// T is deduced to be int, a.xm must be convertible to A<int>​::​X
// i is explicitly specified to be 77, b.ym must be convertible to B<77>​::​Y

end note]

If P has a form that contains <i>, and if the type of i differs from the type of the corresponding template parameter of the template named by the enclosing simple-template-id, deduction fails. If P has a form that contains [i], and if the type of i is not an integral type, deduction fails.142 [Example:

template<int i> class A { /* ... */ };
template<short s> void f(A<s>);
void k1() {
  A<1> a;
  f(a);             // error: deduction fails for conversion from int to short
  f<1>(a);          // OK
}

template<const short cs> class B { };
template<short s> void g(B<s>);
void k2() {
  B<1> b;
  g(b);             // OK: cv-qualifiers are ignored on template parameter types
}

end example]

A template-argument can be deduced from a function, pointer to function, or pointer to member function type.

[Example:

template<class T> void f(void(*)(T,int));
template<class T> void foo(T,int);
void g(int,int);
void g(char,int);

void h(int,int,int);
void h(char,int);
int m() {
  f(&g);            // error: ambiguous
  f(&h);            // OK: void h(char,int) is a unique match
  f(&foo);          // error: type deduction fails because foo is a template
}

end example]

A template type-parameter cannot be deduced from the type of a function default argument. [Example:

template <class T> void f(T = 5, T = 7);
void g() {
  f(1);             // OK: call f<int>(1,7)
  f();              // error: cannot deduce T
  f<int>();         // OK: call f<int>(5,7)
}

end example]

The template-argument corresponding to a template template-parameter is deduced from the type of the template-argument of a class template specialization used in the argument list of a function call. [Example:

template <template <class T> class X> struct A { };
template <template <class T> class X> void f(A<X>) { }
template<class T> struct B { };
A<B> ab;
f(ab);              // calls f(A<B>)

end example]

[Note: Template argument deduction involving parameter packs ([temp.variadic]) can deduce zero or more arguments for each parameter pack. end note] [Example:

template<class> struct X { };
template<class R, class ... ArgTypes> struct X<R(int, ArgTypes ...)> { };
template<class ... Types> struct Y { };
template<class T, class ... Types> struct Y<T, Types& ...> { };

template<class ... Types> int f(void (*)(Types ...));
void g(int, float);

X<int> x1;                      // uses primary template
X<int(int, float, double)> x2;  // uses partial specialization; ArgTypes contains float, double
X<int(float, int)> x3;          // uses primary template
Y<> y1;                         // use primary template; Types is empty
Y<int&, float&, double&> y2;    // uses partial specialization; T is int&, Types contains float, double
Y<int, float, double> y3;       // uses primary template; Types contains int, float, double
int fv = f(g);                  // OK; Types contains int, float

end example]

Although the template-argument corresponding to a template-parameter of type bool may be deduced from an array bound, the resulting value will always be true because the array bound will be nonzero.

17.8.2.6 Deducing template arguments from a function declaration [temp.deduct.decl]

In a declaration whose declarator-id refers to a specialization of a function template, template argument deduction is performed to identify the specialization to which the declaration refers. Specifically, this is done for explicit instantiations, explicit specializations, and certain friend declarations. This is also done to determine whether a deallocation function template specialization matches a placement operator new ([basic.stc.dynamic.deallocation], [expr.new]). In all these cases, P is the type of the function template being considered as a potential match and A is either the function type from the declaration or the type of the deallocation function that would match the placement operator new as described in [expr.new]. The deduction is done as described in [temp.deduct.type].

If, for the set of function templates so considered, there is either no match or more than one match after partial ordering has been considered ([temp.func.order]), deduction fails and, in the declaration cases, the program is ill-formed.