1751 lines
91 KiB
Markdown
1751 lines
91 KiB
Markdown
[temp.fct.spec]
|
||
|
||
# 13 Templates [[temp]](./#temp)
|
||
|
||
## 13.10 Function template specializations [temp.fct.spec]
|
||
|
||
### [13.10.1](#general) General [[temp.fct.spec.general]](temp.fct.spec.general)
|
||
|
||
[1](#general-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7526)
|
||
|
||
A function instantiated from a function template is called a function template
|
||
specialization; so is an explicit specialization of a function template[.](#general-1.sentence-1)
|
||
|
||
Template arguments can be explicitly specified when naming the function
|
||
template specialization, deduced from the context (e.g.,
|
||
deduced from the function arguments in a call to the function template
|
||
specialization, see [[temp.deduct]](#temp.deduct "13.10.3 Template argument deduction")), or obtained from default template arguments[.](#general-1.sentence-2)
|
||
|
||
[2](#general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7535)
|
||
|
||
Each function template specialization instantiated from a template
|
||
has its own copy of any static variable[.](#general-2.sentence-1)
|
||
|
||
[*Example [1](#general-example-1)*: template<class T> void f(T* p) {static T s;};
|
||
|
||
void g(int a, char* b) { f(&a); // calls f<int>(int*) f(&b); // calls f<char*>(char**)}
|
||
|
||
Heref<int>(int*) has a static variables of typeint andf<char*>(char**) has a static variables of typechar*[.](#general-2.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
### [13.10.2](#temp.arg.explicit) Explicit template argument specification [[temp.arg.explicit]](temp.arg.explicit)
|
||
|
||
[1](#temp.arg.explicit-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7566)
|
||
|
||
Template arguments can be specified when referring to a function
|
||
template specialization that is not a specialization of a constructor template
|
||
by qualifying the function template
|
||
name with the list of[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* in the same way as[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* are specified in uses of a class template specialization[.](#temp.arg.explicit-1.sentence-1)
|
||
|
||
[*Example [1](#temp.arg.explicit-example-1)*:
|
||
|
||
template<class T> void sort(Array<T>& v);void f(Array<dcomplex>& cv, Array<int>& ci) { sort<dcomplex>(cv); // sort(Array<dcomplex>&) sort<int>(ci); // sort(Array<int>&)} andtemplate<class U, class V> U convert(V v);
|
||
|
||
void g(double d) {int i = convert<int,double>(d); // int convert(double)char c = convert<char,double>(d); // char convert(double)}
|
||
|
||
â *end example*]
|
||
|
||
[2](#temp.arg.explicit-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7595)
|
||
|
||
Template arguments shall not be specified
|
||
when referring to a specialization of
|
||
a constructor template ([[class.ctor]](class.ctor "11.4.5 Constructors"), [[class.qual]](class.qual "6.5.5.2 Class members"))[.](#temp.arg.explicit-2.sentence-1)
|
||
|
||
[3](#temp.arg.explicit-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7600)
|
||
|
||
A template argument list may be specified when referring to a specialization
|
||
of a function template
|
||
|
||
- [(3.1)](#temp.arg.explicit-3.1)
|
||
|
||
when a function is called,
|
||
|
||
- [(3.2)](#temp.arg.explicit-3.2)
|
||
|
||
when the address of a function is taken, when a function initializes a
|
||
reference to function, or when a pointer to member function is formed,
|
||
|
||
- [(3.3)](#temp.arg.explicit-3.3)
|
||
|
||
in an explicit specialization,
|
||
|
||
- [(3.4)](#temp.arg.explicit-3.4)
|
||
|
||
in an explicit instantiation, or
|
||
|
||
- [(3.5)](#temp.arg.explicit-3.5)
|
||
|
||
in a friend declaration[.](#temp.arg.explicit-3.sentence-1)
|
||
|
||
[4](#temp.arg.explicit-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7617)
|
||
|
||
Trailing template arguments that can be deduced ([[temp.deduct]](#temp.deduct "13.10.3 Template argument deduction")) or
|
||
obtained from default [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* may be omitted from the list of explicit [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s*[.](#temp.arg.explicit-4.sentence-1)
|
||
|
||
[*Note [1](#temp.arg.explicit-note-1)*:
|
||
|
||
A trailing template parameter pack ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates")) not otherwise deduced will be
|
||
deduced as an empty sequence of template arguments[.](#temp.arg.explicit-4.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
If all of the template arguments can be
|
||
deduced or obtained from default [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s*,
|
||
they may all be omitted;
|
||
in this case, the empty template argument list <> itself may also be omitted[.](#temp.arg.explicit-4.sentence-3)
|
||
|
||
[*Example [2](#temp.arg.explicit-example-2)*: template<class X, class Y> X f(Y);template<class X, class Y, class ... Z> X g(Y);void h() {int i = f<int>(5.6); // Y deduced as doubleint j = f(5.6); // error: X cannot be deduced f<void>(f<int, bool>); // Y for outer f deduced as int (*)(bool) f<void>(f<int>); // error: f<int> does not denote a single function template specializationint k = g<int>(5.6); // Y deduced as double; Z deduced as an empty sequence f<void>(g<int, bool>); // Y for outer f deduced as int (*)(bool),// Z deduced as an empty sequence} â *end example*]
|
||
|
||
[5](#temp.arg.explicit-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7646)
|
||
|
||
[*Note [2](#temp.arg.explicit-note-2)*:
|
||
|
||
An empty template argument list can be used to indicate that a given
|
||
use refers to a specialization of a function template even when a
|
||
non-template function ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) is visible that would otherwise be used[.](#temp.arg.explicit-5.sentence-1)
|
||
|
||
For example:template <class T> int f(T); // #1int f(int); // #2int k = f(1); // uses #2int l = f<>(1); // uses #1
|
||
|
||
â *end note*]
|
||
|
||
[6](#temp.arg.explicit-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7660)
|
||
|
||
Template arguments that are present shall be specified in the declaration
|
||
order of their corresponding template parameters[.](#temp.arg.explicit-6.sentence-1)
|
||
|
||
The template argument list shall not specify more[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* than there are corresponding[*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* unless one of the [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* declares a template
|
||
parameter pack[.](#temp.arg.explicit-6.sentence-2)
|
||
|
||
[*Example [3](#temp.arg.explicit-example-3)*: template<class X, class Y, class Z> X f(Y,Z);template<class ... Args> void f2();void g() { f<int,const char*,double>("aa",3.0);
|
||
f<int,const char*>("aa",3.0); // Z deduced as double f<int>("aa",3.0); // Y deduced as const char*; Z deduced as double f("aa",3.0); // error: X cannot be deduced f2<char, short, int, long>(); // OK} â *end example*]
|
||
|
||
[7](#temp.arg.explicit-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7683)
|
||
|
||
Implicit conversions ([[conv]](conv "7.3 Standard conversions")) will be performed on a function argument
|
||
to convert it to the type of the corresponding function parameter if
|
||
the parameter type contains no template parameters
|
||
that participate in template argument deduction[.](#temp.arg.explicit-7.sentence-1)
|
||
|
||
[*Note [3](#temp.arg.explicit-note-3)*:
|
||
|
||
Template parameters do not participate in template argument deduction if
|
||
they are explicitly specified[.](#temp.arg.explicit-7.sentence-2)
|
||
|
||
For example,
|
||
|
||
template<class T> void f(T);
|
||
|
||
class Complex { Complex(double);};
|
||
|
||
void g() { f<Complex>(1); // OK, means f<Complex>(Complex(1))} â *end note*]
|
||
|
||
[8](#temp.arg.explicit-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7706)
|
||
|
||
[*Note [4](#temp.arg.explicit-note-4)*:
|
||
|
||
Because the explicit template argument list follows the function
|
||
template name, and because
|
||
constructor templates ([[class.ctor]](class.ctor "11.4.5 Constructors")) are named without using a
|
||
function name ([[class.qual]](class.qual "6.5.5.2 Class members")), there is no way to provide an explicit
|
||
template argument list for these function templates[.](#temp.arg.explicit-8.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[9](#temp.arg.explicit-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7715)
|
||
|
||
Template argument deduction can extend the sequence of template
|
||
arguments corresponding to a template parameter pack, even when the
|
||
sequence contains explicitly specified template arguments[.](#temp.arg.explicit-9.sentence-1)
|
||
|
||
[*Example [4](#temp.arg.explicit-example-4)*: template<class ... Types> void f(Types ... values);
|
||
|
||
void g() { f<int*, float*>(0, 0, 0); // Types deduced as the sequence int*, float*, int} â *end example*]
|
||
|
||
### [13.10.3](#temp.deduct) Template argument deduction [[temp.deduct]](temp.deduct)
|
||
|
||
#### [13.10.3.1](#temp.deduct.general) General [[temp.deduct.general]](temp.deduct.general)
|
||
|
||
[1](#temp.deduct.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[.](#temp.deduct.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*[.](#temp.deduct.general-1.sentence-2)
|
||
|
||
[*Example [1](#temp.deduct.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](#temp.deduct.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[.](#temp.deduct.general-2.sentence-1)
|
||
|
||
Otherwise, the specified template argument values are substituted for the
|
||
corresponding template parameters as specified below[.](#temp.deduct.general-2.sentence-2)
|
||
|
||
[3](#temp.deduct.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[.](#temp.deduct.general-3.sentence-1)
|
||
|
||
[*Example [2](#temp.deduct.general-example-2)*:
|
||
|
||
A parameter type of âvoid (const int, int[5])â becomes
|
||
âvoid(*)(int,int*)â[.](#temp.deduct.general-3.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[*Note [1](#temp.deduct.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[.](#temp.deduct.general-3.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [3](#temp.deduct.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](#temp.deduct.general-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7803)
|
||
|
||
[*Note [2](#temp.deduct.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[.](#temp.deduct.general-4.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[5](#temp.deduct.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[.](#temp.deduct.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[.](#temp.deduct.general-5.sentence-2)
|
||
|
||
If the substitution results in an invalid type,
|
||
as described above, type deduction fails[.](#temp.deduct.general-5.sentence-3)
|
||
|
||
[*Example [4](#temp.deduct.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[.](#temp.deduct.general-5.sentence-4)
|
||
|
||
If the substitution results in an
|
||
invalid type, as described above, type deduction fails[.](#temp.deduct.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"))[.](#temp.deduct.general-5.sentence-6)
|
||
|
||
If the constraints are not satisfied, type deduction fails[.](#temp.deduct.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[.](#temp.deduct.general-5.sentence-8)
|
||
|
||
[*Note [3](#temp.deduct.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[.](#temp.deduct.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[.](#temp.deduct.general-5.sentence-10)
|
||
|
||
If the substitution results in an invalid type, as described above,
|
||
type deduction fails[.](#temp.deduct.general-5.sentence-11)
|
||
|
||
[*Example [5](#temp.deduct.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](#temp.deduct.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[.](#temp.deduct.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[.](#temp.deduct.general-6.sentence-2)
|
||
|
||
[7](#temp.deduct.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)](#temp.deduct.general-7.1)
|
||
|
||
the function type outside of the [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]"),
|
||
|
||
- [(7.2)](#temp.deduct.general-7.2)
|
||
|
||
the [*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3 Function specifiers [dcl.fct.spec]"),
|
||
|
||
- [(7.3)](#temp.deduct.general-7.3)
|
||
|
||
the template parameter declarations, and
|
||
|
||
- [(7.4)](#temp.deduct.general-7.4)
|
||
|
||
the template argument list of a partial specialization ([[temp.spec.partial.general]](temp.spec.partial.general "13.7.6.1 General"))[.](#temp.deduct.general-7.sentence-1)
|
||
|
||
The substitution occurs in all types and expressions that are used
|
||
in the deduction substitution loci[.](#temp.deduct.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[.](#temp.deduct.general-7.sentence-3)
|
||
|
||
The substitution proceeds in lexical order and stops when
|
||
a condition that causes deduction to fail is encountered[.](#temp.deduct.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[.](#temp.deduct.general-7.sentence-5)
|
||
|
||
[*Note [4](#temp.deduct.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[.](#temp.deduct.general-7.sentence-6)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [6](#temp.deduct.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](#temp.deduct.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[.](#temp.deduct.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[.](#temp.deduct.general-8.sentence-2)
|
||
|
||
[*Note [5](#temp.deduct.general-note-5)*:
|
||
|
||
If no diagnostic is required, the program is still ill-formed[.](#temp.deduct.general-8.sentence-3)
|
||
|
||
Access checking is done as part of the substitution process[.](#temp.deduct.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[.](#temp.deduct.general-8.sentence-5)
|
||
|
||
[*Note [6](#temp.deduct.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[.](#temp.deduct.general-8.sentence-6)
|
||
|
||
Such effects are not in the âimmediate contextâ and can result in the
|
||
program being ill-formed[.](#temp.deduct.general-8.sentence-7)
|
||
|
||
â *end note*]
|
||
|
||
[9](#temp.deduct.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[.](#temp.deduct.general-9.sentence-1)
|
||
|
||
[*Note [7](#temp.deduct.general-note-7)*:
|
||
|
||
The intent is to avoid requiring implementations to deal with
|
||
substitution failure involving arbitrary statements[.](#temp.deduct.general-9.sentence-2)
|
||
|
||
[*Example [7](#temp.deduct.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](#temp.deduct.general-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7995)
|
||
|
||
[*Example [8](#temp.deduct.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](#temp.deduct.general-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8011)
|
||
|
||
[*Note [8](#temp.deduct.general-note-8)*:
|
||
|
||
Type deduction can fail for the following reasons:
|
||
|
||
- [(11.1)](#temp.deduct.general-11.1)
|
||
|
||
Attempting to instantiate a pack expansion containing multiple packs of differing lengths[.](#temp.deduct.general-11.1.sentence-1)
|
||
|
||
- [(11.2)](#temp.deduct.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[.](#temp.deduct.general-11.2.sentence-1)
|
||
[*Example [9](#temp.deduct.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)](#temp.deduct.general-11.3)
|
||
|
||
Attempting to use a type that is not a class or enumeration type in a qualified name[.](#temp.deduct.general-11.3.sentence-1)
|
||
[*Example [10](#temp.deduct.general-example-10)*: template <class T> int f(typename T::B*);int i = f<int>(0); â *end example*]
|
||
|
||
- [(11.4)](#temp.deduct.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)](#temp.deduct.general-11.4.1)
|
||
|
||
the specified member is not a type where a type is required, or
|
||
|
||
* [(11.4.2)](#temp.deduct.general-11.4.2)
|
||
|
||
the specified member is not a template where a template is required, or
|
||
|
||
* [(11.4.3)](#temp.deduct.general-11.4.3)
|
||
|
||
the specified member is not a non-type, non-template where a non-type,
|
||
non-template is required[.](#temp.deduct.general-11.4.sentence-1)
|
||
|
||
[*Example [11](#temp.deduct.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)](#temp.deduct.general-11.5)
|
||
|
||
Attempting to create a pointer to reference type[.](#temp.deduct.general-11.5.sentence-1)
|
||
|
||
- [(11.6)](#temp.deduct.general-11.6)
|
||
|
||
Attempting to create a reference to void[.](#temp.deduct.general-11.6.sentence-1)
|
||
|
||
- [(11.7)](#temp.deduct.general-11.7)
|
||
|
||
Attempting to create âpointer to member of Tâ when T is not a
|
||
class type[.](#temp.deduct.general-11.7.sentence-1)
|
||
[*Example [12](#temp.deduct.general-example-12)*: template <class T> int f(int T::*);int i = f<int>(0); â *end example*]
|
||
|
||
- [(11.8)](#temp.deduct.general-11.8)
|
||
|
||
Attempting to give an invalid type to a constant template parameter[.](#temp.deduct.general-11.8.sentence-1)
|
||
[*Example [13](#temp.deduct.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)](#temp.deduct.general-11.9)
|
||
|
||
Attempting to perform an invalid conversion in either a template
|
||
argument expression, or an expression used in the function
|
||
declaration[.](#temp.deduct.general-11.9.sentence-1)
|
||
[*Example [14](#temp.deduct.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)](#temp.deduct.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[.](#temp.deduct.general-11.10.sentence-1)
|
||
|
||
- [(11.11)](#temp.deduct.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"))[.](#temp.deduct.general-11.11.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[12](#temp.deduct.general-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8124)
|
||
|
||
[*Example [15](#temp.deduct.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"))[.](#temp.deduct.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](#temp.deduct.call) Deducing template arguments from a function call [[temp.deduct.call]](temp.deduct.call)
|
||
|
||
[1](#temp.deduct.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[.](#temp.deduct.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[.](#temp.deduct.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[.](#temp.deduct.call-1.sentence-3)
|
||
|
||
Otherwise, an initializer list argument causes the
|
||
parameter to be considered a non-deduced context ([[temp.deduct.type]](#temp.deduct.type "13.10.3.6 Deducing template arguments from a type"))[.](#temp.deduct.call-1.sentence-4)
|
||
|
||
[*Example [1](#temp.deduct.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[.](#temp.deduct.call-1.sentence-5)
|
||
|
||
Each deduction deduces template arguments for subsequent positions in
|
||
the template parameter packs expanded by the function parameter pack[.](#temp.deduct.call-1.sentence-6)
|
||
|
||
When a function parameter pack appears in a non-deduced
|
||
context ([[temp.deduct.type]](#temp.deduct.type "13.10.3.6 Deducing template arguments from a type")), the type of that pack is
|
||
never deduced[.](#temp.deduct.call-1.sentence-7)
|
||
|
||
[*Example [2](#temp.deduct.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](#temp.deduct.call-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8229)
|
||
|
||
IfP is not a reference type:
|
||
|
||
- [(2.1)](#temp.deduct.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)](#temp.deduct.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)](#temp.deduct.call-2.3)
|
||
|
||
IfA is a cv-qualified type, the top-level cv-qualifiers ofA's
|
||
type are ignored for type deduction[.](#temp.deduct.call-2.sentence-1)
|
||
|
||
[3](#temp.deduct.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[.](#temp.deduct.call-3.sentence-1)
|
||
|
||
IfP is a reference type, the type
|
||
referred to byP is used for type deduction[.](#temp.deduct.call-3.sentence-2)
|
||
|
||
[*Example [3](#temp.deduct.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")))[.](#temp.deduct.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[.](#temp.deduct.call-3.sentence-4)
|
||
|
||
[*Example [4](#temp.deduct.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](#temp.deduct.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)[.](#temp.deduct.call-4.sentence-1)
|
||
|
||
However, there are
|
||
three cases that allow a difference:
|
||
|
||
- [(4.1)](#temp.deduct.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[.](#temp.deduct.call-4.1.sentence-1)
|
||
|
||
- [(4.2)](#temp.deduct.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]")[.](#temp.deduct.call-4.2.sentence-1)
|
||
|
||
- [(4.3)](#temp.deduct.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[.](#temp.deduct.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[.](#temp.deduct.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[.](#temp.deduct.call-4.3.sentence-3)
|
||
[*Example [5](#temp.deduct.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](#temp.deduct.call-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8390)
|
||
|
||
These alternatives are considered only if type deduction would
|
||
otherwise fail[.](#temp.deduct.call-5.sentence-1)
|
||
|
||
If they yield more than one possible deducedA,
|
||
the type deduction fails[.](#temp.deduct.call-5.sentence-2)
|
||
|
||
[*Note [1](#temp.deduct.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[.](#temp.deduct.call-5.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[6](#temp.deduct.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)](#temp.deduct.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[.](#temp.deduct.call-6.1.sentence-1)
|
||
|
||
- [(6.2)](#temp.deduct.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[.](#temp.deduct.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[.](#temp.deduct.call-6.2.sentence-2)
|
||
|
||
[7](#temp.deduct.call-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8423)
|
||
|
||
[*Example [6](#temp.deduct.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](#temp.deduct.call-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8434)
|
||
|
||
[*Example [7](#temp.deduct.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](#temp.deduct.call-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8445)
|
||
|
||
[*Example [8](#temp.deduct.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](#temp.deduct.call-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8456)
|
||
|
||
[*Example [9](#temp.deduct.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](#temp.deduct.funcaddr) Deducing template arguments taking the address of a function template [[temp.deduct.funcaddr]](temp.deduct.funcaddr)
|
||
|
||
[1](#temp.deduct.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]")[.](#temp.deduct.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]](#temp.deduct.type "13.10.3.6 Deducing template arguments from a type")[.](#temp.deduct.funcaddr-1.sentence-2)
|
||
|
||
Otherwise, deduction is performed with empty sets of types P and A[.](#temp.deduct.funcaddr-1.sentence-3)
|
||
|
||
[2](#temp.deduct.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[.](#temp.deduct.funcaddr-2.sentence-1)
|
||
|
||
If template argument
|
||
deduction succeeds for such a function, the return type is determined
|
||
from instantiation of the function body[.](#temp.deduct.funcaddr-2.sentence-2)
|
||
|
||
#### [13.10.3.4](#temp.deduct.conv) Deducing conversion function template arguments [[temp.deduct.conv]](temp.deduct.conv)
|
||
|
||
[1](#temp.deduct.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]](#temp.deduct.type "13.10.3.6 Deducing template arguments from a type")[.](#temp.deduct.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[.](#temp.deduct.conv-1.sentence-2)
|
||
|
||
[2](#temp.deduct.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[.](#temp.deduct.conv-2.sentence-1)
|
||
|
||
[3](#temp.deduct.conv-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8512)
|
||
|
||
IfA is not a reference type:
|
||
|
||
- [(3.1)](#temp.deduct.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)](#temp.deduct.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)](#temp.deduct.conv-3.3)
|
||
|
||
IfP is a cv-qualified type, the top-level cv-qualifiers ofP's
|
||
type are ignored for type deduction[.](#temp.deduct.conv-3.sentence-1)
|
||
|
||
[4](#temp.deduct.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[.](#temp.deduct.conv-4.sentence-1)
|
||
|
||
IfA is a
|
||
reference type, the type referred to byA is used for type deduction[.](#temp.deduct.conv-4.sentence-2)
|
||
|
||
[5](#temp.deduct.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[.](#temp.deduct.conv-5.sentence-1)
|
||
|
||
However, certain attributes of A may be ignored:
|
||
|
||
- [(5.1)](#temp.deduct.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)[.](#temp.deduct.conv-5.1.sentence-1)
|
||
|
||
- [(5.2)](#temp.deduct.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[.](#temp.deduct.conv-5.2.sentence-1)
|
||
|
||
- [(5.3)](#temp.deduct.conv-5.3)
|
||
|
||
Any cv-qualifiers in A that can be restored by a qualification conversion[.](#temp.deduct.conv-5.3.sentence-1)
|
||
|
||
These attributes are ignored only if type deduction would
|
||
otherwise fail[.](#temp.deduct.conv-5.sentence-3)
|
||
|
||
If ignoring them allows more than one possible deducedA,
|
||
the type deduction fails[.](#temp.deduct.conv-5.sentence-4)
|
||
|
||
#### [13.10.3.5](#temp.deduct.partial) Deducing template arguments during partial ordering [[temp.deduct.partial]](temp.deduct.partial)
|
||
|
||
[1](#temp.deduct.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[.](#temp.deduct.partial-1.sentence-1)
|
||
|
||
[2](#temp.deduct.partial-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8587)
|
||
|
||
Two sets of types are used to determine the partial ordering[.](#temp.deduct.partial-2.sentence-1)
|
||
|
||
For each of
|
||
the templates involved there is the original function type and the
|
||
transformed function type[.](#temp.deduct.partial-2.sentence-2)
|
||
|
||
[*Note [1](#temp.deduct.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")[.](#temp.deduct.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[.](#temp.deduct.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[.](#temp.deduct.partial-2.sentence-5)
|
||
|
||
[3](#temp.deduct.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)](#temp.deduct.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[.](#temp.deduct.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)](#temp.deduct.partial-3.2)
|
||
|
||
In the context of a call to a conversion function, the return types of
|
||
the conversion function templates are used[.](#temp.deduct.partial-3.2.sentence-1)
|
||
|
||
- [(3.3)](#temp.deduct.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[.](#temp.deduct.partial-3.3.sentence-1)
|
||
|
||
[4](#temp.deduct.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[.](#temp.deduct.partial-4.sentence-1)
|
||
|
||
[5](#temp.deduct.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)](#temp.deduct.partial-5.1)
|
||
|
||
IfP is a reference type,P is replaced by the type referred to[.](#temp.deduct.partial-5.1.sentence-1)
|
||
|
||
- [(5.2)](#temp.deduct.partial-5.2)
|
||
|
||
IfA is a reference type,A is replaced by the type referred to[.](#temp.deduct.partial-5.2.sentence-1)
|
||
|
||
[6](#temp.deduct.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[.](#temp.deduct.partial-6.sentence-1)
|
||
|
||
The result of this
|
||
determination will be used below[.](#temp.deduct.partial-6.sentence-2)
|
||
|
||
[7](#temp.deduct.partial-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8658)
|
||
|
||
Remove any top-level cv-qualifiers:
|
||
|
||
- [(7.1)](#temp.deduct.partial-7.1)
|
||
|
||
IfP is a cv-qualified type,P is replaced by the cv-unqualified version ofP[.](#temp.deduct.partial-7.1.sentence-1)
|
||
|
||
- [(7.2)](#temp.deduct.partial-7.2)
|
||
|
||
IfA is a cv-qualified type,A is replaced by the cv-unqualified version ofA[.](#temp.deduct.partial-7.2.sentence-1)
|
||
|
||
[8](#temp.deduct.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]](#temp.deduct.type "13.10.3.6 Deducing template arguments from a type")[.](#temp.deduct.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[.](#temp.deduct.partial-8.sentence-2)
|
||
|
||
Each comparison
|
||
deduces template arguments for subsequent positions in the template parameter
|
||
packs expanded by the function parameter pack[.](#temp.deduct.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[.](#temp.deduct.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[.](#temp.deduct.partial-8.sentence-5)
|
||
|
||
[*Example [1](#temp.deduct.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](#temp.deduct.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)](#temp.deduct.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)](#temp.deduct.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[.](#temp.deduct.partial-9.sentence-1)
|
||
|
||
[10](#temp.deduct.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[.](#temp.deduct.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[.](#temp.deduct.partial-10.sentence-2)
|
||
|
||
[11](#temp.deduct.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[.](#temp.deduct.partial-11.sentence-1)
|
||
|
||
[12](#temp.deduct.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[.](#temp.deduct.partial-12.sentence-1)
|
||
|
||
[*Note [2](#temp.deduct.partial-note-2)*:
|
||
|
||
A template parameter used in a non-deduced context is considered used[.](#temp.deduct.partial-12.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [2](#temp.deduct.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](#temp.deduct.partial-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8769)
|
||
|
||
[*Note [3](#temp.deduct.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[.](#temp.deduct.partial-13.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [3](#temp.deduct.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](#temp.deduct.type) Deducing template arguments from a type [[temp.deduct.type]](temp.deduct.type)
|
||
|
||
[1](#temp.deduct.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[.](#temp.deduct.type-1.sentence-1)
|
||
|
||
[2](#temp.deduct.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[.](#temp.deduct.type-2.sentence-1)
|
||
|
||
Type deduction is done
|
||
independently for eachP/A pair, and the deduced template
|
||
argument values are then combined[.](#temp.deduct.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[.](#temp.deduct.type-2.sentence-3)
|
||
|
||
The type of a type parameter
|
||
is only deduced from an array bound
|
||
if it is not otherwise deduced[.](#temp.deduct.type-2.sentence-4)
|
||
|
||
[3](#temp.deduct.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)](#temp.deduct.type-3.1)
|
||
|
||
A function type includes the types of each of the function parameters,
|
||
the return type, and its exception specification[.](#temp.deduct.type-3.1.sentence-1)
|
||
|
||
- [(3.2)](#temp.deduct.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[.](#temp.deduct.type-3.2.sentence-1)
|
||
|
||
- [(3.3)](#temp.deduct.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[.](#temp.deduct.type-3.3.sentence-1)
|
||
|
||
- [(3.4)](#temp.deduct.type-3.4)
|
||
|
||
An array type includes the array element type and the value of the
|
||
array bound[.](#temp.deduct.type-3.4.sentence-1)
|
||
|
||
[4](#temp.deduct.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[.](#temp.deduct.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[.](#temp.deduct.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[.](#temp.deduct.type-4.sentence-3)
|
||
|
||
If a template parameter is used only in non-deduced contexts and is not
|
||
explicitly specified, template argument deduction fails[.](#temp.deduct.type-4.sentence-4)
|
||
|
||
[*Note [1](#temp.deduct.type-note-1)*:
|
||
|
||
Under [[temp.deduct.call]](#temp.deduct.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[.](#temp.deduct.type-4.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
[5](#temp.deduct.type-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8876)
|
||
|
||
The non-deduced contexts are:
|
||
|
||
- [(5.1)](#temp.deduct.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]")[.](#temp.deduct.type-5.1.sentence-1)
|
||
|
||
- [(5.2)](#temp.deduct.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]")[.](#temp.deduct.type-5.2.sentence-1)
|
||
|
||
- [(5.3)](#temp.deduct.type-5.3)
|
||
|
||
A [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")[.](#temp.deduct.type-5.3.sentence-1)
|
||
|
||
- [(5.4)](#temp.deduct.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]")[.](#temp.deduct.type-5.4.sentence-1)
|
||
|
||
- [(5.5)](#temp.deduct.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]")[.](#temp.deduct.type-5.5.sentence-1)
|
||
|
||
- [(5.6)](#temp.deduct.type-5.6)
|
||
|
||
A constant template argument or an array bound in which a subexpression
|
||
references a template parameter[.](#temp.deduct.type-5.6.sentence-1)
|
||
|
||
- [(5.7)](#temp.deduct.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[.](#temp.deduct.type-5.7.sentence-1)
|
||
|
||
- [(5.8)](#temp.deduct.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)](#temp.deduct.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)](#temp.deduct.type-5.8.2)
|
||
|
||
no function whose associated constraints are satisfied
|
||
matches the function parameter type, or
|
||
|
||
* [(5.8.3)](#temp.deduct.type-5.8.3)
|
||
|
||
the overload set supplied as an argument contains one or more function templates[.](#temp.deduct.type-5.8.sentence-1)
|
||
|
||
[*Note [2](#temp.deduct.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"))[.](#temp.deduct.type-5.8.sentence-2)
|
||
â *end note*]
|
||
|
||
- [(5.9)](#temp.deduct.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]](#temp.deduct.call "13.10.3.2 Deducing template arguments from a function call"))[.](#temp.deduct.type-5.9.sentence-1)
|
||
[*Example [1](#temp.deduct.type-example-1)*: template<class T> void g(T);
|
||
g({1,2,3}); // error: no argument deduced for T â *end example*]
|
||
|
||
- [(5.10)](#temp.deduct.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]")[.](#temp.deduct.type-5.10.sentence-1)
|
||
|
||
[6](#temp.deduct.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[.](#temp.deduct.type-6.sentence-1)
|
||
|
||
However, a compound type can include both deduced and non-deduced types[.](#temp.deduct.type-6.sentence-2)
|
||
|
||
[*Example [2](#temp.deduct.type-example-2)*:
|
||
|
||
If a type is specified asA<T>::B<T2>,
|
||
bothT andT2 are non-deduced[.](#temp.deduct.type-6.sentence-3)
|
||
|
||
Likewise, if a type is specified asA<I+J>::X<T>,I,J,
|
||
andT are non-deduced[.](#temp.deduct.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[.](#temp.deduct.type-6.sentence-5)
|
||
|
||
â *end example*]
|
||
|
||
[7](#temp.deduct.type-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8968)
|
||
|
||
[*Example [3](#temp.deduct.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[.](#temp.deduct.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](#temp.deduct.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)](#temp.deduct.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)](#temp.deduct.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)](#temp.deduct.type-8.3)
|
||
|
||
TTopt represents either a class template or
|
||
a template template parameter, and
|
||
|
||
- [(8.4)](#temp.deduct.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[.](#temp.deduct.type-8.sentence-1)
|
||
|
||
[*Note [3](#temp.deduct.type-note-3)*:
|
||
|
||
If a type matches such a form but contains noTs, is, or TTs, deduction is not possible[.](#temp.deduct.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[.](#temp.deduct.type-8.sentence-3)
|
||
|
||
[9](#temp.deduct.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[.](#temp.deduct.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[.](#temp.deduct.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[.](#temp.deduct.type-9.sentence-3)
|
||
|
||
Each comparison deduces
|
||
template arguments for subsequent positions in the template parameter
|
||
packs expanded by Pi[.](#temp.deduct.type-9.sentence-4)
|
||
|
||
During [partial ordering](#temp.deduct.partial "13.10.3.5 Deducing template arguments during partial ordering [temp.deduct.partial]"), if Ai was
|
||
originally a pack expansion:
|
||
|
||
- [(9.1)](#temp.deduct.type-9.1)
|
||
|
||
if P does not contain a template argument corresponding toAi then Ai is ignored;
|
||
|
||
- [(9.2)](#temp.deduct.type-9.2)
|
||
|
||
otherwise, if Pi is not a pack expansion, template argument
|
||
deduction fails[.](#temp.deduct.type-9.sentence-5)
|
||
|
||
[*Example [4](#temp.deduct.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](#temp.deduct.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[.](#temp.deduct.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]](#temp.deduct.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]](#temp.deduct.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]](#temp.deduct.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)[.](#temp.deduct.type-10.sentence-2)
|
||
|
||
[*Note [4](#temp.deduct.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&[.](#temp.deduct.type-10.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [5](#temp.deduct.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[.](#temp.deduct.type-10.sentence-4)
|
||
|
||
Each comparison deduces template arguments for
|
||
subsequent positions in the template parameter packs expanded by the
|
||
function parameter pack[.](#temp.deduct.type-10.sentence-5)
|
||
|
||
During [partial ordering](#temp.deduct.partial "13.10.3.5 Deducing template arguments during partial ordering [temp.deduct.partial]"), if Ai was
|
||
originally a function parameter pack:
|
||
|
||
- [(10.1)](#temp.deduct.type-10.1)
|
||
|
||
if P does not contain a function parameter type corresponding toAi then Ai is ignored;
|
||
|
||
- [(10.2)](#temp.deduct.type-10.2)
|
||
|
||
otherwise, if Pi is not a function parameter pack, template
|
||
argument deduction fails[.](#temp.deduct.type-10.sentence-6)
|
||
|
||
[*Example [6](#temp.deduct.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](#temp.deduct.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[.](#temp.deduct.type-11.sentence-1)
|
||
|
||
[*Example [7](#temp.deduct.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][.](#temp.deduct.type-11.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[12](#temp.deduct.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[.](#temp.deduct.type-12.sentence-1)
|
||
|
||
[13](#temp.deduct.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[.](#temp.deduct.type-13.sentence-1)
|
||
|
||
[*Example [8](#temp.deduct.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](#temp.deduct.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[.](#temp.deduct.type-14.sentence-1)
|
||
|
||
[*Example [9](#temp.deduct.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](#temp.deduct.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[.](#temp.deduct.type-15.sentence-1)
|
||
|
||
[*Example [10](#temp.deduct.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](#temp.deduct.type-16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9285)
|
||
|
||
[*Example [11](#temp.deduct.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](#temp.deduct.type-17)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9296)
|
||
|
||
[*Note [5](#temp.deduct.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](#temp.deduct.type-18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9316)
|
||
|
||
[*Note [6](#temp.deduct.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[.](#temp.deduct.type-18.sentence-1)
|
||
|
||
[*Example [12](#temp.deduct.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](#temp.deduct.type-19)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9338)
|
||
|
||
[*Note [7](#temp.deduct.type-note-7)*:
|
||
|
||
Template parameters do not participate in template argument deduction if
|
||
they are used only in non-deduced contexts[.](#temp.deduct.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](#temp.deduct.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[.](#temp.deduct.type-20.sentence-1)
|
||
|
||
If P has a form that contains [i], and if the type ofi is not an integral type, deduction fails[.](#temp.deduct.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[.](#temp.deduct.type-20.sentence-3)
|
||
|
||
[*Example [13](#temp.deduct.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](#temp.deduct.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[.](#temp.deduct.type-21.sentence-1)
|
||
|
||
[*Example [14](#temp.deduct.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](#temp.deduct.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[.](#temp.deduct.type-22.sentence-1)
|
||
|
||
[*Example [15](#temp.deduct.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](#temp.deduct.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[.](#temp.deduct.type-23.sentence-1)
|
||
|
||
[*Example [16](#temp.deduct.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](#temp.deduct.type-24)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9451)
|
||
|
||
[*Note [8](#temp.deduct.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[.](#temp.deduct.type-24.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [17](#temp.deduct.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](#temp.deduct.decl) Deducing template arguments from a function declaration [[temp.deduct.decl]](temp.deduct.decl)
|
||
|
||
[1](#temp.deduct.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[.](#temp.deduct.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]")[.](#temp.deduct.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"))[.](#temp.deduct.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")[.](#temp.deduct.decl-1.sentence-4)
|
||
|
||
The
|
||
deduction is done as described in [[temp.deduct.type]](#temp.deduct.type "13.10.3.6 Deducing template arguments from a type")[.](#temp.deduct.decl-1.sentence-5)
|
||
|
||
[2](#temp.deduct.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[.](#temp.deduct.decl-2.sentence-1)
|
||
|
||
### [13.10.4](#temp.over) Overload resolution [[temp.over]](temp.over)
|
||
|
||
[1](#temp.over-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9502)
|
||
|
||
When a call of a function or function template
|
||
is written (explicitly, or implicitly using the
|
||
operator notation), template argument deduction ([[temp.deduct]](#temp.deduct "13.10.3 Template argument deduction"))
|
||
and checking of any explicit template arguments ([[temp.arg]](temp.arg "13.4 Template arguments")) are performed
|
||
for each function template to find the template argument values (if any) that
|
||
can be used with that function template to instantiate a function template
|
||
specialization that can be invoked with the call arguments or,
|
||
for conversion function templates, that can convert to the required type[.](#temp.over-1.sentence-1)
|
||
|
||
For each function template:
|
||
|
||
- [(1.1)](#temp.over-1.1)
|
||
|
||
If the argument deduction and checking succeeds, the[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s* (deduced and/or explicit)
|
||
are used to synthesize the declaration of
|
||
a single function template specialization which is
|
||
added to the candidate functions set to be used in overload resolution[.](#temp.over-1.1.sentence-1)
|
||
|
||
- [(1.2)](#temp.over-1.2)
|
||
|
||
If the argument deduction fails or
|
||
the synthesized function template specialization would be ill-formed,
|
||
no such function is added to the set of candidate functions for that template[.](#temp.over-1.2.sentence-1)
|
||
|
||
The complete set of candidate functions includes all the synthesized
|
||
declarations and all of the non-template functions found by name lookup[.](#temp.over-1.sentence-3)
|
||
|
||
The synthesized declarations are
|
||
treated like any other functions in
|
||
the remainder of overload resolution, except as explicitly noted
|
||
in [[over.match.best]](over.match.best "12.2.4 Best viable function")[.](#temp.over-1.sentence-4)[121](#footnote-121 "The parameters of function template specializations contain no template parameter types. The set of conversions allowed on deduced arguments is limited, because the argument deduction process produces function templates with parameters that either match the call arguments exactly or differ only in ways that can be bridged by the allowed limited conversions. Non-deduced arguments allow the full range of conversions. Note also that [over.match.best] specifies that a non-template function will be given preference over a template specialization if the two functions are otherwise equally good candidates for an overload match.")
|
||
|
||
[2](#temp.over-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9544)
|
||
|
||
[*Example [1](#temp.over-example-1)*: template<class T> T max(T a, T b) { return a>b?a:b; }void f(int a, int b, char c, char d) {int m1 = max(a,b); // max(int a, int b)char m2 = max(c,d); // max(char a, char b)int m3 = max(a,c); // error: cannot generate max(int,char)}
|
||
|
||
Adding the non-template functionint max(int,int); to the example above would resolve the third call, by providing a function that
|
||
can be called formax(a,c) after using the standard conversion ofchar toint forc[.](#temp.over-2.sentence-1)
|
||
|
||
â *end example*]
|
||
|
||
[3](#temp.over-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9571)
|
||
|
||
[*Example [2](#temp.over-example-2)*:
|
||
|
||
Here is an example involving conversions on a function argument involved in
|
||
template argument deduction:template<class T> struct B { /* ... */ };template<class T> struct D : public B<T> { /* ... */ };template<class T> void f(B<T>&);
|
||
|
||
void g(B<int>& bi, D<int>& di) { f(bi); // f(bi) f(di); // f((B<int>&)di)}
|
||
|
||
â *end example*]
|
||
|
||
[4](#temp.over-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9587)
|
||
|
||
[*Example [3](#temp.over-example-3)*:
|
||
|
||
Here is an example involving conversions on a function argument not involved in
|
||
template argument deduction:template<class T> void f(T*,int); // #1template<class T> void f(T,char); // #2void h(int* pi, int i, char c) { f(pi,i); // #1: f<int>(pi,i) f(pi,c); // #2: f<int*>(pi,c) f(i,c); // #2: f<int>(i,c); f(i,i); // #2: f<int>(i,char(i))}
|
||
|
||
â *end example*]
|
||
|
||
[5](#temp.over-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9605)
|
||
|
||
Only the signature of a function template specialization is needed to enter the
|
||
specialization in a set of candidate functions[.](#temp.over-5.sentence-1)
|
||
|
||
Therefore only the function template declaration is needed to resolve a call
|
||
for which a template specialization is a candidate[.](#temp.over-5.sentence-2)
|
||
|
||
[*Example [4](#temp.over-example-4)*: template<class T> void f(T); // declarationvoid g() { f("Annemarie"); // calls f<const char*>}
|
||
|
||
The call tof is well-formed even if the templatef is only declared and not defined at the point of the call[.](#temp.over-5.sentence-3)
|
||
|
||
The program will be ill-formed unless a specialization forf<const char*> is explicitly instantiated in some translation unit ([[temp.pre]](temp.pre "13.1 Preamble"))[.](#temp.over-5.sentence-4)
|
||
|
||
â *end example*]
|
||
|
||
[121)](#footnote-121)[121)](#footnoteref-121)
|
||
|
||
The parameters of function template
|
||
specializations contain no
|
||
template parameter types[.](#footnote-121.sentence-1)
|
||
|
||
The set of conversions allowed on deduced arguments is limited, because the
|
||
argument deduction process produces function templates with parameters that
|
||
either match the call arguments exactly or differ only in ways that can be
|
||
bridged by the allowed limited conversions[.](#footnote-121.sentence-2)
|
||
|
||
Non-deduced arguments allow the full range of conversions[.](#footnote-121.sentence-3)
|
||
|
||
Note also that [[over.match.best]](over.match.best "12.2.4 Best viable function") specifies that a non-template function will
|
||
be given preference over a template specialization if the two functions
|
||
are otherwise equally good candidates for an overload match[.](#footnote-121.sentence-4)
|