[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*]
