Init
This commit is contained in:
520
cppdraft/temp/fct.md
Normal file
520
cppdraft/temp/fct.md
Normal file
@@ -0,0 +1,520 @@
|
||||
[temp.fct]
|
||||
|
||||
# 13 Templates [[temp]](./#temp)
|
||||
|
||||
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.fct)
|
||||
|
||||
### 13.7.7 Function templates [temp.fct]
|
||||
|
||||
#### [13.7.7.1](#general) General [[temp.fct.general]](temp.fct.general)
|
||||
|
||||
[1](#general-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4052)
|
||||
|
||||
A function template defines an unbounded set of related functions[.](#general-1.sentence-1)
|
||||
|
||||
[*Example [1](#general-example-1)*:
|
||||
|
||||
A family of sort functions can be declared like this:template<class T> class Array { };template<class T> void sort(Array<T>&);
|
||||
|
||||
â *end example*]
|
||||
|
||||
[2](#general-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4062)
|
||||
|
||||
[*Note [1](#general-note-1)*:
|
||||
|
||||
A function template can have the same name as other function templates
|
||||
and non-template functions ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) in the same scope[.](#general-2.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
A non-template function is not
|
||||
related to a function template
|
||||
(i.e., it is never considered to be a specialization),
|
||||
even if it has the same name and type
|
||||
as a potentially generated function template specialization[.](#general-2.sentence-2)[115](#footnote-115 "That is, declarations of non-template functions do not merely guide overload resolution of function template specializations with the same name. If such a non-template function is odr-used ([term.odr.use]) in a program, it must be defined; it will not be implicitly instantiated using the function template definition.")
|
||||
|
||||
[115)](#footnote-115)[115)](#footnoteref-115)
|
||||
|
||||
That is,
|
||||
declarations of non-template functions do not merely guide
|
||||
overload resolution of
|
||||
function template specializations
|
||||
with the same name[.](#footnote-115.sentence-1)
|
||||
|
||||
If such a non-template function is odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-definition rule")) in a program, it must be defined;
|
||||
it will not be implicitly instantiated using the function template definition[.](#footnote-115.sentence-2)
|
||||
|
||||
#### [13.7.7.2](#temp.over.link) Function template overloading [[temp.over.link]](temp.over.link)
|
||||
|
||||
[1](#temp.over.link-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4084)
|
||||
|
||||
It is possible to overload function templates so that two different
|
||||
function template specializations have the same type[.](#temp.over.link-1.sentence-1)
|
||||
|
||||
[*Example [1](#temp.over.link-example-1)*:
|
||||
|
||||
// translation unit 1:template<class T>void f(T*);void g(int* p) { f(p); // calls f<int>(int*)}
|
||||
|
||||
// translation unit 2:template<class T>void f(T);void h(int* p) { f(p); // calls f<int*>(int*)}
|
||||
|
||||
â *end example*]
|
||||
|
||||
[2](#temp.over.link-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4112)
|
||||
|
||||
Such specializations are distinct functions and do not violate the[one-definition rule](basic.def.odr "6.3 One-definition rule [basic.def.odr]")[.](#temp.over.link-2.sentence-1)
|
||||
|
||||
[3](#temp.over.link-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4116)
|
||||
|
||||
The signature of a function template
|
||||
is defined in [[intro.defs]](intro.defs "3 Terms and definitions")[.](#temp.over.link-3.sentence-1)
|
||||
|
||||
The names of the template parameters are significant only for establishing
|
||||
the relationship between the template parameters and the rest of the
|
||||
signature[.](#temp.over.link-3.sentence-2)
|
||||
|
||||
[*Note [1](#temp.over.link-note-1)*:
|
||||
|
||||
Two distinct function templates can have identical function return types and
|
||||
function parameter lists, even if overload resolution alone cannot distinguish
|
||||
them[.](#temp.over.link-3.sentence-3)
|
||||
|
||||
template<class T> void f();template<int I> void f(); // OK, overloads the first template// distinguishable with an explicit template argument list â *end note*]
|
||||
|
||||
[4](#temp.over.link-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4134)
|
||||
|
||||
When an expression that references a template parameter is used in the
|
||||
function parameter list or the return type in the declaration of a
|
||||
function template, the expression that references the template
|
||||
parameter is part of the signature of the function template[.](#temp.over.link-4.sentence-1)
|
||||
|
||||
This is
|
||||
necessary to permit a declaration of a function template in one
|
||||
translation unit to be linked with another declaration of the function
|
||||
template in another translation unit and, conversely, to ensure that
|
||||
function templates that are intended to be distinct are not linked
|
||||
with one another[.](#temp.over.link-4.sentence-2)
|
||||
|
||||
[*Example [2](#temp.over.link-example-2)*: template <int I, int J> A<I+J> f(A<I>, A<J>); // #1template <int K, int L> A<K+L> f(A<K>, A<L>); // same as #1template <int I, int J> A<I-J> f(A<I>, A<J>); // different from #1 â *end example*]
|
||||
|
||||
[*Note [2](#temp.over.link-note-2)*:
|
||||
|
||||
Most expressions that use template parameters use constant template
|
||||
parameters, but it is possible for an expression to reference a type
|
||||
parameter[.](#temp.over.link-4.sentence-3)
|
||||
|
||||
For example, a template type parameter can be used in thesizeof operator[.](#temp.over.link-4.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[5](#temp.over.link-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4160)
|
||||
|
||||
Two expressions involving template parameters are considered[*equivalent*](#def:equivalent,expressions "13.7.7.2 Function template overloading [temp.over.link]") if two function definitions containing the expressions would satisfy
|
||||
the [one-definition rule](basic.def.odr "6.3 One-definition rule [basic.def.odr]"), except that the tokens used
|
||||
to name the template parameters may differ as long as a token used to
|
||||
name a template parameter in one expression is replaced by another token
|
||||
that names the same template parameter in the other expression[.](#temp.over.link-5.sentence-1)
|
||||
|
||||
Two unevaluated operands that do not involve template parameters
|
||||
are considered equivalent
|
||||
if two function definitions containing the expressions
|
||||
would satisfy the one-definition rule,
|
||||
except that the tokens used to name types and declarations may differ
|
||||
as long as they name the same entities, and
|
||||
the tokens used to form concept-ids ([[temp.names]](temp.names "13.3 Names of template specializations")) may differ
|
||||
as long as the two [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")*s* are the same ([[temp.type]](temp.type "13.6 Type equivalence"))[.](#temp.over.link-5.sentence-2)
|
||||
|
||||
[*Note [3](#temp.over.link-note-3)*:
|
||||
|
||||
For instance, A<42> and A<40+2> name the same type[.](#temp.over.link-5.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
|
||||
Two [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")*s* are never considered equivalent[.](#temp.over.link-5.sentence-4)
|
||||
|
||||
[*Note [4](#temp.over.link-note-4)*:
|
||||
|
||||
The intent is to avoid [*lambda-expression*](expr.prim.lambda.general#nt:lambda-expression "7.5.6.1 General [expr.prim.lambda.general]")*s* appearing in the
|
||||
signature of a function template with external linkage[.](#temp.over.link-5.sentence-5)
|
||||
|
||||
â *end note*]
|
||||
|
||||
For determining whether two dependent names ([[temp.dep]](temp.dep "13.8.3 Dependent names")) are equivalent,
|
||||
only the name itself is considered, not the result of name lookup[.](#temp.over.link-5.sentence-6)
|
||||
|
||||
[*Note [5](#temp.over.link-note-5)*:
|
||||
|
||||
If such a dependent name is unqualified,
|
||||
it is looked up from
|
||||
a first declaration of the function template ([[temp.res.general]](temp.res.general "13.8.1 General"))[.](#temp.over.link-5.sentence-7)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [3](#temp.over.link-example-3)*: template <int I, int J> void f(A<I+J>); // #1template <int K, int L> void f(A<K+L>); // same as #1template <class T> decltype(g(T())) h();int g(int);template <class T> decltype(g(T())) h() // redeclaration of h() uses the earlier lookup…{ return g(T()); } // … although the lookup here does find g(int)int i = h<int>(); // template argument substitution fails; g(int)// not considered at the first declaration of h()// ill-formed, no diagnostic required: the two expressions are functionally equivalent but not equivalenttemplate <int N> void foo(const char (*s)[([]{}, N)]);template <int N> void foo(const char (*s)[([]{}, N)]);
|
||||
|
||||
// two different declarations because the non-dependent portions are not considered equivalenttemplate <class T> void spam(decltype([]{}) (*s)[sizeof(T)]);template <class T> void spam(decltype([]{}) (*s)[sizeof(T)]); â *end example*]
|
||||
|
||||
Two potentially-evaluated expressions involving template parameters that are not equivalent are[*functionally equivalent*](#def:functionally_equivalent,expressions "13.7.7.2 Function template overloading [temp.over.link]") if, for any given set of template arguments, the evaluation of the
|
||||
expression results in the same value[.](#temp.over.link-5.sentence-8)
|
||||
|
||||
Two unevaluated operands that are not equivalent
|
||||
are functionally equivalent if, for any given set of template arguments,
|
||||
the expressions perform
|
||||
the same operations in the same order with the same entities[.](#temp.over.link-5.sentence-9)
|
||||
|
||||
[*Note [6](#temp.over.link-note-6)*:
|
||||
|
||||
For instance, one could have redundant parentheses[.](#temp.over.link-5.sentence-10)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [4](#temp.over.link-example-4)*: template<int I> concept C = true;template<typename T> struct A {void f() requires C<42>; // #1void f() requires true; // OK, different functions}; â *end example*]
|
||||
|
||||
[6](#temp.over.link-6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4235)
|
||||
|
||||
Two [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]")*s* are[*equivalent*](#def:equivalent,template-heads "13.7.7.2 Function template overloading [temp.over.link]") if
|
||||
their [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]")*s* have the same length,
|
||||
corresponding [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* are equivalent
|
||||
and are both declared with [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")*s* that are equivalent
|
||||
if either [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]") is declared with a [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]"),
|
||||
and if either [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") has a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]"),
|
||||
they both have[*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*s* and the corresponding[*constraint-expression*](temp.constr.decl#nt:constraint-expression "13.5.3 Constrained declarations [temp.constr.decl]")*s* are equivalent[.](#temp.over.link-6.sentence-1)
|
||||
|
||||
Two [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* are[*equivalent*](#def:equivalent,template-parameters "13.7.7.2 Function template overloading [temp.over.link]") under the following conditions:
|
||||
|
||||
- [(6.1)](#temp.over.link-6.1)
|
||||
|
||||
they declare template parameters of the same kind,
|
||||
|
||||
- [(6.2)](#temp.over.link-6.2)
|
||||
|
||||
if either declares a template parameter pack, they both do,
|
||||
|
||||
- [(6.3)](#temp.over.link-6.3)
|
||||
|
||||
if they declare constant template parameters,
|
||||
they have equivalent types
|
||||
ignoring the use of [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")*s* for placeholder types, and
|
||||
|
||||
- [(6.4)](#temp.over.link-6.4)
|
||||
|
||||
if they declare template template parameters,
|
||||
their [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]")*s* are equivalent[.](#temp.over.link-6.sentence-2)
|
||||
|
||||
When determining whether types or [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")*s* are equivalent, the rules above are used to compare expressions
|
||||
involving template parameters[.](#temp.over.link-6.sentence-3)
|
||||
|
||||
Two [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]")*s* are[*functionally equivalent*](#def:functionally_equivalent,template-heads "13.7.7.2 Function template overloading [temp.over.link]") if they accept and are satisfied by ([[temp.constr.constr]](temp.constr.constr "13.5.2 Constraints"))
|
||||
the same set of template argument lists[.](#temp.over.link-6.sentence-4)
|
||||
|
||||
[7](#temp.over.link-7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4267)
|
||||
|
||||
If the validity or meaning of the program depends on
|
||||
whether two constructs are equivalent, and they are
|
||||
functionally equivalent but not equivalent, the program is ill-formed,
|
||||
no diagnostic required[.](#temp.over.link-7.sentence-1)
|
||||
|
||||
Furthermore, if two declarations A and B of function templates
|
||||
|
||||
- [(7.1)](#temp.over.link-7.1)
|
||||
|
||||
introduce the same name,
|
||||
|
||||
- [(7.2)](#temp.over.link-7.2)
|
||||
|
||||
have corresponding signatures ([[basic.scope.scope]](basic.scope.scope "6.4.1 General")),
|
||||
|
||||
- [(7.3)](#temp.over.link-7.3)
|
||||
|
||||
would declare the same entity,
|
||||
when considering A and B to correspond in that determination ([[basic.link]](basic.link "6.7 Program and linkage")), and
|
||||
|
||||
- [(7.4)](#temp.over.link-7.4)
|
||||
|
||||
accept and are satisfied by the same set of template argument lists,
|
||||
|
||||
but do not correspond,
|
||||
the program is ill-formed, no diagnostic required[.](#temp.over.link-7.sentence-2)
|
||||
|
||||
[8](#temp.over.link-8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4287)
|
||||
|
||||
[*Note [7](#temp.over.link-note-7)*:
|
||||
|
||||
This rule guarantees that equivalent declarations will be linked with
|
||||
one another, while not requiring implementations to use heroic efforts
|
||||
to guarantee that functionally equivalent declarations will be treated
|
||||
as distinct[.](#temp.over.link-8.sentence-1)
|
||||
|
||||
For example, the last two declarations are functionally
|
||||
equivalent and would cause a program to be ill-formed:// guaranteed to be the sametemplate <int I> void f(A<I>, A<I+10>);template <int I> void f(A<I>, A<I+10>);
|
||||
|
||||
// guaranteed to be differenttemplate <int I> void f(A<I>, A<I+10>);template <int I> void f(A<I>, A<I+11>);
|
||||
|
||||
// ill-formed, no diagnostic requiredtemplate <int I> void f(A<I>, A<I+10>);template <int I> void f(A<I>, A<I+1+2+3+4>);
|
||||
|
||||
â *end note*]
|
||||
|
||||
#### [13.7.7.3](#temp.func.order) Partial ordering of function templates [[temp.func.order]](temp.func.order)
|
||||
|
||||
[1](#temp.func.order-1)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4312)
|
||||
|
||||
If multiple function templates share a name,
|
||||
the use of that name can be ambiguous because
|
||||
template argument deduction ([[temp.deduct]](temp.deduct "13.10.3 Template argument deduction")) may identify
|
||||
a specialization for more than one function template[.](#temp.func.order-1.sentence-1)
|
||||
|
||||
[*Partial ordering*](#def:template,function,partial_ordering "13.7.7.3 Partial ordering of function templates [temp.func.order]") of overloaded function template declarations is used in the following contexts
|
||||
to select the function template to which a function template specialization
|
||||
refers:
|
||||
|
||||
- [(1.1)](#temp.func.order-1.1)
|
||||
|
||||
during overload resolution for a call to a function template specialization ([[over.match.best]](over.match.best "12.2.4 Best viable function"));
|
||||
|
||||
- [(1.2)](#temp.func.order-1.2)
|
||||
|
||||
when the address of a function template specialization is taken;
|
||||
|
||||
- [(1.3)](#temp.func.order-1.3)
|
||||
|
||||
when a placement operator delete that is a
|
||||
function template
|
||||
specialization
|
||||
is selected to match a placement operator 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.4)](#temp.func.order-1.4)
|
||||
|
||||
when a [friend function declaration](temp.friend "13.7.5 Friends [temp.friend]"), an[explicit instantiation](temp.explicit "13.9.3 Explicit instantiation [temp.explicit]") or an [explicit specialization](temp.expl.spec "13.9.4 Explicit specialization [temp.expl.spec]") refers to
|
||||
a function template specialization[.](#temp.func.order-1.sentence-2)
|
||||
|
||||
[2](#temp.func.order-2)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4339)
|
||||
|
||||
Partial ordering selects which of two function templates is more
|
||||
specialized than the other by transforming each template in turn
|
||||
(see next paragraph) and performing template argument deduction
|
||||
using the function type[.](#temp.func.order-2.sentence-1)
|
||||
|
||||
The deduction process determines whether
|
||||
one of the templates is more specialized than the other[.](#temp.func.order-2.sentence-2)
|
||||
|
||||
If so, the
|
||||
more specialized template is the one chosen by the partial ordering
|
||||
process[.](#temp.func.order-2.sentence-3)
|
||||
|
||||
If both deductions succeed, the partial ordering selects
|
||||
the more constrained template (if one exists) as determined below[.](#temp.func.order-2.sentence-4)
|
||||
|
||||
[3](#temp.func.order-3)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4351)
|
||||
|
||||
To produce the transformed template, for each
|
||||
type, constant,
|
||||
type template, variable template, or concept
|
||||
template parameter (including template parameter packs ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates"))
|
||||
thereof) synthesize a unique type, value, class template,
|
||||
variable template, or concept,
|
||||
respectively, and substitute it for each occurrence of that parameter
|
||||
in the function type of the template[.](#temp.func.order-3.sentence-1)
|
||||
|
||||
[*Note [1](#temp.func.order-note-1)*:
|
||||
|
||||
The type replacing the placeholder
|
||||
in the type of the value synthesized for a constant template parameter
|
||||
is also a unique synthesized type[.](#temp.func.order-3.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[4](#temp.func.order-4)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4369)
|
||||
|
||||
A synthesized template has the same [*template-head*](temp.pre#nt:template-head "13.1 Preamble [temp.pre]") as
|
||||
its corresponding template template parameter[.](#temp.func.order-4.sentence-1)
|
||||
|
||||
[5](#temp.func.order-5)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4375)
|
||||
|
||||
Each function template M that is a member function
|
||||
is considered to have
|
||||
a new first parameter of type X(M), described below,
|
||||
inserted in its function parameter list[.](#temp.func.order-5.sentence-1)
|
||||
|
||||
If exactly one of the function templates was considered by overload resolution
|
||||
via a rewritten candidate ([[over.match.oper]](over.match.oper "12.2.2.3 Operators in expressions"))
|
||||
with a reversed order of parameters,
|
||||
then the order of the function parameters in its transformed template
|
||||
is reversed[.](#temp.func.order-5.sentence-2)
|
||||
|
||||
For a function template M with cv-qualifiers cv that is a member of a class A:
|
||||
|
||||
- [(5.1)](#temp.func.order-5.1)
|
||||
|
||||
The type X(M) is ârvalue reference to cv Aâ
|
||||
if the optional [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]") ofM is && or
|
||||
if M has no [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]") and
|
||||
the positionally-corresponding parameter of the other transformed template
|
||||
has rvalue reference type;
|
||||
if this determination depends recursively upon
|
||||
whether X(M) is an rvalue reference type,
|
||||
it is not considered to have rvalue reference type[.](#temp.func.order-5.1.sentence-1)
|
||||
|
||||
- [(5.2)](#temp.func.order-5.2)
|
||||
|
||||
Otherwise, X(M) is âlvalue reference to cv Aâ[.](#temp.func.order-5.2.sentence-1)
|
||||
|
||||
[*Note [2](#temp.func.order-note-2)*:
|
||||
|
||||
This allows a non-static
|
||||
member to be ordered with respect to a non-member function and for the results
|
||||
to be equivalent to the ordering of two equivalent non-members[.](#temp.func.order-5.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
|
||||
[*Example [1](#temp.func.order-example-1)*: struct A { };template<class T> struct B {template<class R> int operator*(R&); // #1};
|
||||
|
||||
template<class T, class R> int operator*(T&, R&); // #2// The declaration of B::operator* is transformed into the equivalent of// template<class R> int operator*(B<A>&, R&); // #1aint main() { A a;
|
||||
B<A> b;
|
||||
b * a; // calls #1} â *end example*]
|
||||
|
||||
[6](#temp.func.order-6)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4428)
|
||||
|
||||
Using the transformed function template's function type,
|
||||
perform type deduction against the other template as described in [[temp.deduct.partial]](temp.deduct.partial "13.10.3.5 Deducing template arguments during partial ordering")[.](#temp.func.order-6.sentence-1)
|
||||
|
||||
[*Example [2](#temp.func.order-example-2)*: template<class T> struct A { A(); };
|
||||
|
||||
template<class T> void f(T);template<class T> void f(T*);template<class T> void f(const T*);
|
||||
|
||||
template<class T> void g(T);template<class T> void g(T&);
|
||||
|
||||
template<class T> void h(const T&);template<class T> void h(A<T>&);
|
||||
|
||||
void m() {const int* p;
|
||||
f(p); // f(const T*) is more specialized than f(T) or f(T*)float x;
|
||||
g(x); // ambiguous: g(T) or g(T&) A<int> z;
|
||||
h(z); // overload resolution selects h(A<T>&)const A<int> z2;
|
||||
h(z2); // h(const T&) is called because h(A<T>&) is not callable} â *end example*]
|
||||
|
||||
[7](#temp.func.order-7)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4459)
|
||||
|
||||
[*Note [3](#temp.func.order-note-3)*:
|
||||
|
||||
Since, in a call context, such type deduction considers only parameters
|
||||
for which there are explicit call arguments, some parameters are ignored (namely,
|
||||
function parameter packs, parameters with default arguments, and ellipsis
|
||||
parameters)[.](#temp.func.order-7.sentence-1)
|
||||
|
||||
[*Example [3](#temp.func.order-example-3)*: template<class T> void f(T); // #1template<class T> void f(T*, int=1); // #2template<class T> void g(T); // #3template<class T> void g(T*, ...); // #4int main() {int* ip;
|
||||
f(ip); // calls #2 g(ip); // calls #4} â *end example*]
|
||||
|
||||
[*Example [4](#temp.func.order-example-4)*: template<class T, class U> struct A { };
|
||||
|
||||
template<class T, class U> void f(U, A<U, T>* p = 0); // #1template< class U> void f(U, A<U, U>* p = 0); // #2template<class T > void g(T, T = T()); // #3template<class T, class... U> void g(T, U ...); // #4void h() { f<int>(42, (A<int, int>*)0); // calls #2 f<int>(42); // error: ambiguous g(42); // error: ambiguous} â *end example*]
|
||||
|
||||
[*Example [5](#temp.func.order-example-5)*: template<class T, class... U> void f(T, U...); // #1template<class T > void f(T); // #2template<class T, class... U> void g(T*, U...); // #3template<class T > void g(T); // #4void h(int i) { f(&i); // OK, calls #2 g(&i); // OK, calls #3} â *end example*]
|
||||
|
||||
â *end note*]
|
||||
|
||||
[8](#temp.func.order-8)
|
||||
|
||||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4512)
|
||||
|
||||
If deduction against the other template succeeds for both transformed templates,
|
||||
constraints can be considered as follows:
|
||||
|
||||
- [(8.1)](#temp.func.order-8.1)
|
||||
|
||||
If their [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]")*s* (possibly including [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* invented for an abbreviated function template ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))) or
|
||||
function parameter lists differ in length,
|
||||
neither template is more specialized than the other[.](#temp.func.order-8.1.sentence-1)
|
||||
|
||||
- [(8.2)](#temp.func.order-8.2)
|
||||
|
||||
Otherwise:
|
||||
* [(8.2.1)](#temp.func.order-8.2.1)
|
||||
|
||||
If exactly one of the templates was considered by overload resolution
|
||||
via a rewritten candidate with reversed order of parameters:
|
||||
+
|
||||
[(8.2.1.1)](#temp.func.order-8.2.1.1)
|
||||
If, for either template, some of the template parameters
|
||||
are not deducible from their function parameters,
|
||||
neither template is more specialized than the other.
|
||||
|
||||
+
|
||||
[(8.2.1.2)](#temp.func.order-8.2.1.2)
|
||||
If there is either no reordering or more than one reordering
|
||||
of the associated [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]") such that
|
||||
- [(8.2.1.2.1)](#temp.func.order-8.2.1.2.1)
|
||||
|
||||
the corresponding [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* of the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]")*s* are equivalent and
|
||||
|
||||
- [(8.2.1.2.2)](#temp.func.order-8.2.1.2.2)
|
||||
|
||||
the function parameters that positionally correspond
|
||||
between the two templates are of the same type,
|
||||
|
||||
neither template is more specialized than the other.
|
||||
|
||||
* [(8.2.2)](#temp.func.order-8.2.2)
|
||||
|
||||
Otherwise, if the corresponding [*template-parameter*](temp.param#nt:template-parameter "13.2 Template parameters [temp.param]")*s* of the [*template-parameter-list*](temp.pre#nt:template-parameter-list "13.1 Preamble [temp.pre]")*s* are not equivalent ([[temp.over.link]](#temp.over.link "13.7.7.2 Function template overloading")) or
|
||||
if the function parameters that positionally correspond
|
||||
between the two templates are not of the same type,
|
||||
neither template is more specialized than the other[.](#temp.func.order-8.2.sentence-1)
|
||||
|
||||
- [(8.3)](#temp.func.order-8.3)
|
||||
|
||||
Otherwise, if the context in which the partial ordering is done
|
||||
is that of a call to a conversion function and
|
||||
the return types of the templates are not the same,
|
||||
then neither template is more specialized than the other[.](#temp.func.order-8.3.sentence-1)
|
||||
|
||||
- [(8.4)](#temp.func.order-8.4)
|
||||
|
||||
Otherwise,
|
||||
if one template is more constrained than the other ([[temp.constr.order]](temp.constr.order "13.5.5 Partial ordering by constraints")),
|
||||
the more constrained template is more specialized than the other[.](#temp.func.order-8.4.sentence-1)
|
||||
|
||||
- [(8.5)](#temp.func.order-8.5)
|
||||
|
||||
Otherwise, neither template is more specialized than the other[.](#temp.func.order-8.5.sentence-1)
|
||||
|
||||
[*Example [6](#temp.func.order-example-6)*: template <typename> constexpr bool True = true;template <typename T> concept C = True<T>;
|
||||
|
||||
void f(C auto &, auto &) = delete;template <C Q> void f(Q &, C auto &);
|
||||
|
||||
void g(struct A *ap, struct B *bp) { f(*ap, *bp); // OK, can use different methods to produce template parameters}template <typename T, typename U> struct X {};
|
||||
|
||||
template <typename T, C U, typename V> bool operator==(X<T, U>, V) = delete;template <C T, C U, C V> bool operator==(T, X<U, V>);
|
||||
|
||||
void h() { X<void *, int>{} == 0; // OK, correspondence of [T, U, V] and [U, V, T]} â *end example*]
|
||||
Reference in New Issue
Block a user