521 lines
26 KiB
Markdown
521 lines
26 KiB
Markdown
[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*]
|