254 lines
11 KiB
Markdown
254 lines
11 KiB
Markdown
[temp.func.order]
|
||
|
||
# 13 Templates [[temp]](./#temp)
|
||
|
||
## 13.7 Template declarations [[temp.decls]](temp.decls#temp.func.order)
|
||
|
||
### 13.7.7 Function templates [[temp.fct]](temp.fct#temp.func.order)
|
||
|
||
#### 13.7.7.3 Partial ordering of function templates [temp.func.order]
|
||
|
||
[1](#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[.](#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)](#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)](#1.2)
|
||
|
||
when the address of a function template specialization is taken;
|
||
|
||
- [(1.3)](#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)](#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[.](#1.sentence-2)
|
||
|
||
[2](#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[.](#2.sentence-1)
|
||
|
||
The deduction process determines whether
|
||
one of the templates is more specialized than the other[.](#2.sentence-2)
|
||
|
||
If so, the
|
||
more specialized template is the one chosen by the partial ordering
|
||
process[.](#2.sentence-3)
|
||
|
||
If both deductions succeed, the partial ordering selects
|
||
the more constrained template (if one exists) as determined below[.](#2.sentence-4)
|
||
|
||
[3](#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[.](#3.sentence-1)
|
||
|
||
[*Note [1](#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[.](#3.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[4](#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[.](#4.sentence-1)
|
||
|
||
[5](#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[.](#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[.](#5.sentence-2)
|
||
|
||
For a function template M with cv-qualifiers cv that is a member of a class A:
|
||
|
||
- [(5.1)](#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[.](#5.1.sentence-1)
|
||
|
||
- [(5.2)](#5.2)
|
||
|
||
Otherwise, X(M) is âlvalue reference to cv Aâ[.](#5.2.sentence-1)
|
||
|
||
[*Note [2](#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[.](#5.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [1](#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](#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")[.](#6.sentence-1)
|
||
|
||
[*Example [2](#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](#7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L4459)
|
||
|
||
[*Note [3](#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)[.](#7.sentence-1)
|
||
|
||
[*Example [3](#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](#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](#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](#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)](#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[.](#8.1.sentence-1)
|
||
|
||
- [(8.2)](#8.2)
|
||
|
||
Otherwise:
|
||
* [(8.2.1)](#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)](#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)](#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)](#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)](#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)](#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[.](#8.2.sentence-1)
|
||
|
||
- [(8.3)](#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[.](#8.3.sentence-1)
|
||
|
||
- [(8.4)](#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[.](#8.4.sentence-1)
|
||
|
||
- [(8.5)](#8.5)
|
||
|
||
Otherwise, neither template is more specialized than the other[.](#8.5.sentence-1)
|
||
|
||
[*Example [6](#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*]
|