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
. 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
are replaced with the corresponding deduced
or default argument values
. If the substitution results in an
invalid type, as described above, type deduction fails
. If the constraints are not satisfied, type deduction fails
. In the context of a function call, if type deduction has not yet failed, then
for those function parameters for which the function call has arguments,
each function parameter with a type that was non-dependent
before substitution of any explicitly-specified template arguments
is checked against its corresponding argument;
if the corresponding argument cannot be implicitly converted
to the parameter type, type deduction fails
. [
Note 3:
Overload resolution will check the other parameters, including
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
. —
end note]
If type deduction has not yet failed, then
all uses of template parameters in 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
. [
Example 5:
template <class T> struct Z {
typedef typename T::x xx;
};
template <class T> concept C = requires { typename T::A; };
template <C T> typename Z<T>::xx f(void *, T);
template <class T> void f(int, T);
struct A {} a;
struct ZZ {
template <class T, class = typename Z<T>::xx> operator T *();
operator int();
};
int main() {
ZZ zz;
f(1, a);
f(zz, 42);
}
—
end example]
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 deduction substitution loci
. The expressions include not only
constant expressions such as those that appear in array bounds or as constant
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
. If substitution into different declarations of the same function template would
cause template instantiations to occur in a different order or not at all,
the program is ill-formed; no diagnostic required
. [
Example 6:
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(.) { }
template <class T> typename T::X h(typename A<T>::X);
template <class T> auto h(typename A<T>::X) -> typename T::X;
template <class T> void h(.) { }
void x() {
f<int>(0);
g<int>(0);
h<int>(0);
}
—
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 in the same context using the substituted arguments
. [
Note 5:
If no diagnostic is required, the program is still ill-formed
. Access checking is done as part of the substitution process
. —
end note]
Invalid types and expressions can result in a deduction failure
only in the immediate context of the deduction substitution loci
. [
Note 6:
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]
When substituting into a
lambda-expression,
substitution into its body is not in the immediate context
. [
Note 7:
The intent is to avoid requiring implementations to deal with
substitution failure involving arbitrary statements
. [
Example 7:
template <class T>
auto f(T) -> decltype([]() { T::invalid; } ();
void f(.);
f(0);
template <class T, std::size_t = sizeof([]() { T::invalid; })>
void g(T);
void g(.);
g(0);
template <class T>
auto h(T) -> decltype([x = T::invalid]() { });
void h(.);
h(0);
template <class T>
auto i(T) -> decltype([]() -> typename T::invalid { });
void i(.);
i(0);
template <class T>
auto j(T t) -> decltype([](auto x) -> decltype(x.invalid) { } (t));
void j(.);
j(0);
—
end example]
—
end note]
[
Example 8:
struct X { };
struct Y {
Y(X) {}
};
template <class T> auto f(T t1, T t2) -> decltype(t1 + t2);
X f(Y, Y);
X x1, x2;
X x3 = f(x1, x2);
—
end example]
[
Note 8:
Type deduction can fail for the following reasons:
Attempting to instantiate a pack expansion containing multiple packs of differing lengths
.Attempting to create an array with an element type that is
void, a
function type, or a reference type, or attempting
to create an array with a size that is zero or negative. [
Example 9:
template <class T> int f(T[5]);
int I = f<int>(0);
int j = f<void>(0);
—
end example]
Attempting to use a type that is not a class or enumeration type in a qualified name
. [
Example 10:
template <class T> int f(typename T::B*);
int i = f<int>(0);
—
end example]
Attempting to use a type in a
nested-name-specifier of a
qualified-id when
that type does not contain the specified member, or
- the specified member is not a type where a type is required, or
- the specified member is not a template where a template is required, or
- the specified member is not a non-type, non-template where a non-type,
non-template is required.
[
Example 11:
template <int I> struct X { };
template <template <class T> class> struct Z { };
template <class T> void f(typename T::Y*) {}
template <class T> void g(X<T::N>*) {}
template <class T> void h(Z<T::TT>*) {}
struct A {};
struct B { int Y; };
struct C {
typedef int N;
};
struct D {
typedef int TT;
};
int main() {
f<A>(0);
f<B>(0);
g<C>(0);
h<D>(0);
}
—
end example]
Attempting to create a pointer to reference type
.Attempting to create a reference to
void.Attempting to create “pointer to member of
T” when
T is not a
class type
. [
Example 12:
template <class T> int f(int T::*);
int i = f<int>(0);
—
end example]
Attempting to give an invalid type to a constant template parameter
. [
Example 13:
template <class T, T> struct S {};
template <class T> int f(S<T, T{}>*);
class X {
int m;
};
int i0 = f<X>(0);
—
end example]
Attempting to perform an invalid conversion in either a template
argument expression, or an expression used in the function
declaration
. [
Example 14:
template <class T, T*> int f(int);
int i2 = f<int,1>(0);
—
end example]
Attempting to create a function type in which a parameter has a type
of
void, or in which the return type is a function type
or array type.Attempting to give to
an explicit object parameter of a lambda's function call operator
a type not permitted for such (
[expr.prim.lambda.closure])
. — end note]template <int> int f(int);
template <signed char> int f(int);
int i1 = f<1000>(0);
int i2 = f<1>(0);
— end example]
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 independently,
taking P′
as separate function template parameter types P′i
and the ith initializer element as the corresponding argument. In the
P′[N] case, if N is a constant 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 1:
template<class T> void f(std::initializer_list<T>);
f({1,2,3});
f({1,"asdf"});
template<class T> void g(T);
g({1,2,3});
template<class T, int N> void h(T const(&)[N]);
h({1,2,3});
template<class T> void j(T const(&)[3]);
j({42});
struct Aggr { int i; int j; };
template<int N> void k(Aggr const(&)[N]);
k({1,2,3});
k({1},{2},{3});
template<int M, int N> void m(int const(&)[M][N]);
m({1,2},{3,4});
template<class T, int N> void n(T const(&)[N], T);
n({1},{2},{3},Aggr();
template<typename T, int N> void o(T (* const (&)[N])(T)) { }
int f1(int);
int f4(int);
char f4(char);
o({ &f1, &f4 });
o({ &f1, static_cast<char(*)(char)>(&f4) });
—
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 pack is
never deduced
. [
Example 2:
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);
g(x, y, z);
g1(x, y, z);
g1<int, int>(x, y, z);
}
—
end example]
If
P
is not a reference type:
- If
A
is an array type, the pointer type produced by the array-to-pointer
standard conversion is used in place of
A
for type deduction;
otherwise,
- If
A
is a function type, the pointer type produced by the
function-to-pointer standard conversion is used in place
of
A
for type
deduction; otherwise,
- If
A
is a cv-qualified type, the top-level cv-qualifiers of
A's
type are ignored for type deduction.
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 3:
template<class T> int f(const T&);
int n1 = f(5);
const int i = 0;
int n2 = f(i);
template <class T> int g(volatile T&);
int n3 = g(i);
—
end example]
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 4:
template <class T> int f(T&& heisenreference);
template <class T> int g(const T&&);
int i;
int n1 = f(i);
int n2 = f(0);
int n3 = g(i);
template <class T> struct A {
template <class U>
A(T&&, U&&, int*);
A(T&&, int*);
};
template <class T> A(T&&, int*) -> A<T>;
int *ip;
A a{i, 0, ip};
A a0{0, 0, ip};
A a2{i, ip};
—
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. However, if there is a class
C that is
a (direct or indirect) base class of
D and
derived (directly or indirectly) from a class
B and
that would be a valid deduced
A,
the deduced
A cannot be
B or pointer to
B,
respectively
. [
Example 5:
template <typename. T> struct X;
template <> struct X<> {};
template <typename T, typename. Ts>
struct X<T, Ts..> : X<Ts..> {};
struct D : X<int> {};
struct E : X<>, X<int> {};
template <typename. T>
int f(const X<T..>&);
int x = f(D();
int z = f(E();
—
end example]
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 1:
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
whose associated constraints (
[temp.constr.constr]) are satisfied
. If all successful deductions yield the same deduced
A,
that deduced
A is the result of deduction;
otherwise, the parameter is treated as a non-deduced context
.[
Example 6:
template <class T> int f(T (*p)(T));
int g(int);
int g(char);
int i = f(g);
—
end example]
[
Example 7:
template <class T> int f(T, T (*p)(T));
int g(int);
char g(char);
int i = f(1, g);
—
end example]
[
Example 8:
template <class T> int f(T, T (*p)(T));
char g(char);
template <class T> T g(T);
int i = f(1, g);
—
end example]
[
Example 9:
template<bool B> struct X {
static void f(short) requires B;
static void f(short);
};
void test() {
auto x = &X<true>::f;
auto y = &X<false>::f;
}
—
end example]
Template arguments can be deduced from the type specified when taking
the address of an
overload set. If there is a target,
the function template's function type and the target type
are used as the types of
P
and
A,
and the deduction is done as
described in
[temp.deduct.type]. Otherwise, deduction is performed with empty sets of types
P and
A.A placeholder type (
[dcl.spec.auto]) 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
.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 subclause
.If
A
is not a reference type:
- If
P
is an array type, the pointer type produced by the
array-to-pointer standard conversion is used in place of
P
for type
deduction; otherwise,
- If
P
is a function type, the pointer type produced by the
function-to-pointer standard conversion is used in place of
P
for
type deduction; otherwise,
- If
P
is a cv-qualified type, the top-level cv-qualifiers of
P's
type are ignored for type deduction.
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, certain attributes of
A may be ignored:
If the original
A is a reference type,
any cv-qualifiers of
A
(i.e., the type referred to by the reference)
.If the original
A is
a function pointer or pointer-to-member-function type
with a potentially-throwing exception specification (
[except.spec]),
the exception specification
.Any cv-qualifiers in
A
that can be restored by a qualification conversion
.
These attributes are ignored only if type deduction would
otherwise fail
. If ignoring them allows more than one possible deduced
A,
the type deduction fails
.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
.
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
.In the context of a call to a conversion function, the return types of
the conversion function templates are 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.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 1:
template<class. Args> void f(Args.. args);
template<class T1, class. Args> void f(T1 a1, Args.. args);
template<class T1, class T2> void f(T1 a1, T2 a2);
f();
f(1, 2, 3);
f(1, 2);
—
end example]
If, for a given type, 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. 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 function parameter pack
for which
F does not have a corresponding parameter, and
if
F does not have a trailing function parameter pack,
then
F is more specialized than
G.In most cases,
deduction fails if not all template parameters have values,
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 2:
A template parameter used in a non-deduced context is considered used
. —
end note]
[
Example 2:
template <class T> T f(int);
template <class T, class U> T f(U);
void g() {
f<int>(1);
}
—
end example]
[
Note 3:
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 3:
template<class ..> struct Tuple { };
template<class .. Types> void g(Tuple<Types ..>);
template<class T1, class .. Types> void g(Tuple<T1, Types ..>);
template<class T1, class .. Types> void g(Tuple<T1, Types& ..>);
g(Tuple<>();
g(Tuple<int, float>();
g(Tuple<int, float&>();
g(Tuple<int>();
—
end example]