1463 lines
71 KiB
Markdown
1463 lines
71 KiB
Markdown
[temp.deduct]
|
||
|
||
# 13 Templates [[temp]](./#temp)
|
||
|
||
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct)
|
||
|
||
### 13.10.3 Template argument deduction [temp.deduct]
|
||
|
||
#### [13.10.3.1](#general) General [[temp.deduct.general]](temp.deduct.general)
|
||
|
||
[1](#general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7733)
|
||
|
||
When a
|
||
function template
|
||
specialization is referenced, all of the
|
||
template arguments shall have values[.](#general-1.sentence-1)
|
||
|
||
The values can be
|
||
explicitly specified or, in some cases, be deduced from the use
|
||
or obtained from default[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s*[.](#general-1.sentence-2)
|
||
|
||
[*Example [1](#general-example-1)*:
|
||
|
||
void f(Array<dcomplex>& cv, Array<int>& ci) { sort(cv); // calls sort(Array<dcomplex>&) sort(ci); // calls sort(Array<int>&)} andvoid 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*]
|
||
|
||
[2](#general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7758)
|
||
|
||
When an explicit template argument list is specified, if the
|
||
given [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") is not valid ([[temp.names]](temp.names "13.3 Names of template specializations")),
|
||
type deduction fails[.](#general-2.sentence-1)
|
||
|
||
Otherwise, the specified template argument values are substituted for the
|
||
corresponding template parameters as specified below[.](#general-2.sentence-2)
|
||
|
||
[3](#general-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7766)
|
||
|
||
After this substitution is performed, the function parameter type
|
||
adjustments described in [[dcl.fct]](dcl.fct "9.3.4.6 Functions") are performed[.](#general-3.sentence-1)
|
||
|
||
[*Example [2](#general-example-2)*:
|
||
|
||
A parameter type of âvoid (const int, int[5])â becomes
|
||
âvoid(*)(int,int*)â[.](#general-3.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[*Note [1](#general-note-1)*:
|
||
|
||
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[.](#general-3.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [3](#general-example-3)*: 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*]
|
||
|
||
[4](#general-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7803)
|
||
|
||
[*Note [2](#general-note-2)*:
|
||
|
||
f<int>(1) and f<const int>(1) call distinct functions
|
||
even though both of the functions called have the same function type[.](#general-4.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[5](#general-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7809)
|
||
|
||
The resulting substituted and adjusted function type is used as
|
||
the type of the function template for template argument
|
||
deduction[.](#general-5.sentence-1)
|
||
|
||
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[.](#general-5.sentence-2)
|
||
|
||
If the substitution results in an invalid type,
|
||
as described above, type deduction fails[.](#general-5.sentence-3)
|
||
|
||
[*Example [4](#general-example-4)*: 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
|
||
are replaced with the corresponding deduced
|
||
or default argument values[.](#general-5.sentence-4)
|
||
|
||
If the substitution results in an
|
||
invalid type, as described above, type deduction fails[.](#general-5.sentence-5)
|
||
|
||
If the function template has associated constraints ([[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations")),
|
||
those constraints are checked for satisfaction ([[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints"))[.](#general-5.sentence-6)
|
||
|
||
If the constraints are not satisfied, type deduction fails[.](#general-5.sentence-7)
|
||
|
||
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[.](#general-5.sentence-8)
|
||
|
||
[*Note [3](#general-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[.](#general-5.sentence-9)
|
||
|
||
â *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[.](#general-5.sentence-10)
|
||
|
||
If the substitution results in an invalid type, as described above,
|
||
type deduction fails[.](#general-5.sentence-11)
|
||
|
||
[*Example [5](#general-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); // #1template <class T> void f(int, T); // #2struct A {} a;struct ZZ {template <class T, class = typename Z<T>::xx> operator T *(); operator int();};int main() { ZZ zz;
|
||
f(1, a); // OK, deduction fails for #1 because there is no conversion from int to void* f(zz, 42); // OK, deduction fails for #1 because C<int> is not satisfied} â *end example*]
|
||
|
||
[6](#general-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7882)
|
||
|
||
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[.](#general-6.sentence-1)
|
||
|
||
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[.](#general-6.sentence-2)
|
||
|
||
[7](#general-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7891)
|
||
|
||
The [*deduction substitution loci*](#def:deduction_substitution_loci "13.10.3.1 General [temp.deduct.general]") are
|
||
|
||
- [(7.1)](#general-7.1)
|
||
|
||
the function type outside of the [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]"),
|
||
|
||
- [(7.2)](#general-7.2)
|
||
|
||
the [*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3 Function specifiers [dcl.fct.spec]"),
|
||
|
||
- [(7.3)](#general-7.3)
|
||
|
||
the template parameter declarations, and
|
||
|
||
- [(7.4)](#general-7.4)
|
||
|
||
the template argument list of a partial specialization ([[temp.spec.partial.general]](temp.spec.partial.general "13.7.6.1 General"))[.](#general-7.sentence-1)
|
||
|
||
The substitution occurs in all types and expressions that are used
|
||
in the deduction substitution loci[.](#general-7.sentence-2)
|
||
|
||
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[.](#general-7.sentence-3)
|
||
|
||
The substitution proceeds in lexical order and stops when
|
||
a condition that causes deduction to fail is encountered[.](#general-7.sentence-4)
|
||
|
||
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[.](#general-7.sentence-5)
|
||
|
||
[*Note [4](#general-note-4)*:
|
||
|
||
The equivalent substitution in
|
||
exception specifications ([[except.spec]](except.spec "14.5 Exception specifications"))
|
||
and function contract assertions ([[dcl.contract.func]](dcl.contract.func "9.4.1 General"))
|
||
is done only when
|
||
the [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") or [*function-contract-specifier*](dcl.contract.func#nt:function-contract-specifier "9.4.1 General [dcl.contract.func]"), respectively,
|
||
is instantiated,
|
||
at which point a program is ill-formed
|
||
if the substitution results in an invalid type or expression[.](#general-7.sentence-6)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [6](#general-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; // redeclarationtemplate <class T> void h(...) { }void x() { f<int>(0); // OK, substituting return type causes deduction to fail g<int>(0); // error, substituting parameter type instantiates A<int> h<int>(0); // ill-formed, no diagnostic required} â *end example*]
|
||
|
||
[8](#general-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7941)
|
||
|
||
If a substitution results in an invalid type or expression, type deduction fails[.](#general-8.sentence-1)
|
||
|
||
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[.](#general-8.sentence-2)
|
||
|
||
[*Note [5](#general-note-5)*:
|
||
|
||
If no diagnostic is required, the program is still ill-formed[.](#general-8.sentence-3)
|
||
|
||
Access checking is done as part of the substitution process[.](#general-8.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
Invalid types and expressions can result in a deduction failure
|
||
only in the immediate context of the deduction substitution loci[.](#general-8.sentence-5)
|
||
|
||
[*Note [6](#general-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[.](#general-8.sentence-6)
|
||
|
||
Such effects are not in the âimmediate contextâ and can result in the
|
||
program being ill-formed[.](#general-8.sentence-7)
|
||
|
||
â *end note*]
|
||
|
||
[9](#general-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7959)
|
||
|
||
When substituting into a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]"),
|
||
substitution into its body is not in the immediate context[.](#general-9.sentence-1)
|
||
|
||
[*Note [7](#general-note-7)*:
|
||
|
||
The intent is to avoid requiring implementations to deal with
|
||
substitution failure involving arbitrary statements[.](#general-9.sentence-2)
|
||
|
||
[*Example [7](#general-example-7)*: template <class T>auto f(T) -> decltype([]() { T::invalid; } ());void f(...);
|
||
f(0); // error: invalid expression not part of the immediate contexttemplate <class T, std::size_t = sizeof([]() { T::invalid; })>void g(T);void g(...);
|
||
g(0); // error: invalid expression not part of the immediate contexttemplate <class T>auto h(T) -> decltype([x = T::invalid]() { });void h(...);
|
||
h(0); // error: invalid expression not part of the immediate contexttemplate <class T>auto i(T) -> decltype([]() -> typename T::invalid { });void i(...);
|
||
i(0); // error: invalid expression not part of the immediate contexttemplate <class T>auto j(T t) -> decltype([](auto x) -> decltype(x.invalid) { } (t)); // #1void j(...); // #2 j(0); // deduction fails on #1, calls #2 â *end example*]
|
||
|
||
â *end note*]
|
||
|
||
[10](#general-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7995)
|
||
|
||
[*Example [8](#general-example-8)*: 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*]
|
||
|
||
[11](#general-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8011)
|
||
|
||
[*Note [8](#general-note-8)*:
|
||
|
||
Type deduction can fail for the following reasons:
|
||
|
||
- [(11.1)](#general-11.1)
|
||
|
||
Attempting to instantiate a pack expansion containing multiple packs of differing lengths[.](#general-11.1.sentence-1)
|
||
|
||
- [(11.2)](#general-11.2)
|
||
|
||
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[.](#general-11.2.sentence-1)
|
||
[*Example [9](#general-example-9)*: template <class T> int f(T[5]);int I = f<int>(0);int j = f<void>(0); // invalid array â *end example*]
|
||
|
||
- [(11.3)](#general-11.3)
|
||
|
||
Attempting to use a type that is not a class or enumeration type in a qualified name[.](#general-11.3.sentence-1)
|
||
[*Example [10](#general-example-10)*: template <class T> int f(typename T::B*);int i = f<int>(0); â *end example*]
|
||
|
||
- [(11.4)](#general-11.4)
|
||
|
||
Attempting to use a type in a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") of a[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") when
|
||
that type does not contain the specified member, or
|
||
* [(11.4.1)](#general-11.4.1)
|
||
|
||
the specified member is not a type where a type is required, or
|
||
|
||
* [(11.4.2)](#general-11.4.2)
|
||
|
||
the specified member is not a template where a template is required, or
|
||
|
||
* [(11.4.3)](#general-11.4.3)
|
||
|
||
the specified member is not a non-type, non-template where a non-type,
|
||
non-template is required[.](#general-11.4.sentence-1)
|
||
|
||
[*Example [11](#general-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() {// Deduction fails in each of these cases: f<A>(0); // A does not contain a member Y f<B>(0); // The Y member of B is not a type g<C>(0); // The N member of C is not a non-type, non-template name h<D>(0); // The TT member of D is not a template} â *end example*]
|
||
|
||
- [(11.5)](#general-11.5)
|
||
|
||
Attempting to create a pointer to reference type[.](#general-11.5.sentence-1)
|
||
|
||
- [(11.6)](#general-11.6)
|
||
|
||
Attempting to create a reference to void[.](#general-11.6.sentence-1)
|
||
|
||
- [(11.7)](#general-11.7)
|
||
|
||
Attempting to create âpointer to member of Tâ when T is not a
|
||
class type[.](#general-11.7.sentence-1)
|
||
[*Example [12](#general-example-12)*: template <class T> int f(int T::*);int i = f<int>(0); â *end example*]
|
||
|
||
- [(11.8)](#general-11.8)
|
||
|
||
Attempting to give an invalid type to a constant template parameter[.](#general-11.8.sentence-1)
|
||
[*Example [13](#general-example-13)*: template <class T, T> struct S {};template <class T> int f(S<T, T{}>*); // #1class X {int m;};int i0 = f<X>(0); // #1 uses a value of non-structural type X as a constant template argument â *end example*]
|
||
|
||
- [(11.9)](#general-11.9)
|
||
|
||
Attempting to perform an invalid conversion in either a template
|
||
argument expression, or an expression used in the function
|
||
declaration[.](#general-11.9.sentence-1)
|
||
[*Example [14](#general-example-14)*: template <class T, T*> int f(int);int i2 = f<int,1>(0); // can't convert 1 to int* â *end example*]
|
||
|
||
- [(11.10)](#general-11.10)
|
||
|
||
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[.](#general-11.10.sentence-1)
|
||
|
||
- [(11.11)](#general-11.11)
|
||
|
||
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]](expr.prim.lambda.closure "7.5.6.2 Closure types"))[.](#general-11.11.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[12](#general-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8124)
|
||
|
||
[*Example [15](#general-example-15)*:
|
||
|
||
In the following example,
|
||
assuming a signed char cannot represent the value 1000,
|
||
a [narrowing conversion](dcl.init.list#def:conversion,narrowing "9.5.5 List-initialization [dcl.init.list]") would be required
|
||
to convert the [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") of type int to signed char,
|
||
therefore substitution fails for the
|
||
second template ([[temp.arg.nontype]](temp.arg.nontype "13.4.3 Constant template arguments"))[.](#general-12.sentence-1)
|
||
|
||
template <int> int f(int);template <signed char> int f(int);int i1 = f<1000>(0); // OKint i2 = f<1>(0); // ambiguous; not narrowing â *end example*]
|
||
|
||
#### [13.10.3.2](#call) Deducing template arguments from a function call [[temp.deduct.call]](temp.deduct.call)
|
||
|
||
[1](#call-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8146)
|
||
|
||
Template argument deduction is done by comparing each function
|
||
template parameter type (call itP)
|
||
that contains template parameters that participate in template argument deduction
|
||
with the type of the corresponding argument of the call (call itA)
|
||
as described below[.](#call-1.sentence-1)
|
||
|
||
If removing references and cv-qualifiers from P givesstd::initializer_list<Pâ²> or Pâ²[N] for some Pâ² and N and the
|
||
argument is a non-empty initializer list ([[dcl.init.list]](dcl.init.list "9.5.5 List-initialization")), 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[.](#call-1.sentence-2)
|
||
|
||
In the Pâ²[N] case, if N is a constant template parameter,N is deduced from the length of the initializer list[.](#call-1.sentence-3)
|
||
|
||
Otherwise, an initializer list argument causes the
|
||
parameter to be considered a non-deduced context ([[temp.deduct.type]](#type "13.10.3.6 Deducing template arguments from a type"))[.](#call-1.sentence-4)
|
||
|
||
[*Example [1](#call-example-1)*: template<class T> void f(std::initializer_list<T>);
|
||
f({1,2,3}); // T deduced as int f({1,"asdf"}); // error: T deduced as both int and const char*template<class T> void g(T);
|
||
g({1,2,3}); // error: no argument deduced for Ttemplate<class T, int N> void h(T const(&)[N]);
|
||
h({1,2,3}); // T deduced as int; N deduced as 3template<class T> void j(T const(&)[3]);
|
||
j({42}); // T deduced as int; array bound not consideredstruct 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 as 3template<int M, int N> void m(int const(&)[M][N]);
|
||
m({{1,2},{3,4}}); // M and N both deduced as 2template<class T, int N> void n(T const(&)[N], T);
|
||
n({{1},{2},{3}},Aggr()); // OK, T is Aggr, N is 3template<typename T, int N> void o(T (* const (&)[N])(T)) { }int f1(int);int f4(int);char f4(char);
|
||
o({ &f1, &f4 }); // OK, T deduced as int from first element, nothing// deduced from second element, N deduced as 2 o({ &f1, static_cast<char(*)(char)>(&f4) }); // error: conflicting deductions for T â *end example*]
|
||
|
||
For a function parameter pack that occurs at the end
|
||
of the [*parameter-declaration-list*](dcl.fct#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]"),
|
||
deduction is performed for each remaining argument of the call,
|
||
taking the type P of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") of the function parameter pack
|
||
as the corresponding function template parameter type[.](#call-1.sentence-5)
|
||
|
||
Each deduction deduces template arguments for subsequent positions in
|
||
the template parameter packs expanded by the function parameter pack[.](#call-1.sentence-6)
|
||
|
||
When a function parameter pack appears in a non-deduced
|
||
context ([[temp.deduct.type]](#type "13.10.3.6 Deducing template arguments from a type")), the type of that pack is
|
||
never deduced[.](#call-1.sentence-7)
|
||
|
||
[*Example [2](#call-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); // Types deduced as int, float, const int g(x, y, z); // T1 deduced as int; Types deduced as float, int g1(x, y, z); // error: Types is not deduced g1<int, int, int>(x, y, z); // OK, no deduction occurs} â *end example*]
|
||
|
||
[2](#call-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8229)
|
||
|
||
IfP is not a reference type:
|
||
|
||
- [(2.1)](#call-2.1)
|
||
|
||
IfA is an array type, the pointer type produced by the [array-to-pointer
|
||
standard conversion](conv.array "7.3.3 Array-to-pointer conversion [conv.array]") is used in place ofA for type deduction;
|
||
otherwise,
|
||
|
||
- [(2.2)](#call-2.2)
|
||
|
||
IfA is a function type, the pointer type produced by the[function-to-pointer standard conversion](conv.func "7.3.4 Function-to-pointer conversion [conv.func]") is used in place
|
||
ofA for type
|
||
deduction; otherwise,
|
||
|
||
- [(2.3)](#call-2.3)
|
||
|
||
IfA is a cv-qualified type, the top-level cv-qualifiers ofA's
|
||
type are ignored for type deduction[.](#call-2.sentence-1)
|
||
|
||
[3](#call-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8259)
|
||
|
||
IfP is a cv-qualified type, the top-level cv-qualifiers ofP's
|
||
type are ignored for type deduction[.](#call-3.sentence-1)
|
||
|
||
IfP is a reference type, the type
|
||
referred to byP is used for type deduction[.](#call-3.sentence-2)
|
||
|
||
[*Example [3](#call-example-3)*: 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*](#def:forwarding_reference "13.10.3.2 Deducing template arguments from a function call [temp.deduct.call]") 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]](over.match.class.deduct "12.2.2.9 Class template argument deduction")))[.](#call-3.sentence-3)
|
||
|
||
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[.](#call-3.sentence-4)
|
||
|
||
[*Example [4](#call-example-4)*: 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 lvaluetemplate <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*]
|
||
|
||
[4](#call-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8315)
|
||
|
||
In general, the deduction process attempts to find template argument
|
||
values that will make the deducedA identical toA (after
|
||
the typeA is transformed as described above)[.](#call-4.sentence-1)
|
||
|
||
However, there are
|
||
three cases that allow a difference:
|
||
|
||
- [(4.1)](#call-4.1)
|
||
|
||
If the originalP is a reference type, the deducedA (i.e.,
|
||
the type referred to by the reference) can be more cv-qualified than
|
||
the transformed A[.](#call-4.1.sentence-1)
|
||
|
||
- [(4.2)](#call-4.2)
|
||
|
||
The transformed A can be another pointer or pointer-to-member type that can be converted
|
||
to the deducedA via a [function pointer conversion](conv.fctptr "7.3.14 Function pointer conversions [conv.fctptr]") and/or[qualification conversion](conv.qual "7.3.6 Qualification conversions [conv.qual]")[.](#call-4.2.sentence-1)
|
||
|
||
- [(4.3)](#call-4.3)
|
||
|
||
IfP is a class andP has the form[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") ortypenameopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]"),
|
||
then
|
||
the transformed A can be a derived class D of the
|
||
deducedA[.](#call-4.3.sentence-1)
|
||
Likewise, ifP is a pointer to a class of the form[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") ortypenameopt [*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]"),
|
||
the transformed A can be a pointer to a
|
||
derived class D of the class pointed to by the deducedA[.](#call-4.3.sentence-2)
|
||
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[.](#call-4.3.sentence-3)
|
||
[*Example [5](#call-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()); // calls f<int>, not f<>// B is X<>, C is X<int>int z = f(E()); // calls f<int>, not f<> â *end example*]
|
||
|
||
[5](#call-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8390)
|
||
|
||
These alternatives are considered only if type deduction would
|
||
otherwise fail[.](#call-5.sentence-1)
|
||
|
||
If they yield more than one possible deducedA,
|
||
the type deduction fails[.](#call-5.sentence-2)
|
||
|
||
[*Note [1](#call-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*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") cannot be deduced from a function call and the[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") must be explicitly specified[.](#call-5.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[6](#call-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8406)
|
||
|
||
WhenP is a function type, function pointer type, or pointer-to-member-function type:
|
||
|
||
- [(6.1)](#call-6.1)
|
||
|
||
If the argument is an overload set containing one or more function templates,
|
||
the parameter is treated as a non-deduced context[.](#call-6.1.sentence-1)
|
||
|
||
- [(6.2)](#call-6.2)
|
||
|
||
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]](temp.constr.constr "13.5.2 Constraints")) are satisfied[.](#call-6.2.sentence-1)
|
||
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[.](#call-6.2.sentence-2)
|
||
|
||
[7](#call-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8423)
|
||
|
||
[*Example [6](#call-example-6)*: // 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*]
|
||
|
||
[8](#call-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8434)
|
||
|
||
[*Example [7](#call-example-7)*: // 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*]
|
||
|
||
[9](#call-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8445)
|
||
|
||
[*Example [8](#call-example-8)*: // 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*]
|
||
|
||
[10](#call-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8456)
|
||
|
||
[*Example [9](#call-example-9)*: // All arguments for placeholder type deduction ([[dcl.type.auto.deduct]](dcl.type.auto.deduct "9.2.9.7.2 Placeholder type deduction")) yield the same deduced type.template<bool B> struct X {static void f(short) requires B; // #1static void f(short); // #2};void test() {auto x = &X<true>::f; // OK, deduces void(*)(short), selects #1auto y = &X<false>::f; // OK, deduces void(*)(short), selects #2} â *end example*]
|
||
|
||
#### [13.10.3.3](#funcaddr) Deducing template arguments taking the address of a function template [[temp.deduct.funcaddr]](temp.deduct.funcaddr)
|
||
|
||
[1](#funcaddr-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8473)
|
||
|
||
Template arguments can be deduced from the type specified when taking
|
||
the address of an [overload set](over.over "12.3 Address of an overload set [over.over]")[.](#funcaddr-1.sentence-1)
|
||
|
||
If there is a target,
|
||
the function template's function type and the target type
|
||
are used as the types ofP andA,
|
||
and the deduction is done as
|
||
described in [[temp.deduct.type]](#type "13.10.3.6 Deducing template arguments from a type")[.](#funcaddr-1.sentence-2)
|
||
|
||
Otherwise, deduction is performed with empty sets of types P and A[.](#funcaddr-1.sentence-3)
|
||
|
||
[2](#funcaddr-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8486)
|
||
|
||
A placeholder type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers")) in the return type of a
|
||
function template is a non-deduced context[.](#funcaddr-2.sentence-1)
|
||
|
||
If template argument
|
||
deduction succeeds for such a function, the return type is determined
|
||
from instantiation of the function body[.](#funcaddr-2.sentence-2)
|
||
|
||
#### [13.10.3.4](#conv) Deducing conversion function template arguments [[temp.deduct.conv]](temp.deduct.conv)
|
||
|
||
[1](#conv-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8494)
|
||
|
||
Template argument deduction is done by comparing the return type of
|
||
the
|
||
conversion function template
|
||
(call itP)
|
||
with the type specified by the [*conversion-type-id*](class.conv.fct#nt:conversion-type-id "11.4.8.3 Conversion functions [class.conv.fct]") of the[*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") being looked up
|
||
(call it A) as described in [[temp.deduct.type]](#type "13.10.3.6 Deducing template arguments from a type")[.](#conv-1.sentence-1)
|
||
|
||
If the [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") is constructed during
|
||
overload resolution ([[over.match.funcs]](over.match.funcs "12.2.2 Candidate functions and argument lists")),
|
||
the rules in the remainder of this subclause apply[.](#conv-1.sentence-2)
|
||
|
||
[2](#conv-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8507)
|
||
|
||
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 ofP in the remainder of this subclause[.](#conv-2.sentence-1)
|
||
|
||
[3](#conv-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8512)
|
||
|
||
IfA is not a reference type:
|
||
|
||
- [(3.1)](#conv-3.1)
|
||
|
||
IfP is an array type, the pointer type produced by the[array-to-pointer standard conversion](conv.array "7.3.3 Array-to-pointer conversion [conv.array]") is used in place ofP for type
|
||
deduction; otherwise,
|
||
|
||
- [(3.2)](#conv-3.2)
|
||
|
||
IfP is a function type, the pointer type produced by the[function-to-pointer standard conversion](conv.func "7.3.4 Function-to-pointer conversion [conv.func]") is used in place ofP for
|
||
type deduction; otherwise,
|
||
|
||
- [(3.3)](#conv-3.3)
|
||
|
||
IfP is a cv-qualified type, the top-level cv-qualifiers ofP's
|
||
type are ignored for type deduction[.](#conv-3.sentence-1)
|
||
|
||
[4](#conv-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8541)
|
||
|
||
IfA is a cv-qualified type, the top-level cv-qualifiers ofA's
|
||
type are ignored for type deduction[.](#conv-4.sentence-1)
|
||
|
||
IfA is a
|
||
reference type, the type referred to byA is used for type deduction[.](#conv-4.sentence-2)
|
||
|
||
[5](#conv-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8554)
|
||
|
||
In general, the deduction process attempts to find template argument
|
||
values that will make the deducedA identical toA[.](#conv-5.sentence-1)
|
||
|
||
However, certain attributes of A may be ignored:
|
||
|
||
- [(5.1)](#conv-5.1)
|
||
|
||
If the original A is a reference type,
|
||
any cv-qualifiers of A (i.e., the type referred to by the reference)[.](#conv-5.1.sentence-1)
|
||
|
||
- [(5.2)](#conv-5.2)
|
||
|
||
If the original A is
|
||
a function pointer or pointer-to-member-function type
|
||
with a potentially-throwing exception specification ([[except.spec]](except.spec "14.5 Exception specifications")),
|
||
the exception specification[.](#conv-5.2.sentence-1)
|
||
|
||
- [(5.3)](#conv-5.3)
|
||
|
||
Any cv-qualifiers in A that can be restored by a qualification conversion[.](#conv-5.3.sentence-1)
|
||
|
||
These attributes are ignored only if type deduction would
|
||
otherwise fail[.](#conv-5.sentence-3)
|
||
|
||
If ignoring them allows more than one possible deducedA,
|
||
the type deduction fails[.](#conv-5.sentence-4)
|
||
|
||
#### [13.10.3.5](#partial) Deducing template arguments during partial ordering [[temp.deduct.partial]](temp.deduct.partial)
|
||
|
||
[1](#partial-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8583)
|
||
|
||
Template argument deduction is done by comparing certain types associated with
|
||
the two function templates being compared[.](#partial-1.sentence-1)
|
||
|
||
[2](#partial-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8587)
|
||
|
||
Two sets of types are used to determine the partial ordering[.](#partial-2.sentence-1)
|
||
|
||
For each of
|
||
the templates involved there is the original function type and the
|
||
transformed function type[.](#partial-2.sentence-2)
|
||
|
||
[*Note [1](#partial-note-1)*:
|
||
|
||
The creation of the transformed type is described in [[temp.func.order]](temp.func.order "13.7.7.3 Partial ordering of function templates")[.](#partial-2.sentence-3)
|
||
|
||
â *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[.](#partial-2.sentence-4)
|
||
|
||
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[.](#partial-2.sentence-5)
|
||
|
||
[3](#partial-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8602)
|
||
|
||
The types used to determine the ordering depend on the context in which
|
||
the partial ordering is done:
|
||
|
||
- [(3.1)](#partial-3.1)
|
||
|
||
In the context of a function call, the types used are those function parameter types
|
||
for which the function call has arguments[.](#partial-3.1.sentence-1)[119](#footnote-119 "Default arguments are not considered to be arguments in this context; they only become arguments after a function has been selected.")
|
||
|
||
- [(3.2)](#partial-3.2)
|
||
|
||
In the context of a call to a conversion function, the return types of
|
||
the conversion function templates are used[.](#partial-3.2.sentence-1)
|
||
|
||
- [(3.3)](#partial-3.3)
|
||
|
||
In [other contexts](temp.func.order "13.7.7.3 Partial ordering of function templates [temp.func.order]") the function template's function
|
||
type is used[.](#partial-3.3.sentence-1)
|
||
|
||
[4](#partial-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8622)
|
||
|
||
Each type nominated above from the parameter template and the corresponding type from the
|
||
argument template are used as the types ofP andA[.](#partial-4.sentence-1)
|
||
|
||
[5](#partial-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8629)
|
||
|
||
Before the partial ordering is done, certain transformations are performed
|
||
on the types used for partial ordering:
|
||
|
||
- [(5.1)](#partial-5.1)
|
||
|
||
IfP is a reference type,P is replaced by the type referred to[.](#partial-5.1.sentence-1)
|
||
|
||
- [(5.2)](#partial-5.2)
|
||
|
||
IfA is a reference type,A is replaced by the type referred to[.](#partial-5.2.sentence-1)
|
||
|
||
[6](#partial-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8647)
|
||
|
||
If bothP andA 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[.](#partial-6.sentence-1)
|
||
|
||
The result of this
|
||
determination will be used below[.](#partial-6.sentence-2)
|
||
|
||
[7](#partial-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8658)
|
||
|
||
Remove any top-level cv-qualifiers:
|
||
|
||
- [(7.1)](#partial-7.1)
|
||
|
||
IfP is a cv-qualified type,P is replaced by the cv-unqualified version ofP[.](#partial-7.1.sentence-1)
|
||
|
||
- [(7.2)](#partial-7.2)
|
||
|
||
IfA is a cv-qualified type,A is replaced by the cv-unqualified version ofA[.](#partial-7.2.sentence-1)
|
||
|
||
[8](#partial-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8677)
|
||
|
||
Using the resulting typesP andA,
|
||
the deduction is then done as described in [[temp.deduct.type]](#type "13.10.3.6 Deducing template arguments from a type")[.](#partial-8.sentence-1)
|
||
|
||
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*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") of the function parameter pack[.](#partial-8.sentence-2)
|
||
|
||
Each comparison
|
||
deduces template arguments for subsequent positions in the template parameter
|
||
packs expanded by the function parameter pack[.](#partial-8.sentence-3)
|
||
|
||
Similarly, if A was transformed from a function parameter pack,
|
||
it is compared with each remaining parameter type of the parameter template[.](#partial-8.sentence-4)
|
||
|
||
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[.](#partial-8.sentence-5)
|
||
|
||
[*Example [1](#partial-example-1)*: template<class... Args> void f(Args... args); // #1template<class T1, class... Args> void f(T1 a1, Args... args); // #2template<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*]
|
||
|
||
[9](#partial-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8706)
|
||
|
||
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):
|
||
|
||
- [(9.1)](#partial-9.1)
|
||
|
||
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,
|
||
|
||
- [(9.2)](#partial-9.2)
|
||
|
||
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[.](#partial-9.sentence-1)
|
||
|
||
[10](#partial-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8723)
|
||
|
||
Function template F is [*at least as specialized as*](#def:more_specialized "13.10.3.5 Deducing template arguments during partial ordering [temp.deduct.partial]") 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[.](#partial-10.sentence-1)
|
||
|
||
F is [*more specialized than*](#def:more_specialized,function_template "13.10.3.5 Deducing template arguments during partial ordering [temp.deduct.partial]")G ifF is at least as specialized asG andG is not at least as specialized asF[.](#partial-10.sentence-2)
|
||
|
||
[11](#partial-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8742)
|
||
|
||
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[.](#partial-11.sentence-1)
|
||
|
||
[12](#partial-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8750)
|
||
|
||
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[.](#partial-12.sentence-1)
|
||
|
||
[*Note [2](#partial-note-2)*:
|
||
|
||
A template parameter used in a non-deduced context is considered used[.](#partial-12.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [2](#partial-example-2)*: template <class T> T f(int); // #1template <class T, class U> T f(U); // #2void g() { f<int>(1); // calls #1} â *end example*]
|
||
|
||
[13](#partial-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8769)
|
||
|
||
[*Note [3](#partial-note-3)*:
|
||
|
||
Partial ordering of function templates containing
|
||
template parameter packs is independent of the number of deduced arguments
|
||
for those template parameter packs[.](#partial-13.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [3](#partial-example-3)*: template<class ...> struct Tuple { };template<class ... Types> void g(Tuple<Types ...>); // #1template<class T1, class ... Types> void g(Tuple<T1, Types ...>); // #2template<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*]
|
||
|
||
[119)](#footnote-119)[119)](#footnoteref-119)
|
||
|
||
Default arguments
|
||
are not considered to be arguments in this context; they only become arguments
|
||
after a function has been selected[.](#footnote-119.sentence-1)
|
||
|
||
#### [13.10.3.6](#type) Deducing template arguments from a type [[temp.deduct.type]](temp.deduct.type)
|
||
|
||
[1](#type-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8791)
|
||
|
||
Template arguments can be deduced in several different contexts, but
|
||
in each case a type that is specified in terms of template parameters
|
||
(call itP)
|
||
is compared with an actual type (call itA),
|
||
and an attempt is made to find template argument values (a type for a type
|
||
parameter, a value for a constant template parameter, or a template for a
|
||
template template parameter) that will makeP,
|
||
after substitution of the deduced values (call it the deducedA),
|
||
compatible withA[.](#type-1.sentence-1)
|
||
|
||
[2](#type-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8807)
|
||
|
||
In some cases, the deduction is done using a single set of typesP andA,
|
||
in other cases, there will be a set of corresponding typesP andA[.](#type-2.sentence-1)
|
||
|
||
Type deduction is done
|
||
independently for eachP/A pair, and the deduced template
|
||
argument values are then combined[.](#type-2.sentence-2)
|
||
|
||
If type deduction cannot be done
|
||
for anyP/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[.](#type-2.sentence-3)
|
||
|
||
The type of a type parameter
|
||
is only deduced from an array bound
|
||
if it is not otherwise deduced[.](#type-2.sentence-4)
|
||
|
||
[3](#type-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8832)
|
||
|
||
A given typeP can be composed from a number of other
|
||
types, templates, and constant template argument values:
|
||
|
||
- [(3.1)](#type-3.1)
|
||
|
||
A function type includes the types of each of the function parameters,
|
||
the return type, and its exception specification[.](#type-3.1.sentence-1)
|
||
|
||
- [(3.2)](#type-3.2)
|
||
|
||
A pointer-to-member type includes the type of the class object pointed to
|
||
and the type of the member pointed to[.](#type-3.2.sentence-1)
|
||
|
||
- [(3.3)](#type-3.3)
|
||
|
||
A type that is a specialization of a class template (e.g.,A<int>)
|
||
includes the types, templates, and constant template argument values referenced by the
|
||
template argument list of the specialization[.](#type-3.3.sentence-1)
|
||
|
||
- [(3.4)](#type-3.4)
|
||
|
||
An array type includes the array element type and the value of the
|
||
array bound[.](#type-3.4.sentence-1)
|
||
|
||
[4](#type-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8854)
|
||
|
||
In most cases, the types, templates, and constant template argument values that are used
|
||
to composeP participate in template argument deduction[.](#type-4.sentence-1)
|
||
|
||
That is,
|
||
they may be used to determine the value of a template argument, and
|
||
template argument deduction fails if
|
||
the value so determined is not consistent with the values determined
|
||
elsewhere[.](#type-4.sentence-2)
|
||
|
||
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[.](#type-4.sentence-3)
|
||
|
||
If a template parameter is used only in non-deduced contexts and is not
|
||
explicitly specified, template argument deduction fails[.](#type-4.sentence-4)
|
||
|
||
[*Note [1](#type-note-1)*:
|
||
|
||
Under [[temp.deduct.call]](#call "13.10.3.2 Deducing template arguments from a function call"),
|
||
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[.](#type-4.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
[5](#type-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8876)
|
||
|
||
The non-deduced contexts are:
|
||
|
||
- [(5.1)](#type-5.1)
|
||
|
||
The[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") of a type that was specified using a[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]")[.](#type-5.1.sentence-1)
|
||
|
||
- [(5.2)](#type-5.2)
|
||
|
||
A [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]") or a [*pack-index-expression*](expr.prim.pack.index#nt:pack-index-expression "7.5.5.4 Pack indexing expression [expr.prim.pack.index]")[.](#type-5.2.sentence-1)
|
||
|
||
- [(5.3)](#type-5.3)
|
||
|
||
A [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")[.](#type-5.3.sentence-1)
|
||
|
||
- [(5.4)](#type-5.4)
|
||
|
||
The [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") of a [*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]")[.](#type-5.4.sentence-1)
|
||
|
||
- [(5.5)](#type-5.5)
|
||
|
||
The [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") of a [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]")[.](#type-5.5.sentence-1)
|
||
|
||
- [(5.6)](#type-5.6)
|
||
|
||
A constant template argument or an array bound in which a subexpression
|
||
references a template parameter[.](#type-5.6.sentence-1)
|
||
|
||
- [(5.7)](#type-5.7)
|
||
|
||
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[.](#type-5.7.sentence-1)
|
||
|
||
- [(5.8)](#type-5.8)
|
||
|
||
A function parameter for which the associated argument is an
|
||
overload set such that one or more of the following apply:
|
||
* [(5.8.1)](#type-5.8.1)
|
||
|
||
functions whose associated constraints are satisfied and
|
||
that do not all have the same function type
|
||
match the function parameter type (resulting in an ambiguous deduction), or
|
||
|
||
* [(5.8.2)](#type-5.8.2)
|
||
|
||
no function whose associated constraints are satisfied
|
||
matches the function parameter type, or
|
||
|
||
* [(5.8.3)](#type-5.8.3)
|
||
|
||
the overload set supplied as an argument contains one or more function templates[.](#type-5.8.sentence-1)
|
||
|
||
[*Note [2](#type-note-2)*:
|
||
A particular function from the overload set is selected ([[over.over]](over.over "12.3 Address of an overload set"))
|
||
after template argument deduction has succeeded ([[temp.over]](temp.over "13.10.4 Overload resolution"))[.](#type-5.8.sentence-2)
|
||
â *end note*]
|
||
|
||
- [(5.9)](#type-5.9)
|
||
|
||
A function parameter for which the associated argument is an initializer
|
||
list ([[dcl.init.list]](dcl.init.list "9.5.5 List-initialization")) but the parameter does not have
|
||
a type for which deduction from an initializer list is specified ([[temp.deduct.call]](#call "13.10.3.2 Deducing template arguments from a function call"))[.](#type-5.9.sentence-1)
|
||
[*Example [1](#type-example-1)*: template<class T> void g(T);
|
||
g({1,2,3}); // error: no argument deduced for T â *end example*]
|
||
|
||
- [(5.10)](#type-5.10)
|
||
|
||
A function parameter pack that does not occur at the end of the[*parameter-declaration-list*](dcl.fct#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]")[.](#type-5.10.sentence-1)
|
||
|
||
[6](#type-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8931)
|
||
|
||
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[.](#type-6.sentence-1)
|
||
|
||
However, a compound type can include both deduced and non-deduced types[.](#type-6.sentence-2)
|
||
|
||
[*Example [2](#type-example-2)*:
|
||
|
||
If a type is specified asA<T>::B<T2>,
|
||
bothT andT2 are non-deduced[.](#type-6.sentence-3)
|
||
|
||
Likewise, if a type is specified asA<I+J>::X<T>,I,J,
|
||
andT are non-deduced[.](#type-6.sentence-4)
|
||
|
||
If a type is specified asvoidf(typenameA<T>::B,A<T>),
|
||
theT inA<T>::B is non-deduced but
|
||
theT inA<T> is deduced[.](#type-6.sentence-5)
|
||
|
||
â *end example*]
|
||
|
||
[7](#type-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8968)
|
||
|
||
[*Example [3](#type-example-3)*:
|
||
|
||
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 deduced as both A and B f(b,a); // error: T deduced as both A and 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[.](#type-7.sentence-2)
|
||
|
||
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 deduced as both char and int f(g3); // error: U deduced as both char and float}
|
||
|
||
Here is an example where the exception specification of a function type
|
||
is deduced:template<bool E> void f1(void (*)() noexcept(E));template<bool> struct A { };template<bool B> void f2(void (*)(A<B>) noexcept(B));
|
||
|
||
void g1();void g2() noexcept;void g3(A<true>);
|
||
|
||
void h() { f1(g1); // OK, E is false f1(g2); // OK, E is true f2(g3); // error: B deduced as both true and false}
|
||
|
||
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*]
|
||
|
||
[8](#type-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9046)
|
||
|
||
A type template argument T,
|
||
a constant template argument i,
|
||
a template template argument TT denoting a class template or an alias template, or
|
||
a template template argument VV denoting a variable template or a concept
|
||
can be deduced ifP andA have one of the following forms:cvopt T
|
||
T* T& T&& Topt[iopt] Topt(Topt) noexcept(iopt) Topt Topt::* TTopt<T> TTopt<i> TTopt<TT> TTopt<VV> TTopt<> where
|
||
|
||
- [(8.1)](#type-8.1)
|
||
|
||
Topt represents a type or parameter-type-list that either
|
||
satisfies these rules recursively,
|
||
is a non-deduced context in P or A, or
|
||
is the same non-dependent type in P and A,
|
||
|
||
- [(8.2)](#type-8.2)
|
||
|
||
iopt represents an expression that either
|
||
is an i,
|
||
is value-dependent in P or A, or
|
||
has the same constant value in P and A,
|
||
|
||
- [(8.3)](#type-8.3)
|
||
|
||
TTopt represents either a class template or
|
||
a template template parameter, and
|
||
|
||
- [(8.4)](#type-8.4)
|
||
|
||
noexcept(iopt) represents an
|
||
exception specification ([[except.spec]](except.spec "14.5 Exception specifications"))
|
||
in which the (possibly-implicit, see [[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")'s operand
|
||
satisfies the rules for an iopt above[.](#type-8.sentence-1)
|
||
|
||
[*Note [3](#type-note-3)*:
|
||
|
||
If a type matches such a form but contains noTs, is, or TTs, deduction is not possible[.](#type-8.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
Similarly,<X> represents template argument lists where
|
||
at least one argument contains an X, whereX is one of T, i, TT, or VV;
|
||
and<> represents template argument lists where no argument contains aT, an i, a TT, or a VV[.](#type-8.sentence-3)
|
||
|
||
[9](#type-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9112)
|
||
|
||
If P has a form that contains<T>, <i>, <TT>, or <VV>,
|
||
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[.](#type-9.sentence-1)
|
||
|
||
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[.](#type-9.sentence-2)
|
||
|
||
If Pi is a pack expansion, then the pattern
|
||
of Pi is compared with each remaining argument in the
|
||
template argument list of A[.](#type-9.sentence-3)
|
||
|
||
Each comparison deduces
|
||
template arguments for subsequent positions in the template parameter
|
||
packs expanded by Pi[.](#type-9.sentence-4)
|
||
|
||
During [partial ordering](#partial "13.10.3.5 Deducing template arguments during partial ordering [temp.deduct.partial]"), if Ai was
|
||
originally a pack expansion:
|
||
|
||
- [(9.1)](#type-9.1)
|
||
|
||
if P does not contain a template argument corresponding toAi then Ai is ignored;
|
||
|
||
- [(9.2)](#type-9.2)
|
||
|
||
otherwise, if Pi is not a pack expansion, template argument
|
||
deduction fails[.](#type-9.sentence-5)
|
||
|
||
[*Example [4](#type-example-4)*: template<class T1, class... Z> class S; // #1template<class T1, class... Z> class S<T1, const Z&...> { }; // #2template<class T1, class T2> class S<T1, const T2&> { }; // #3 S<int, const int&> s; // both #2 and #3 match; #3 is more specializedtemplate<class T, class... U> struct A { }; // #1template<class T1, class T2, class... U> struct A<T1, T2*, U...> { }; // #2template<class T1, class T2> struct A<T1, T2> { }; // #3template struct A<int, int*>; // selects #2 â *end example*]
|
||
|
||
[10](#type-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9149)
|
||
|
||
Similarly, if P has a form that contains(T), then each parameter type Pi of the respective parameter-type-list ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) ofP is compared with the corresponding parameter typeAi of the corresponding parameter-type-list
|
||
of A[.](#type-10.sentence-1)
|
||
|
||
If P and A are function types that originated from deduction when
|
||
taking the address of a function template ([[temp.deduct.funcaddr]](#funcaddr "13.10.3.3 Deducing template arguments taking the address of a function template")) or when
|
||
deducing template arguments from a function declaration ([[temp.deduct.decl]](#decl "13.10.3.7 Deducing template arguments from a function declaration"))
|
||
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]](#call "13.10.3.2 Deducing template arguments from a function call"))
|
||
and Ai is an lvalue reference, in which case the type ofPi is changed to be the template parameter type (i.e., T&& is
|
||
changed to simply T)[.](#type-10.sentence-2)
|
||
|
||
[*Note [4](#type-note-4)*:
|
||
|
||
As a result, when Pi is T&& and Ai is X&, the adjusted Pi will be T,
|
||
causing T to be deduced as X&[.](#type-10.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [5](#type-example-5)*: template <class T> void f(T&&);template <> void f(int&) { } // #1template <> void f(int&&) { } // #2void 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*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") corresponding to Pi is a function parameter pack,
|
||
then the type of its [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") is compared with
|
||
each remaining parameter type in the parameter-type-list
|
||
of A[.](#type-10.sentence-4)
|
||
|
||
Each comparison deduces template arguments for
|
||
subsequent positions in the template parameter packs expanded by the
|
||
function parameter pack[.](#type-10.sentence-5)
|
||
|
||
During [partial ordering](#partial "13.10.3.5 Deducing template arguments during partial ordering [temp.deduct.partial]"), if Ai was
|
||
originally a function parameter pack:
|
||
|
||
- [(10.1)](#type-10.1)
|
||
|
||
if P does not contain a function parameter type corresponding toAi then Ai is ignored;
|
||
|
||
- [(10.2)](#type-10.2)
|
||
|
||
otherwise, if Pi is not a function parameter pack, template
|
||
argument deduction fails[.](#type-10.sentence-6)
|
||
|
||
[*Example [6](#type-example-6)*: template<class T, class... U> void f(T*, U...) { } // #1template<class T> void f(T) { } // #2template void f(int*); // selects #1 â *end example*]
|
||
|
||
[11](#type-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9206)
|
||
|
||
These forms can be used in the same way asT is for further composition of types[.](#type-11.sentence-1)
|
||
|
||
[*Example [7](#type-example-7)*:
|
||
|
||
X<int> (*)(char[6]) is of the form[*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]")<T> (*)(*type*[i]) which is a variant of*type* (*)(T) where type isX<int> andT ischar[6][.](#type-11.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[12](#type-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9230)
|
||
|
||
Template arguments cannot be deduced from function arguments involving
|
||
constructs other than the ones specified above[.](#type-12.sentence-1)
|
||
|
||
[13](#type-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9234)
|
||
|
||
When the value of the argument
|
||
corresponding to a constant 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[.](#type-13.sentence-1)
|
||
|
||
[*Example [8](#type-example-8)*: 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 as long from the// template argument value in the type A<2> â *end example*]
|
||
|
||
[14](#type-14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9256)
|
||
|
||
The type of N in the type T[N] is std::size_t[.](#type-14.sentence-1)
|
||
|
||
[*Example [9](#type-example-9)*: 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 as std::size_t from the type int[42] â *end example*]
|
||
|
||
[15](#type-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9270)
|
||
|
||
The type of B in the [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")noexcept(B) of a function type is bool[.](#type-15.sentence-1)
|
||
|
||
[*Example [10](#type-example-10)*: template<bool> struct A { };template<auto> struct B;template<auto X, void (*F)() noexcept(X)> struct B<F> { A<X> ax;};void f_nothrow() noexcept;
|
||
B<f_nothrow> bn; // OK, type of X deduced as bool â *end example*]
|
||
|
||
[16](#type-16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9285)
|
||
|
||
[*Example [11](#type-example-11)*: 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*]
|
||
|
||
[17](#type-17)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9296)
|
||
|
||
[*Note [5](#type-note-5)*:
|
||
|
||
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 as 20 f1<20>(v); // OK f2(v); // error: cannot deduce template-argument i f2<10>(v); // OK f3(v); // OK, i deduced as 10}
|
||
|
||
â *end note*]
|
||
|
||
[18](#type-18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9316)
|
||
|
||
[*Note [6](#type-note-6)*:
|
||
|
||
If, in the declaration of a function template with a constant
|
||
template parameter, the constant template parameter
|
||
is used in a subexpression in the function parameter list,
|
||
the expression is a non-deduced context as specified above[.](#type-18.sentence-1)
|
||
|
||
[*Example [12](#type-example-12)*: 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*]
|
||
|
||
[19](#type-19)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9338)
|
||
|
||
[*Note [7](#type-note-7)*:
|
||
|
||
Template parameters do not participate in template argument deduction if
|
||
they are used only in non-deduced contexts[.](#type-19.sentence-1)
|
||
|
||
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 heretypename 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 deduced as 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*]
|
||
|
||
[20](#type-20)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9358)
|
||
|
||
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*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]"), deduction fails[.](#type-20.sentence-1)
|
||
|
||
If P has a form that contains [i], and if the type ofi is not an integral type, deduction fails[.](#type-20.sentence-2)[120](#footnote-120 "Although the template-argument corresponding to a template parameter of type bool can be deduced from an array bound, the resulting value will always be true because the array bound will be nonzero.")
|
||
|
||
If P has a form that includes noexcept(i) and
|
||
the type of i is not bool, deduction fails[.](#type-20.sentence-3)
|
||
|
||
[*Example [13](#type-example-13)*: 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*]
|
||
|
||
[21](#type-21)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9396)
|
||
|
||
A[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") can be deduced from a function, pointer to function, or
|
||
pointer-to-member-function type[.](#type-21.sentence-1)
|
||
|
||
[*Example [14](#type-example-14)*: 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*]
|
||
|
||
[22](#type-22)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9419)
|
||
|
||
A template[*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") cannot be deduced from the type of a function default argument[.](#type-22.sentence-1)
|
||
|
||
[*Example [15](#type-example-15)*: template <class T> void f(T = 5, T = 7);void g() { f(1); // OK, calls f<int>(1,7) f(); // error: cannot deduce T f<int>(); // OK, calls f<int>(5,7)} â *end example*]
|
||
|
||
[23](#type-23)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9434)
|
||
|
||
The[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") corresponding to a template template parameter
|
||
is deduced from the type of the[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") of a class template specialization used in the argument list of a function call[.](#type-23.sentence-1)
|
||
|
||
[*Example [16](#type-example-16)*: 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*]
|
||
|
||
[24](#type-24)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9451)
|
||
|
||
[*Note [8](#type-note-8)*:
|
||
|
||
Template argument deduction involving parameter
|
||
packs ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates")) can deduce zero or more arguments for
|
||
each parameter pack[.](#type-24.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [17](#type-example-17)*: 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; // uses 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, doubleint fv = f(g); // OK; Types contains int, float â *end example*]
|
||
|
||
[120)](#footnote-120)[120)](#footnoteref-120)
|
||
|
||
Although the[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") corresponding to a template parameter of typebool can be deduced from an array bound, the resulting value will always betrue because the array bound will be nonzero[.](#footnote-120.sentence-1)
|
||
|
||
#### [13.10.3.7](#decl) Deducing template arguments from a function declaration [[temp.deduct.decl]](temp.deduct.decl)
|
||
|
||
[1](#decl-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9479)
|
||
|
||
In a declaration whose [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") refers to a specialization
|
||
of a function template, template argument deduction is performed to identify
|
||
the specialization to which the declaration refers[.](#decl-1.sentence-1)
|
||
|
||
Specifically, this is done
|
||
for [explicit instantiations](temp.explicit "13.9.3 Explicit instantiation [temp.explicit]"), [explicit specializations](temp.expl.spec "13.9.4 Explicit specialization [temp.expl.spec]"),
|
||
and certain [friend declarations](temp.friend "13.7.5 Friends [temp.friend]")[.](#decl-1.sentence-2)
|
||
|
||
This is also done to
|
||
determine whether a deallocation function template specialization matches a placementoperator new ([[basic.stc.dynamic.deallocation]](basic.stc.dynamic.deallocation "6.8.6.5.3 Deallocation functions"), [[expr.new]](expr.new "7.6.2.8 New"))[.](#decl-1.sentence-3)
|
||
|
||
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 placementoperator new as described in [[expr.new]](expr.new "7.6.2.8 New")[.](#decl-1.sentence-4)
|
||
|
||
The
|
||
deduction is done as described in [[temp.deduct.type]](#type "13.10.3.6 Deducing template arguments from a type")[.](#decl-1.sentence-5)
|
||
|
||
[2](#decl-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9494)
|
||
|
||
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]](temp.func.order "13.7.7.3 Partial ordering of function templates")),
|
||
deduction fails and, in the declaration cases, the
|
||
program is ill-formed[.](#decl-2.sentence-1)
|