Init
This commit is contained in:
208
cppdraft/temp/deduct/call.md
Normal file
208
cppdraft/temp/deduct/call.md
Normal file
@@ -0,0 +1,208 @@
|
||||
[temp.deduct.call]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct.call)
|
||||
|
||||
### 13.10.3 Template argument deduction [[temp.deduct]](temp.deduct#call)
|
||||
|
||||
#### 13.10.3.2 Deducing template arguments from a function call [temp.deduct.call]
|
||||
|
||||
[1](#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[.](#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[.](#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[.](#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"))[.](#1.sentence-4)
|
||||
|
||||
[*Example [1](#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[.](#1.sentence-5)
|
||||
|
||||
Each deduction deduces template arguments for subsequent positions in
|
||||
the template parameter packs expanded by the function parameter pack[.](#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[.](#1.sentence-7)
|
||||
|
||||
[*Example [2](#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](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8229)
|
||||
|
||||
IfP is not a reference type:
|
||||
|
||||
- [(2.1)](#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)](#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)](#2.3)
|
||||
|
||||
IfA is a cv-qualified type, the top-level cv-qualifiers ofA's
|
||||
type are ignored for type deduction[.](#2.sentence-1)
|
||||
|
||||
[3](#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[.](#3.sentence-1)
|
||||
|
||||
IfP is a reference type, the type
|
||||
referred to byP is used for type deduction[.](#3.sentence-2)
|
||||
|
||||
[*Example [3](#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")))[.](#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[.](#3.sentence-4)
|
||||
|
||||
[*Example [4](#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](#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)[.](#4.sentence-1)
|
||||
|
||||
However, there are
|
||||
three cases that allow a difference:
|
||||
|
||||
- [(4.1)](#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[.](#4.1.sentence-1)
|
||||
|
||||
- [(4.2)](#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]")[.](#4.2.sentence-1)
|
||||
|
||||
- [(4.3)](#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[.](#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[.](#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[.](#4.3.sentence-3)
|
||||
[*Example [5](#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](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8390)
|
||||
|
||||
These alternatives are considered only if type deduction would
|
||||
otherwise fail[.](#5.sentence-1)
|
||||
|
||||
If they yield more than one possible deducedA,
|
||||
the type deduction fails[.](#5.sentence-2)
|
||||
|
||||
[*Note [1](#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[.](#5.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[6](#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)](#6.1)
|
||||
|
||||
If the argument is an overload set containing one or more function templates,
|
||||
the parameter is treated as a non-deduced context[.](#6.1.sentence-1)
|
||||
|
||||
- [(6.2)](#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[.](#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[.](#6.2.sentence-2)
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8423)
|
||||
|
||||
[*Example [6](#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](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8434)
|
||||
|
||||
[*Example [7](#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](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8445)
|
||||
|
||||
[*Example [8](#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](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8456)
|
||||
|
||||
[*Example [9](#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*]
|
||||
93
cppdraft/temp/deduct/conv.md
Normal file
93
cppdraft/temp/deduct/conv.md
Normal file
@@ -0,0 +1,93 @@
|
||||
[temp.deduct.conv]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct.conv)
|
||||
|
||||
### 13.10.3 Template argument deduction [[temp.deduct]](temp.deduct#conv)
|
||||
|
||||
#### 13.10.3.4 Deducing conversion function template arguments [temp.deduct.conv]
|
||||
|
||||
[1](#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")[.](#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[.](#1.sentence-2)
|
||||
|
||||
[2](#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[.](#2.sentence-1)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8512)
|
||||
|
||||
IfA is not a reference type:
|
||||
|
||||
- [(3.1)](#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)](#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)](#3.3)
|
||||
|
||||
IfP is a cv-qualified type, the top-level cv-qualifiers ofP's
|
||||
type are ignored for type deduction[.](#3.sentence-1)
|
||||
|
||||
[4](#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[.](#4.sentence-1)
|
||||
|
||||
IfA is a
|
||||
reference type, the type referred to byA is used for type deduction[.](#4.sentence-2)
|
||||
|
||||
[5](#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[.](#5.sentence-1)
|
||||
|
||||
However, certain attributes of A may be ignored:
|
||||
|
||||
- [(5.1)](#5.1)
|
||||
|
||||
If the original A is a reference type,
|
||||
any cv-qualifiers of A (i.e., the type referred to by the reference)[.](#5.1.sentence-1)
|
||||
|
||||
- [(5.2)](#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[.](#5.2.sentence-1)
|
||||
|
||||
- [(5.3)](#5.3)
|
||||
|
||||
Any cv-qualifiers in A that can be restored by a qualification conversion[.](#5.3.sentence-1)
|
||||
|
||||
These attributes are ignored only if type deduction would
|
||||
otherwise fail[.](#5.sentence-3)
|
||||
|
||||
If ignoring them allows more than one possible deducedA,
|
||||
the type deduction fails[.](#5.sentence-4)
|
||||
41
cppdraft/temp/deduct/decl.md
Normal file
41
cppdraft/temp/deduct/decl.md
Normal file
@@ -0,0 +1,41 @@
|
||||
[temp.deduct.decl]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct.decl)
|
||||
|
||||
### 13.10.3 Template argument deduction [[temp.deduct]](temp.deduct#decl)
|
||||
|
||||
#### 13.10.3.7 Deducing template arguments from a function declaration [temp.deduct.decl]
|
||||
|
||||
[1](#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[.](#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]")[.](#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"))[.](#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")[.](#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")[.](#1.sentence-5)
|
||||
|
||||
[2](#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[.](#2.sentence-1)
|
||||
35
cppdraft/temp/deduct/funcaddr.md
Normal file
35
cppdraft/temp/deduct/funcaddr.md
Normal file
@@ -0,0 +1,35 @@
|
||||
[temp.deduct.funcaddr]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct.funcaddr)
|
||||
|
||||
### 13.10.3 Template argument deduction [[temp.deduct]](temp.deduct#funcaddr)
|
||||
|
||||
#### 13.10.3.3 Deducing template arguments taking the address of a function template [temp.deduct.funcaddr]
|
||||
|
||||
[1](#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]")[.](#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")[.](#1.sentence-2)
|
||||
|
||||
Otherwise, deduction is performed with empty sets of types P and A[.](#1.sentence-3)
|
||||
|
||||
[2](#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[.](#2.sentence-1)
|
||||
|
||||
If template argument
|
||||
deduction succeeds for such a function, the return type is determined
|
||||
from instantiation of the function body[.](#2.sentence-2)
|
||||
368
cppdraft/temp/deduct/general.md
Normal file
368
cppdraft/temp/deduct/general.md
Normal file
@@ -0,0 +1,368 @@
|
||||
[temp.deduct.general]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct.general)
|
||||
|
||||
### 13.10.3 Template argument deduction [[temp.deduct]](temp.deduct#general)
|
||||
|
||||
#### 13.10.3.1 General [temp.deduct.general]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7733)
|
||||
|
||||
When a
|
||||
function template
|
||||
specialization is referenced, all of the
|
||||
template arguments shall have values[.](#1.sentence-1)
|
||||
|
||||
The values can be
|
||||
explicitly specified or, in some cases, be deduced from the use
|
||||
or obtained from default[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]")*s*[.](#1.sentence-2)
|
||||
|
||||
[*Example [1](#example-1)*:
|
||||
|
||||
void f(Array<dcomplex>& cv, Array<int>& ci) { sort(cv); // calls sort(Array<dcomplex>&) sort(ci); // calls sort(Array<int>&)} andvoid g(double d) {int i = convert<int>(d); // calls convert<int,double>(double)int c = convert<char>(d); // calls convert<char,double>(double)}
|
||||
|
||||
â *end example*]
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7758)
|
||||
|
||||
When an explicit template argument list is specified, if the
|
||||
given [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]") is not valid ([[temp.names]](temp.names "13.3 Names of template specializations")),
|
||||
type deduction fails[.](#2.sentence-1)
|
||||
|
||||
Otherwise, the specified template argument values are substituted for the
|
||||
corresponding template parameters as specified below[.](#2.sentence-2)
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7766)
|
||||
|
||||
After this substitution is performed, the function parameter type
|
||||
adjustments described in [[dcl.fct]](dcl.fct "9.3.4.6 Functions") are performed[.](#3.sentence-1)
|
||||
|
||||
[*Example [2](#example-2)*:
|
||||
|
||||
A parameter type of âvoid (const int, int[5])â becomes
|
||||
âvoid(*)(int,int*)â[.](#3.sentence-2)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
A top-level qualifier in a function parameter declaration does not affect
|
||||
the function type but still affects the type of the function parameter
|
||||
variable within the function[.](#3.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [3](#example-3)*: template <class T> void f(T t);template <class X> void g(const X x);template <class Z> void h(Z, Z*);
|
||||
|
||||
int main() {// #1: function type is f(int), t is non const f<int>(1); // #2: function type is f(int), t is const f<const int>(1); // #3: function type is g(int), x is const g<int>(1); // #4: function type is g(int), x is const g<const int>(1); // #5: function type is h(int, const int*) h<const int>(1,0);} â *end example*]
|
||||
|
||||
[4](#4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7803)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
f<int>(1) and f<const int>(1) call distinct functions
|
||||
even though both of the functions called have the same function type[.](#4.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7809)
|
||||
|
||||
The resulting substituted and adjusted function type is used as
|
||||
the type of the function template for template argument
|
||||
deduction[.](#5.sentence-1)
|
||||
|
||||
If a template argument has not been deduced and its
|
||||
corresponding template parameter has a default argument, the
|
||||
template argument is determined by substituting the template
|
||||
arguments determined for preceding template parameters into the
|
||||
default argument[.](#5.sentence-2)
|
||||
|
||||
If the substitution results in an invalid type,
|
||||
as described above, type deduction fails[.](#5.sentence-3)
|
||||
|
||||
[*Example [4](#example-4)*: template <class T, class U = double>void f(T t = 0, U u = 0);
|
||||
|
||||
void g() { f(1, 'c'); // f<int,char>(1,'c') f(1); // f<int,double>(1,0) f(); // error: T cannot be deduced f<int>(); // f<int,double>(0,0) f<int,char>(); // f<int,char>(0,0)} â *end example*]
|
||||
|
||||
When all template arguments have been deduced or obtained from
|
||||
default template arguments, all uses of template parameters in
|
||||
the template parameter list of the template
|
||||
are replaced with the corresponding deduced
|
||||
or default argument values[.](#5.sentence-4)
|
||||
|
||||
If the substitution results in an
|
||||
invalid type, as described above, type deduction fails[.](#5.sentence-5)
|
||||
|
||||
If the function template has associated constraints ([[temp.constr.decl]](temp.constr.decl "13.5.3 Constrained declarations")),
|
||||
those constraints are checked for satisfaction ([[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints"))[.](#5.sentence-6)
|
||||
|
||||
If the constraints are not satisfied, type deduction fails[.](#5.sentence-7)
|
||||
|
||||
In the context of a function call, if type deduction has not yet failed, then
|
||||
for those function parameters for which the function call has arguments,
|
||||
each function parameter with a type that was non-dependent
|
||||
before substitution of any explicitly-specified template arguments
|
||||
is checked against its corresponding argument;
|
||||
if the corresponding argument cannot be implicitly converted
|
||||
to the parameter type, type deduction fails[.](#5.sentence-8)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
Overload resolution will check the other parameters, including
|
||||
parameters with dependent types in which
|
||||
no template parameters participate in template argument deduction and
|
||||
parameters that became non-dependent due to substitution of
|
||||
explicitly-specified template arguments[.](#5.sentence-9)
|
||||
|
||||
â *end note*]
|
||||
|
||||
If type deduction has not yet failed, then
|
||||
all uses of template parameters in the function type are
|
||||
replaced with the corresponding deduced or default argument values[.](#5.sentence-10)
|
||||
|
||||
If the substitution results in an invalid type, as described above,
|
||||
type deduction fails[.](#5.sentence-11)
|
||||
|
||||
[*Example [5](#example-5)*: template <class T> struct Z {typedef typename T::x xx;};template <class T> concept C = requires { typename T::A; };template <C T> typename Z<T>::xx f(void *, T); // #1template <class T> void f(int, T); // #2struct A {} a;struct ZZ {template <class T, class = typename Z<T>::xx> operator T *(); operator int();};int main() { ZZ zz;
|
||||
f(1, a); // OK, deduction fails for #1 because there is no conversion from int to void* f(zz, 42); // OK, deduction fails for #1 because C<int> is not satisfied} â *end example*]
|
||||
|
||||
[6](#6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7882)
|
||||
|
||||
At certain points in the template argument deduction process it is necessary
|
||||
to take a function type that makes use of template parameters and replace those
|
||||
template parameters with the corresponding template arguments[.](#6.sentence-1)
|
||||
|
||||
This is done at
|
||||
the beginning of template argument deduction when any explicitly specified
|
||||
template arguments are substituted into the function type, and again at the end
|
||||
of template argument deduction when any template arguments that were deduced or
|
||||
obtained from default arguments are substituted[.](#6.sentence-2)
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7891)
|
||||
|
||||
The [*deduction substitution loci*](#def:deduction_substitution_loci "13.10.3.1 General [temp.deduct.general]") are
|
||||
|
||||
- [(7.1)](#7.1)
|
||||
|
||||
the function type outside of the [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]"),
|
||||
|
||||
- [(7.2)](#7.2)
|
||||
|
||||
the [*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3 Function specifiers [dcl.fct.spec]"),
|
||||
|
||||
- [(7.3)](#7.3)
|
||||
|
||||
the template parameter declarations, and
|
||||
|
||||
- [(7.4)](#7.4)
|
||||
|
||||
the template argument list of a partial specialization ([[temp.spec.partial.general]](temp.spec.partial.general "13.7.6.1 General"))[.](#7.sentence-1)
|
||||
|
||||
The substitution occurs in all types and expressions that are used
|
||||
in the deduction substitution loci[.](#7.sentence-2)
|
||||
|
||||
The expressions include not only
|
||||
constant expressions such as those that appear in array bounds or as nontype
|
||||
template arguments but also general expressions (i.e., non-constant expressions)
|
||||
inside sizeof, decltype, and other contexts that allow non-constant
|
||||
expressions[.](#7.sentence-3)
|
||||
|
||||
The substitution proceeds in lexical order and stops when
|
||||
a condition that causes deduction to fail is encountered[.](#7.sentence-4)
|
||||
|
||||
If substitution into different declarations of the same function template would
|
||||
cause template instantiations to occur in a different order or not at all,
|
||||
the program is ill-formed; no diagnostic required[.](#7.sentence-5)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
The equivalent substitution in
|
||||
exception specifications ([[except.spec]](except.spec "14.5 Exception specifications"))
|
||||
and function contract assertions ([[dcl.contract.func]](dcl.contract.func "9.4.1 General"))
|
||||
is done only when
|
||||
the [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") or [*function-contract-specifier*](dcl.contract.func#nt:function-contract-specifier "9.4.1 General [dcl.contract.func]"), respectively,
|
||||
is instantiated,
|
||||
at which point a program is ill-formed
|
||||
if the substitution results in an invalid type or expression[.](#7.sentence-6)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [6](#example-6)*: template <class T> struct A { using X = typename T::X; };template <class T> typename T::X f(typename A<T>::X);template <class T> void f(...) { }template <class T> auto g(typename A<T>::X) -> typename T::X;template <class T> void g(...) { }template <class T> typename T::X h(typename A<T>::X);template <class T> auto h(typename A<T>::X) -> typename T::X; // redeclarationtemplate <class T> void h(...) { }void x() { f<int>(0); // OK, substituting return type causes deduction to fail g<int>(0); // error, substituting parameter type instantiates A<int> h<int>(0); // ill-formed, no diagnostic required} â *end example*]
|
||||
|
||||
[8](#8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7941)
|
||||
|
||||
If a substitution results in an invalid type or expression, type deduction fails[.](#8.sentence-1)
|
||||
|
||||
An
|
||||
invalid type or expression is one that would be ill-formed, with a diagnostic
|
||||
required, if written in the same context using the substituted arguments[.](#8.sentence-2)
|
||||
|
||||
[*Note [5](#note-5)*:
|
||||
|
||||
If no diagnostic is required, the program is still ill-formed[.](#8.sentence-3)
|
||||
|
||||
Access checking is done as part of the substitution process[.](#8.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Invalid types and expressions can result in a deduction failure
|
||||
only in the immediate context of the deduction substitution loci[.](#8.sentence-5)
|
||||
|
||||
[*Note [6](#note-6)*:
|
||||
|
||||
The substitution into types and expressions can result
|
||||
in effects such as the instantiation of class template specializations and/or
|
||||
function template specializations, the generation of implicitly-defined functions,
|
||||
etc[.](#8.sentence-6)
|
||||
|
||||
Such effects are not in the âimmediate contextâ and can result in the
|
||||
program being ill-formed[.](#8.sentence-7)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[9](#9)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7959)
|
||||
|
||||
When substituting into a [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]"),
|
||||
substitution into its body is not in the immediate context[.](#9.sentence-1)
|
||||
|
||||
[*Note [7](#note-7)*:
|
||||
|
||||
The intent is to avoid requiring implementations to deal with
|
||||
substitution failure involving arbitrary statements[.](#9.sentence-2)
|
||||
|
||||
[*Example [7](#example-7)*: template <class T>auto f(T) -> decltype([]() { T::invalid; } ());void f(...);
|
||||
f(0); // error: invalid expression not part of the immediate contexttemplate <class T, std::size_t = sizeof([]() { T::invalid; })>void g(T);void g(...);
|
||||
g(0); // error: invalid expression not part of the immediate contexttemplate <class T>auto h(T) -> decltype([x = T::invalid]() { });void h(...);
|
||||
h(0); // error: invalid expression not part of the immediate contexttemplate <class T>auto i(T) -> decltype([]() -> typename T::invalid { });void i(...);
|
||||
i(0); // error: invalid expression not part of the immediate contexttemplate <class T>auto j(T t) -> decltype([](auto x) -> decltype(x.invalid) { } (t)); // #1void j(...); // #2 j(0); // deduction fails on #1, calls #2 â *end example*]
|
||||
|
||||
â *end note*]
|
||||
|
||||
[10](#10)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L7995)
|
||||
|
||||
[*Example [8](#example-8)*: struct X { };struct Y { Y(X) {}};
|
||||
|
||||
template <class T> auto f(T t1, T t2) -> decltype(t1 + t2); // #1 X f(Y, Y); // #2 X x1, x2;
|
||||
X x3 = f(x1, x2); // deduction fails on #1 (cannot add X+X), calls #2 â *end example*]
|
||||
|
||||
[11](#11)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8011)
|
||||
|
||||
[*Note [8](#note-8)*:
|
||||
|
||||
Type deduction can fail for the following reasons:
|
||||
|
||||
- [(11.1)](#11.1)
|
||||
|
||||
Attempting to instantiate a pack expansion containing multiple packs of differing lengths[.](#11.1.sentence-1)
|
||||
|
||||
- [(11.2)](#11.2)
|
||||
|
||||
Attempting to create an array with an element type that is void, a
|
||||
function type, or a reference type, or attempting
|
||||
to create an array with a size that is zero or negative[.](#11.2.sentence-1)
|
||||
[*Example [9](#example-9)*: template <class T> int f(T[5]);int I = f<int>(0);int j = f<void>(0); // invalid array â *end example*]
|
||||
|
||||
- [(11.3)](#11.3)
|
||||
|
||||
Attempting to use a type that is not a class or enumeration type in a qualified name[.](#11.3.sentence-1)
|
||||
[*Example [10](#example-10)*: template <class T> int f(typename T::B*);int i = f<int>(0); â *end example*]
|
||||
|
||||
- [(11.4)](#11.4)
|
||||
|
||||
Attempting to use a type in a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") of a[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") when
|
||||
that type does not contain the specified member, or
|
||||
* [(11.4.1)](#11.4.1)
|
||||
|
||||
the specified member is not a type where a type is required, or
|
||||
|
||||
* [(11.4.2)](#11.4.2)
|
||||
|
||||
the specified member is not a template where a template is required, or
|
||||
|
||||
* [(11.4.3)](#11.4.3)
|
||||
|
||||
the specified member is not a non-type, non-template where a non-type,
|
||||
non-template is required[.](#11.4.sentence-1)
|
||||
|
||||
[*Example [11](#example-11)*: template <int I> struct X { };template <template <class T> class> struct Z { };template <class T> void f(typename T::Y*) {}template <class T> void g(X<T::N>*) {}template <class T> void h(Z<T::TT>*) {}struct A {};struct B { int Y; };struct C {typedef int N;};struct D {typedef int TT;};
|
||||
|
||||
int main() {// Deduction fails in each of these cases: f<A>(0); // A does not contain a member Y f<B>(0); // The Y member of B is not a type g<C>(0); // The N member of C is not a non-type, non-template name h<D>(0); // The TT member of D is not a template} â *end example*]
|
||||
|
||||
- [(11.5)](#11.5)
|
||||
|
||||
Attempting to create a pointer to reference type[.](#11.5.sentence-1)
|
||||
|
||||
- [(11.6)](#11.6)
|
||||
|
||||
Attempting to create a reference to void[.](#11.6.sentence-1)
|
||||
|
||||
- [(11.7)](#11.7)
|
||||
|
||||
Attempting to create âpointer to member of Tâ when T is not a
|
||||
class type[.](#11.7.sentence-1)
|
||||
[*Example [12](#example-12)*: template <class T> int f(int T::*);int i = f<int>(0); â *end example*]
|
||||
|
||||
- [(11.8)](#11.8)
|
||||
|
||||
Attempting to give an invalid type to a constant template parameter[.](#11.8.sentence-1)
|
||||
[*Example [13](#example-13)*: template <class T, T> struct S {};template <class T> int f(S<T, T{}>*); // #1class X {int m;};int i0 = f<X>(0); // #1 uses a value of non-structural type X as a constant template argument â *end example*]
|
||||
|
||||
- [(11.9)](#11.9)
|
||||
|
||||
Attempting to perform an invalid conversion in either a template
|
||||
argument expression, or an expression used in the function
|
||||
declaration[.](#11.9.sentence-1)
|
||||
[*Example [14](#example-14)*: template <class T, T*> int f(int);int i2 = f<int,1>(0); // can't convert 1 to int* â *end example*]
|
||||
|
||||
- [(11.10)](#11.10)
|
||||
|
||||
Attempting to create a function type in which a parameter has a type
|
||||
of void, or in which the return type is a function type
|
||||
or array type[.](#11.10.sentence-1)
|
||||
|
||||
- [(11.11)](#11.11)
|
||||
|
||||
Attempting to give to
|
||||
an explicit object parameter of a lambda's function call operator
|
||||
a type not permitted for such ([[expr.prim.lambda.closure]](expr.prim.lambda.closure "7.5.6.2 Closure types"))[.](#11.11.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[12](#12)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8124)
|
||||
|
||||
[*Example [15](#example-15)*:
|
||||
|
||||
In the following example,
|
||||
assuming a signed char cannot represent the value 1000,
|
||||
a [narrowing conversion](dcl.init.list#def:conversion,narrowing "9.5.5 List-initialization [dcl.init.list]") would be required
|
||||
to convert the [*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") of type int to signed char,
|
||||
therefore substitution fails for the
|
||||
second template ([[temp.arg.nontype]](temp.arg.nontype "13.4.3 Constant template arguments"))[.](#12.sentence-1)
|
||||
|
||||
template <int> int f(int);template <signed char> int f(int);int i1 = f<1000>(0); // OKint i2 = f<1>(0); // ambiguous; not narrowing â *end example*]
|
||||
57
cppdraft/temp/deduct/guide.md
Normal file
57
cppdraft/temp/deduct/guide.md
Normal file
@@ -0,0 +1,57 @@
|
||||
[temp.deduct.guide]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.deduct.guide)
|
||||
|
||||
### 13.7.2 Class templates [[temp.class]](temp.class#temp.deduct.guide)
|
||||
|
||||
#### 13.7.2.3 Deduction guides [temp.deduct.guide]
|
||||
|
||||
[1](#1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2823)
|
||||
|
||||
Deduction guides are used
|
||||
when a [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") or [*splice-type-specifier*](dcl.type.splice#nt:splice-type-specifier "9.2.9.9 Type splicing [dcl.type.splice]") appears as a type specifier
|
||||
for a deduced class type ([[dcl.type.class.deduct]](dcl.type.class.deduct "9.2.9.8 Deduced class template specialization types"))[.](#1.sentence-1)
|
||||
|
||||
Deduction guides are not found by name lookup[.](#1.sentence-2)
|
||||
|
||||
Instead, when performing class template argument deduction ([[over.match.class.deduct]](over.match.class.deduct "12.2.2.9 Class template argument deduction")),
|
||||
all reachable deduction guides declared for the class template are considered[.](#1.sentence-3)
|
||||
|
||||
[deduction-guide:](#nt:deduction-guide "13.7.2.3 Deduction guides [temp.deduct.guide]")
|
||||
[*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3 Function specifiers [dcl.fct.spec]")opt [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") ( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") ) -> [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")opt ;
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2837)
|
||||
|
||||
[*Example [1](#example-1)*: template<class T, class D = int>struct S { T data;};template<class U> S(U) -> S<typename U::type>;
|
||||
|
||||
struct A {using type = short; operator type();};
|
||||
S x{A()}; // x is of type S<short, int> â *end example*]
|
||||
|
||||
[3](#3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L2855)
|
||||
|
||||
The same restrictions apply
|
||||
to the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") of a deduction guide
|
||||
as in a function declaration ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")),
|
||||
except that a generic parameter type placeholder ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers"))
|
||||
shall not appear in the [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") of
|
||||
a deduction guide[.](#3.sentence-1)
|
||||
|
||||
The [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") shall name a class template specialization[.](#3.sentence-2)
|
||||
|
||||
The [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") shall be the same [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") as the [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") of the [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")[.](#3.sentence-3)
|
||||
|
||||
A [*deduction-guide*](#nt:deduction-guide "13.7.2.3 Deduction guides [temp.deduct.guide]") shall inhabit the scope
|
||||
to which the corresponding class template belongs
|
||||
and, for a member class template, have the same access[.](#3.sentence-4)
|
||||
|
||||
Two deduction guide declarations
|
||||
for the same class template
|
||||
shall not have equivalent [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]")*s* if either is reachable from the other[.](#3.sentence-5)
|
||||
219
cppdraft/temp/deduct/partial.md
Normal file
219
cppdraft/temp/deduct/partial.md
Normal file
@@ -0,0 +1,219 @@
|
||||
[temp.deduct.partial]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct.partial)
|
||||
|
||||
### 13.10.3 Template argument deduction [[temp.deduct]](temp.deduct#partial)
|
||||
|
||||
#### 13.10.3.5 Deducing template arguments during partial ordering [temp.deduct.partial]
|
||||
|
||||
[1](#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[.](#1.sentence-1)
|
||||
|
||||
[2](#2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8587)
|
||||
|
||||
Two sets of types are used to determine the partial ordering[.](#2.sentence-1)
|
||||
|
||||
For each of
|
||||
the templates involved there is the original function type and the
|
||||
transformed function type[.](#2.sentence-2)
|
||||
|
||||
[*Note [1](#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")[.](#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[.](#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[.](#2.sentence-5)
|
||||
|
||||
[3](#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)](#3.1)
|
||||
|
||||
In the context of a function call, the types used are those function parameter types
|
||||
for which the function call has arguments[.](#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)](#3.2)
|
||||
|
||||
In the context of a call to a conversion function, the return types of
|
||||
the conversion function templates are used[.](#3.2.sentence-1)
|
||||
|
||||
- [(3.3)](#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[.](#3.3.sentence-1)
|
||||
|
||||
[4](#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[.](#4.sentence-1)
|
||||
|
||||
[5](#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)](#5.1)
|
||||
|
||||
IfP is a reference type,P is replaced by the type referred to[.](#5.1.sentence-1)
|
||||
|
||||
- [(5.2)](#5.2)
|
||||
|
||||
IfA is a reference type,A is replaced by the type referred to[.](#5.2.sentence-1)
|
||||
|
||||
[6](#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[.](#6.sentence-1)
|
||||
|
||||
The result of this
|
||||
determination will be used below[.](#6.sentence-2)
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8658)
|
||||
|
||||
Remove any top-level cv-qualifiers:
|
||||
|
||||
- [(7.1)](#7.1)
|
||||
|
||||
IfP is a cv-qualified type,P is replaced by the cv-unqualified version ofP[.](#7.1.sentence-1)
|
||||
|
||||
- [(7.2)](#7.2)
|
||||
|
||||
IfA is a cv-qualified type,A is replaced by the cv-unqualified version ofA[.](#7.2.sentence-1)
|
||||
|
||||
[8](#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")[.](#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[.](#8.sentence-2)
|
||||
|
||||
Each comparison
|
||||
deduces template arguments for subsequent positions in the template parameter
|
||||
packs expanded by the function parameter pack[.](#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[.](#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[.](#8.sentence-5)
|
||||
|
||||
[*Example [1](#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](#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)](#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)](#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[.](#9.sentence-1)
|
||||
|
||||
[10](#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[.](#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[.](#10.sentence-2)
|
||||
|
||||
[11](#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[.](#11.sentence-1)
|
||||
|
||||
[12](#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[.](#12.sentence-1)
|
||||
|
||||
[*Note [2](#note-2)*:
|
||||
|
||||
A template parameter used in a non-deduced context is considered used[.](#12.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [2](#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](#13)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8769)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
Partial ordering of function templates containing
|
||||
template parameter packs is independent of the number of deduced arguments
|
||||
for those template parameter packs[.](#13.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [3](#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)
|
||||
540
cppdraft/temp/deduct/type.md
Normal file
540
cppdraft/temp/deduct/type.md
Normal file
@@ -0,0 +1,540 @@
|
||||
[temp.deduct.type]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct.type)
|
||||
|
||||
### 13.10.3 Template argument deduction [[temp.deduct]](temp.deduct#type)
|
||||
|
||||
#### 13.10.3.6 Deducing template arguments from a type [temp.deduct.type]
|
||||
|
||||
[1](#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[.](#1.sentence-1)
|
||||
|
||||
[2](#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[.](#2.sentence-1)
|
||||
|
||||
Type deduction is done
|
||||
independently for eachP/A pair, and the deduced template
|
||||
argument values are then combined[.](#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[.](#2.sentence-3)
|
||||
|
||||
The type of a type parameter
|
||||
is only deduced from an array bound
|
||||
if it is not otherwise deduced[.](#2.sentence-4)
|
||||
|
||||
[3](#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)](#3.1)
|
||||
|
||||
A function type includes the types of each of the function parameters,
|
||||
the return type, and its exception specification[.](#3.1.sentence-1)
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
A pointer-to-member type includes the type of the class object pointed to
|
||||
and the type of the member pointed to[.](#3.2.sentence-1)
|
||||
|
||||
- [(3.3)](#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[.](#3.3.sentence-1)
|
||||
|
||||
- [(3.4)](#3.4)
|
||||
|
||||
An array type includes the array element type and the value of the
|
||||
array bound[.](#3.4.sentence-1)
|
||||
|
||||
[4](#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[.](#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[.](#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[.](#4.sentence-3)
|
||||
|
||||
If a template parameter is used only in non-deduced contexts and is not
|
||||
explicitly specified, template argument deduction fails[.](#4.sentence-4)
|
||||
|
||||
[*Note [1](#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[.](#4.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8876)
|
||||
|
||||
The non-deduced contexts are:
|
||||
|
||||
- [(5.1)](#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]")[.](#5.1.sentence-1)
|
||||
|
||||
- [(5.2)](#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]")[.](#5.2.sentence-1)
|
||||
|
||||
- [(5.3)](#5.3)
|
||||
|
||||
A [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")[.](#5.3.sentence-1)
|
||||
|
||||
- [(5.4)](#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]")[.](#5.4.sentence-1)
|
||||
|
||||
- [(5.5)](#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]")[.](#5.5.sentence-1)
|
||||
|
||||
- [(5.6)](#5.6)
|
||||
|
||||
A constant template argument or an array bound in which a subexpression
|
||||
references a template parameter[.](#5.6.sentence-1)
|
||||
|
||||
- [(5.7)](#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[.](#5.7.sentence-1)
|
||||
|
||||
- [(5.8)](#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)](#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)](#5.8.2)
|
||||
|
||||
no function whose associated constraints are satisfied
|
||||
matches the function parameter type, or
|
||||
|
||||
* [(5.8.3)](#5.8.3)
|
||||
|
||||
the overload set supplied as an argument contains one or more function templates[.](#5.8.sentence-1)
|
||||
|
||||
[*Note [2](#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"))[.](#5.8.sentence-2)
|
||||
â *end note*]
|
||||
|
||||
- [(5.9)](#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"))[.](#5.9.sentence-1)
|
||||
[*Example [1](#example-1)*: template<class T> void g(T);
|
||||
g({1,2,3}); // error: no argument deduced for T â *end example*]
|
||||
|
||||
- [(5.10)](#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]")[.](#5.10.sentence-1)
|
||||
|
||||
[6](#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[.](#6.sentence-1)
|
||||
|
||||
However, a compound type can include both deduced and non-deduced types[.](#6.sentence-2)
|
||||
|
||||
[*Example [2](#example-2)*:
|
||||
|
||||
If a type is specified asA<T>::B<T2>,
|
||||
bothT andT2 are non-deduced[.](#6.sentence-3)
|
||||
|
||||
Likewise, if a type is specified asA<I+J>::X<T>,I,J,
|
||||
andT are non-deduced[.](#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[.](#6.sentence-5)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[7](#7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8968)
|
||||
|
||||
[*Example [3](#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[.](#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](#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)](#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)](#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)](#8.3)
|
||||
|
||||
TTopt represents either a class template or
|
||||
a template template parameter, and
|
||||
|
||||
- [(8.4)](#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[.](#8.sentence-1)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
If a type matches such a form but contains noTs, is, or TTs, deduction is not possible[.](#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[.](#8.sentence-3)
|
||||
|
||||
[9](#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[.](#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[.](#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[.](#9.sentence-3)
|
||||
|
||||
Each comparison deduces
|
||||
template arguments for subsequent positions in the template parameter
|
||||
packs expanded by Pi[.](#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)](#9.1)
|
||||
|
||||
if P does not contain a template argument corresponding toAi then Ai is ignored;
|
||||
|
||||
- [(9.2)](#9.2)
|
||||
|
||||
otherwise, if Pi is not a pack expansion, template argument
|
||||
deduction fails[.](#9.sentence-5)
|
||||
|
||||
[*Example [4](#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](#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[.](#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)[.](#10.sentence-2)
|
||||
|
||||
[*Note [4](#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&[.](#10.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [5](#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[.](#10.sentence-4)
|
||||
|
||||
Each comparison deduces template arguments for
|
||||
subsequent positions in the template parameter packs expanded by the
|
||||
function parameter pack[.](#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)](#10.1)
|
||||
|
||||
if P does not contain a function parameter type corresponding toAi then Ai is ignored;
|
||||
|
||||
- [(10.2)](#10.2)
|
||||
|
||||
otherwise, if Pi is not a function parameter pack, template
|
||||
argument deduction fails[.](#10.sentence-6)
|
||||
|
||||
[*Example [6](#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](#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[.](#11.sentence-1)
|
||||
|
||||
[*Example [7](#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][.](#11.sentence-2)
|
||||
|
||||
â *end example*]
|
||||
|
||||
[12](#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[.](#12.sentence-1)
|
||||
|
||||
[13](#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[.](#13.sentence-1)
|
||||
|
||||
[*Example [8](#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](#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[.](#14.sentence-1)
|
||||
|
||||
[*Example [9](#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](#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[.](#15.sentence-1)
|
||||
|
||||
[*Example [10](#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](#16)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9285)
|
||||
|
||||
[*Example [11](#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](#17)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9296)
|
||||
|
||||
[*Note [5](#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](#18)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9316)
|
||||
|
||||
[*Note [6](#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[.](#18.sentence-1)
|
||||
|
||||
[*Example [12](#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](#19)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9338)
|
||||
|
||||
[*Note [7](#note-7)*:
|
||||
|
||||
Template parameters do not participate in template argument deduction if
|
||||
they are used only in non-deduced contexts[.](#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](#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[.](#20.sentence-1)
|
||||
|
||||
If P has a form that contains [i], and if the type ofi is not an integral type, deduction fails[.](#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[.](#20.sentence-3)
|
||||
|
||||
[*Example [13](#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](#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[.](#21.sentence-1)
|
||||
|
||||
[*Example [14](#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](#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[.](#22.sentence-1)
|
||||
|
||||
[*Example [15](#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](#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[.](#23.sentence-1)
|
||||
|
||||
[*Example [16](#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](#24)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L9451)
|
||||
|
||||
[*Note [8](#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[.](#24.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [17](#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)
|
||||
Reference in New Issue
Block a user