369 lines
17 KiB
Markdown
369 lines
17 KiB
Markdown
[temp.deduct.general]
|
||
|
||
# 13 Templates [[temp]](./#temp)
|
||
|
||
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct.general)
|
||
|
||
### 13.10.3 Template argument deduction [[temp.deduct]](temp.deduct#general)
|
||
|
||
#### 13.10.3.1 General [temp.deduct.general]
|
||
|
||
[1](#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[.](#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*[.](#1.sentence-2)
|
||
|
||
[*Example [1](#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](#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[.](#2.sentence-1)
|
||
|
||
Otherwise, the specified template argument values are substituted for the
|
||
corresponding template parameters as specified below[.](#2.sentence-2)
|
||
|
||
[3](#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[.](#3.sentence-1)
|
||
|
||
[*Example [2](#example-2)*:
|
||
|
||
A parameter type of âvoid (const int, int[5])â becomes
|
||
âvoid(*)(int,int*)â[.](#3.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[*Note [1](#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[.](#3.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [3](#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](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7803)
|
||
|
||
[*Note [2](#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[.](#4.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[5](#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[.](#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[.](#5.sentence-2)
|
||
|
||
If the substitution results in an invalid type,
|
||
as described above, type deduction fails[.](#5.sentence-3)
|
||
|
||
[*Example [4](#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[.](#5.sentence-4)
|
||
|
||
If the substitution results in an
|
||
invalid type, as described above, type deduction fails[.](#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"))[.](#5.sentence-6)
|
||
|
||
If the constraints are not satisfied, type deduction fails[.](#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[.](#5.sentence-8)
|
||
|
||
[*Note [3](#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[.](#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[.](#5.sentence-10)
|
||
|
||
If the substitution results in an invalid type, as described above,
|
||
type deduction fails[.](#5.sentence-11)
|
||
|
||
[*Example [5](#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](#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[.](#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[.](#6.sentence-2)
|
||
|
||
[7](#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)](#7.1)
|
||
|
||
the function type outside of the [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]"),
|
||
|
||
- [(7.2)](#7.2)
|
||
|
||
the [*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3 Function specifiers [dcl.fct.spec]"),
|
||
|
||
- [(7.3)](#7.3)
|
||
|
||
the template parameter declarations, and
|
||
|
||
- [(7.4)](#7.4)
|
||
|
||
the template argument list of a partial specialization ([[temp.spec.partial.general]](temp.spec.partial.general "13.7.6.1 General"))[.](#7.sentence-1)
|
||
|
||
The substitution occurs in all types and expressions that are used
|
||
in the deduction substitution loci[.](#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[.](#7.sentence-3)
|
||
|
||
The substitution proceeds in lexical order and stops when
|
||
a condition that causes deduction to fail is encountered[.](#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[.](#7.sentence-5)
|
||
|
||
[*Note [4](#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[.](#7.sentence-6)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [6](#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](#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[.](#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[.](#8.sentence-2)
|
||
|
||
[*Note [5](#note-5)*:
|
||
|
||
If no diagnostic is required, the program is still ill-formed[.](#8.sentence-3)
|
||
|
||
Access checking is done as part of the substitution process[.](#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[.](#8.sentence-5)
|
||
|
||
[*Note [6](#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[.](#8.sentence-6)
|
||
|
||
Such effects are not in the âimmediate contextâ and can result in the
|
||
program being ill-formed[.](#8.sentence-7)
|
||
|
||
â *end note*]
|
||
|
||
[9](#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[.](#9.sentence-1)
|
||
|
||
[*Note [7](#note-7)*:
|
||
|
||
The intent is to avoid requiring implementations to deal with
|
||
substitution failure involving arbitrary statements[.](#9.sentence-2)
|
||
|
||
[*Example [7](#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](#10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7995)
|
||
|
||
[*Example [8](#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](#11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8011)
|
||
|
||
[*Note [8](#note-8)*:
|
||
|
||
Type deduction can fail for the following reasons:
|
||
|
||
- [(11.1)](#11.1)
|
||
|
||
Attempting to instantiate a pack expansion containing multiple packs of differing lengths[.](#11.1.sentence-1)
|
||
|
||
- [(11.2)](#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[.](#11.2.sentence-1)
|
||
[*Example [9](#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)](#11.3)
|
||
|
||
Attempting to use a type that is not a class or enumeration type in a qualified name[.](#11.3.sentence-1)
|
||
[*Example [10](#example-10)*: template <class T> int f(typename T::B*);int i = f<int>(0); â *end example*]
|
||
|
||
- [(11.4)](#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)](#11.4.1)
|
||
|
||
the specified member is not a type where a type is required, or
|
||
|
||
* [(11.4.2)](#11.4.2)
|
||
|
||
the specified member is not a template where a template is required, or
|
||
|
||
* [(11.4.3)](#11.4.3)
|
||
|
||
the specified member is not a non-type, non-template where a non-type,
|
||
non-template is required[.](#11.4.sentence-1)
|
||
|
||
[*Example [11](#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)](#11.5)
|
||
|
||
Attempting to create a pointer to reference type[.](#11.5.sentence-1)
|
||
|
||
- [(11.6)](#11.6)
|
||
|
||
Attempting to create a reference to void[.](#11.6.sentence-1)
|
||
|
||
- [(11.7)](#11.7)
|
||
|
||
Attempting to create âpointer to member of Tâ when T is not a
|
||
class type[.](#11.7.sentence-1)
|
||
[*Example [12](#example-12)*: template <class T> int f(int T::*);int i = f<int>(0); â *end example*]
|
||
|
||
- [(11.8)](#11.8)
|
||
|
||
Attempting to give an invalid type to a constant template parameter[.](#11.8.sentence-1)
|
||
[*Example [13](#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)](#11.9)
|
||
|
||
Attempting to perform an invalid conversion in either a template
|
||
argument expression, or an expression used in the function
|
||
declaration[.](#11.9.sentence-1)
|
||
[*Example [14](#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)](#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[.](#11.10.sentence-1)
|
||
|
||
- [(11.11)](#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"))[.](#11.11.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[12](#12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8124)
|
||
|
||
[*Example [15](#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"))[.](#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*]
|