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 4:
template <class T, class U = double>
void f(T t = 0, U u = 0);
void g() {
f(1, 'c');
f(1);
f();
f<int>();
f<int,char>();
}
—
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
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]