[temp.deduct.partial]

# 13 Templates [[temp]](./#temp)

## 13.10 Function template specializations [[temp.fct.spec]](temp.fct.spec#temp.deduct.partial)

### 13.10.3 Template argument deduction [[temp.deduct]](temp.deduct#partial)

#### 13.10.3.5 Deducing template arguments during partial ordering [temp.deduct.partial]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8583)

Template argument deduction is done by comparing certain types associated with
the two function templates being compared[.](#1.sentence-1)

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8587)

Two sets of types are used to determine the partial ordering[.](#2.sentence-1)

For each of
the templates involved there is the original function type and the
transformed function type[.](#2.sentence-2)

[*Note [1](#note-1)*:

The creation of the transformed type is described in [[temp.func.order]](temp.func.order "13.7.7.3 Partial ordering of function templates")[.](#2.sentence-3)

â *end note*]

The deduction process uses the
transformed type as the argument template and the original type of the
other template as the parameter template[.](#2.sentence-4)

This process is done twice
for each type involved in the partial ordering comparison: once using
the transformed template-1 as the argument template and template-2 as
the parameter template and again using the transformed template-2 as
the argument template and template-1 as the parameter template[.](#2.sentence-5)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8602)

The types used to determine the ordering depend on the context in which
the partial ordering is done:

- [(3.1)](#3.1)

  In the context of a function call, the types used are those function parameter types
for which the function call has arguments[.](#3.1.sentence-1)[119](#footnote-119 "Default arguments are not considered to be arguments in this context; they only become arguments after a function has been selected.")

- [(3.2)](#3.2)

  In the context of a call to a conversion function, the return types of
the conversion function templates are used[.](#3.2.sentence-1)

- [(3.3)](#3.3)

  In [other contexts](temp.func.order "13.7.7.3 Partial ordering of function templates [temp.func.order]") the function template's function
type is used[.](#3.3.sentence-1)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8622)

Each type nominated above from the parameter template and the corresponding type from the
argument template are used as the types ofP andA[.](#4.sentence-1)

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8629)

Before the partial ordering is done, certain transformations are performed
on the types used for partial ordering:

- [(5.1)](#5.1)

  IfP is a reference type,P is replaced by the type referred to[.](#5.1.sentence-1)

- [(5.2)](#5.2)

  IfA is a reference type,A is replaced by the type referred to[.](#5.2.sentence-1)

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8647)

If bothP andA were reference types (before being replaced with the type referred to
above), determine which of the two types (if any) is more cv-qualified
than the other; otherwise the types are considered to be equally
cv-qualified for partial ordering purposes[.](#6.sentence-1)

The result of this
determination will be used below[.](#6.sentence-2)

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8658)

Remove any top-level cv-qualifiers:

- [(7.1)](#7.1)

  IfP is a cv-qualified type,P is replaced by the cv-unqualified version ofP[.](#7.1.sentence-1)

- [(7.2)](#7.2)

  IfA is a cv-qualified type,A is replaced by the cv-unqualified version ofA[.](#7.2.sentence-1)

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8677)

Using the resulting typesP andA,
the deduction is then done as described in [[temp.deduct.type]](temp.deduct.type "13.10.3.6 Deducing template arguments from a type")[.](#8.sentence-1)

If P is a function parameter pack, the type A of each remaining
parameter type of the argument template is compared with the type P of
the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") of the function parameter pack[.](#8.sentence-2)

Each comparison
deduces template arguments for subsequent positions in the template parameter
packs expanded by the function parameter pack[.](#8.sentence-3)

Similarly, if A was transformed from a function parameter pack,
it is compared with each remaining parameter type of the parameter template[.](#8.sentence-4)

If deduction succeeds for a given type,
the type from the argument template is considered to be at least as specialized
as the type from the parameter template[.](#8.sentence-5)

[*Example [1](#example-1)*: template<class... Args> void f(Args... args); // #1template<class T1, class... Args> void f(T1 a1, Args... args); // #2template<class T1, class T2> void f(T1 a1, T2 a2); // #3 f(); // calls #1 f(1, 2, 3); // calls #2 f(1, 2); // calls #3; non-variadic template #3 is more specialized// than the variadic templates #1 and #2 â *end example*]

[9](#9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8706)

If, for a given type, the
types are identical after the transformations above
and both P and A were reference types (before being replaced with the
type referred to above):

- [(9.1)](#9.1)

if the type from the argument template was an lvalue reference and the type
from the parameter template was not,
the parameter type is not considered to be
at least as specialized as the argument type; otherwise,

- [(9.2)](#9.2)

if the type from
the argument template is more cv-qualified than the type from the
parameter template (as described above),
the parameter type is not considered to be
at least as specialized as the argument type[.](#9.sentence-1)

[10](#10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8723)

Function template F is [*at least as specialized as*](#def:more_specialized "13.10.3.5 Deducing template arguments during partial ordering [temp.deduct.partial]") function template G if,
for each pair of types used to determine the ordering,
the type from F is at least as specialized as
the type from G[.](#10.sentence-1)

F is [*more specialized than*](#def:more_specialized,function_template "13.10.3.5 Deducing template arguments during partial ordering [temp.deduct.partial]")G ifF is at least as specialized asG andG is not at least as specialized asF[.](#10.sentence-2)

[11](#11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8742)

If, after considering the above, function template F is at least as specialized as function template G and vice-versa, and
if G has a trailing function parameter pack
for which F does not have a corresponding parameter, and
if F does not have a trailing function parameter pack,
then F is more specialized than G[.](#11.sentence-1)

[12](#12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8750)

In most cases,
deduction fails if not all template parameters have values,
but for partial ordering purposes a template
parameter may remain without a value provided it is not used in the
types being used for partial ordering[.](#12.sentence-1)

[*Note [2](#note-2)*:

A template parameter used in a non-deduced context is considered used[.](#12.sentence-2)

â *end note*]

[*Example [2](#example-2)*: template <class T> T f(int); // #1template <class T, class U> T f(U); // #2void g() { f<int>(1); // calls #1} â *end example*]

[13](#13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/templates.tex#L8769)

[*Note [3](#note-3)*:

Partial ordering of function templates containing
template parameter packs is independent of the number of deduced arguments
for those template parameter packs[.](#13.sentence-1)

â *end note*]

[*Example [3](#example-3)*: template<class ...> struct Tuple { };template<class ... Types> void g(Tuple<Types ...>); // #1template<class T1, class ... Types> void g(Tuple<T1, Types ...>); // #2template<class T1, class ... Types> void g(Tuple<T1, Types& ...>); // #3 g(Tuple<>()); // calls #1 g(Tuple<int, float>()); // calls #2 g(Tuple<int, float&>()); // calls #3 g(Tuple<int>()); // calls #3 â *end example*]

[119)](#footnote-119)[119)](#footnoteref-119)

Default arguments
are not considered to be arguments in this context; they only become arguments
after a function has been selected[.](#footnote-119.sentence-1)
