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*]
|
||||
Reference in New Issue
Block a user