[temp.deduct.type]

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

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

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

#### 13.10.3.6 Deducing template arguments from a type [temp.deduct.type]

[1](#1)

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

Template arguments can be deduced in several different contexts, but
in each case a type that is specified in terms of template parameters
(call itP)
is compared with an actual type (call itA),
and an attempt is made to find template argument values (a type for a type
parameter, a value for a constant template parameter, or a template for a
template template parameter) that will makeP,
after substitution of the deduced values (call it the deducedA),
compatible withA[.](#1.sentence-1)

[2](#2)

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

In some cases, the deduction is done using a single set of typesP andA,
in other cases, there will be a set of corresponding typesP andA[.](#2.sentence-1)

Type deduction is done
independently for eachP/A pair, and the deduced template
argument values are then combined[.](#2.sentence-2)

If type deduction cannot be done
for anyP/A pair, or if for any pair the deduction leads to more than
one possible set of deduced values, or if different pairs yield
different deduced values, or if any template argument remains neither
deduced nor explicitly specified, template argument deduction fails[.](#2.sentence-3)

The type of a type parameter
is only deduced from an array bound
if it is not otherwise deduced[.](#2.sentence-4)

[3](#3)

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

A given typeP can be composed from a number of other
types, templates, and constant template argument values:

- [(3.1)](#3.1)

  A function type includes the types of each of the function parameters,
the return type, and its exception specification[.](#3.1.sentence-1)

- [(3.2)](#3.2)

  A pointer-to-member type includes the type of the class object pointed to
and the type of the member pointed to[.](#3.2.sentence-1)

- [(3.3)](#3.3)

  A type that is a specialization of a class template (e.g.,A<int>)
includes the types, templates, and constant template argument values referenced by the
template argument list of the specialization[.](#3.3.sentence-1)

- [(3.4)](#3.4)

  An array type includes the array element type and the value of the
array bound[.](#3.4.sentence-1)

[4](#4)

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

In most cases, the types, templates, and constant template argument values that are used
to composeP participate in template argument deduction[.](#4.sentence-1)

That is,
they may be used to determine the value of a template argument, and
template argument deduction fails if
the value so determined is not consistent with the values determined
elsewhere[.](#4.sentence-2)

In certain contexts, however, the value does not
participate in type deduction, but instead uses the values of template
arguments that were either deduced elsewhere or explicitly specified[.](#4.sentence-3)

If a template parameter is used only in non-deduced contexts and is not
explicitly specified, template argument deduction fails[.](#4.sentence-4)

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

Under [[temp.deduct.call]](temp.deduct.call "13.10.3.2 Deducing template arguments from a function call"),
if P contains no template parameters that appear
in deduced contexts, no deduction is done, so P and A need not have the same form[.](#4.sentence-5)

â *end note*]

[5](#5)

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

The non-deduced contexts are:

- [(5.1)](#5.1)

  The[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") of a type that was specified using a[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]")[.](#5.1.sentence-1)

- [(5.2)](#5.2)

  A [*pack-index-specifier*](dcl.type.pack.index#nt:pack-index-specifier "9.2.9.4 Pack indexing specifier [dcl.type.pack.index]") or a [*pack-index-expression*](expr.prim.pack.index#nt:pack-index-expression "7.5.5.4 Pack indexing expression [expr.prim.pack.index]")[.](#5.2.sentence-1)

- [(5.3)](#5.3)

  A [*type-constraint*](temp.param#nt:type-constraint "13.2 Template parameters [temp.param]")[.](#5.3.sentence-1)

- [(5.4)](#5.4)

  The [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") of a [*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6 Decltype specifiers [dcl.type.decltype]")[.](#5.4.sentence-1)

- [(5.5)](#5.5)

  The [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") of a [*splice-specifier*](basic.splice#nt:splice-specifier "6.6 Splice specifiers [basic.splice]")[.](#5.5.sentence-1)

- [(5.6)](#5.6)

  A constant template argument or an array bound in which a subexpression
references a template parameter[.](#5.6.sentence-1)

- [(5.7)](#5.7)

  A template parameter used in the parameter type of a function parameter that
has a default argument that is being used in the call for which argument
deduction is being done[.](#5.7.sentence-1)

- [(5.8)](#5.8)

  A function parameter for which the associated argument is an
overload set such that one or more of the following apply:
  * [(5.8.1)](#5.8.1)

functions whose associated constraints are satisfied and
that do not all have the same function type
match the function parameter type (resulting in an ambiguous deduction), or

  * [(5.8.2)](#5.8.2)

no function whose associated constraints are satisfied
matches the function parameter type, or

  * [(5.8.3)](#5.8.3)

the overload set supplied as an argument contains one or more function templates[.](#5.8.sentence-1)

  [*Note [2](#note-2)*:
  A particular function from the overload set is selected ([[over.over]](over.over "12.3 Address of an overload set"))
after template argument deduction has succeeded ([[temp.over]](temp.over "13.10.4 Overload resolution"))[.](#5.8.sentence-2)
 â *end note*]

- [(5.9)](#5.9)

  A function parameter for which the associated argument is an initializer
list ([[dcl.init.list]](dcl.init.list "9.5.5 List-initialization")) but the parameter does not have
a type for which deduction from an initializer list is specified ([[temp.deduct.call]](temp.deduct.call "13.10.3.2 Deducing template arguments from a function call"))[.](#5.9.sentence-1)
  [*Example [1](#example-1)*: template<class T> void g(T);
g({1,2,3}); // error: no argument deduced for T â *end example*]

- [(5.10)](#5.10)

  A function parameter pack that does not occur at the end of the[*parameter-declaration-list*](dcl.fct#nt:parameter-declaration-list "9.3.4.6 Functions [dcl.fct]")[.](#5.10.sentence-1)

[6](#6)

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

When a type name is specified in a way that includes a non-deduced
context, all of the types that comprise that type name are also
non-deduced[.](#6.sentence-1)

However, a compound type can include both deduced and non-deduced types[.](#6.sentence-2)

[*Example [2](#example-2)*:

If a type is specified asA<T>​::​B<T2>,
bothT andT2 are non-deduced[.](#6.sentence-3)

Likewise, if a type is specified asA<I+J>​::​X<T>,I,J,
andT are non-deduced[.](#6.sentence-4)

If a type is specified asvoidf(typenameA<T>​::​B,A<T>),
theT inA<T>​::​B is non-deduced but
theT inA<T> is deduced[.](#6.sentence-5)

â *end example*]

[7](#7)

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

[*Example [3](#example-3)*:

Here is an example in which different parameter/argument pairs produce
inconsistent template argument deductions:template<class T> void f(T x, T y) { /* ... */ }struct A { /* ... */ };struct B : A { /* ... */ };void g(A a, B b) { f(a,b); // error: T deduced as both A and B f(b,a); // error: T deduced as both A and B f(a,a); // OK, T is A f(b,b); // OK, T is B}

Here is an example where two template arguments are deduced from a
single function parameter/argument pair[.](#7.sentence-2)

This can lead to conflicts
that cause type deduction to fail:template <class T, class U> void f(T (*)(T, U, U));

int g1(int, float, float);char g2(int, float, float);int g3(int, char, float);

void r() { f(g1); // OK, T is int and U is float f(g2); // error: T deduced as both char and int f(g3); // error: U deduced as both char and float}

Here is an example where the exception specification of a function type
is deduced:template<bool E> void f1(void (*)() noexcept(E));template<bool> struct A { };template<bool B> void f2(void (*)(A<B>) noexcept(B));

void g1();void g2() noexcept;void g3(A<true>);

void h() { f1(g1); // OK, E is false f1(g2); // OK, E is true f2(g3); // error: B deduced as both true and false}

Here is an example where a qualification conversion applies between the
argument type on the function call and the deduced template argument type:template<class T> void f(const T*) { }int* p;void s() { f(p); // f(const int*)}

Here is an example where the template argument is used to instantiate
a derived class type of the corresponding function parameter type:template <class T> struct B { };template <class T> struct D : public B<T> {};struct D2 : public B<int> {};template <class T> void f(B<T>&) {}void t() { D<int> d;
 D2 d2;
 f(d); // calls f(B<int>&) f(d2); // calls f(B<int>&)}

â *end example*]

[8](#8)

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

A type template argument T,
a constant template argument i,
a template template argument TT denoting a class template or an alias template, or
a template template argument VV denoting a variable template or a concept
can be deduced ifP andA have one of the following forms:cvopt T
T* T& T&& Topt[iopt] Topt(Topt) noexcept(iopt) Topt Topt::* TTopt<T> TTopt<i> TTopt<TT> TTopt<VV> TTopt<> where

- [(8.1)](#8.1)

Topt represents a type or parameter-type-list that either
satisfies these rules recursively,
is a non-deduced context in P or A, or
is the same non-dependent type in P and A,

- [(8.2)](#8.2)

iopt represents an expression that either
is an i,
is value-dependent in P or A, or
has the same constant value in P and A,

- [(8.3)](#8.3)

TTopt represents either a class template or
a template template parameter, and

- [(8.4)](#8.4)

noexcept(iopt) represents an
exception specification ([[except.spec]](except.spec "14.5 Exception specifications"))
in which the (possibly-implicit, see [[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")'s operand
satisfies the rules for an iopt above[.](#8.sentence-1)

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

If a type matches such a form but contains noTs, is, or TTs, deduction is not possible[.](#8.sentence-2)

â *end note*]

Similarly,<X> represents template argument lists where
at least one argument contains an X, whereX is one of T, i, TT, or VV;
and<> represents template argument lists where no argument contains aT, an i, a TT, or a VV[.](#8.sentence-3)

[9](#9)

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

If P has a form that contains<T>, <i>, <TT>, or <VV>,
then each argument Pi of the
respective template argument list of P is compared with the
corresponding argument Ai of the corresponding
template argument list of A[.](#9.sentence-1)

If the template argument list
of P contains a pack expansion that is not the last
template argument, the entire template argument list is a non-deduced
context[.](#9.sentence-2)

If Pi is a pack expansion, then the pattern
of Pi is compared with each remaining argument in the
template argument list of A[.](#9.sentence-3)

Each comparison deduces
template arguments for subsequent positions in the template parameter
packs expanded by Pi[.](#9.sentence-4)

During [partial ordering](temp.deduct.partial "13.10.3.5 Deducing template arguments during partial ordering [temp.deduct.partial]"), if Ai was
originally a pack expansion:

- [(9.1)](#9.1)

if P does not contain a template argument corresponding toAi then Ai is ignored;

- [(9.2)](#9.2)

otherwise, if Pi is not a pack expansion, template argument
deduction fails[.](#9.sentence-5)

[*Example [4](#example-4)*: template<class T1, class... Z> class S; // #1template<class T1, class... Z> class S<T1, const Z&...> { }; // #2template<class T1, class T2> class S<T1, const T2&> { }; // #3 S<int, const int&> s; // both #2 and #3 match; #3 is more specializedtemplate<class T, class... U> struct A { }; // #1template<class T1, class T2, class... U> struct A<T1, T2*, U...> { }; // #2template<class T1, class T2> struct A<T1, T2> { }; // #3template struct A<int, int*>; // selects #2 â *end example*]

[10](#10)

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

Similarly, if P has a form that contains(T), then each parameter type Pi of the respective parameter-type-list ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) ofP is compared with the corresponding parameter typeAi of the corresponding parameter-type-list
of A[.](#10.sentence-1)

If P and A are function types that originated from deduction when
taking the address of a function template ([[temp.deduct.funcaddr]](temp.deduct.funcaddr "13.10.3.3 Deducing template arguments taking the address of a function template")) or when
deducing template arguments from a function declaration ([[temp.deduct.decl]](temp.deduct.decl "13.10.3.7 Deducing template arguments from a function declaration"))
and Pi and Ai are parameters of the top-level
parameter-type-list of P and A, respectively,Pi is adjusted if it is a forwarding reference ([[temp.deduct.call]](temp.deduct.call "13.10.3.2 Deducing template arguments from a function call"))
and Ai is an lvalue reference, in which case the type ofPi is changed to be the template parameter type (i.e., T&& is
changed to simply T)[.](#10.sentence-2)

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

As a result, when Pi is T&& and Ai is X&, the adjusted Pi will be T,
causing T to be deduced as X&[.](#10.sentence-3)

â *end note*]

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

If the [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6 Functions [dcl.fct]") corresponding to Pi is a function parameter pack,
then the type of its [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") is compared with
each remaining parameter type in the parameter-type-list
of A[.](#10.sentence-4)

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

During [partial ordering](temp.deduct.partial "13.10.3.5 Deducing template arguments during partial ordering [temp.deduct.partial]"), if Ai was
originally a function parameter pack:

- [(10.1)](#10.1)

if P does not contain a function parameter type corresponding toAi then Ai is ignored;

- [(10.2)](#10.2)

otherwise, if Pi is not a function parameter pack, template
argument deduction fails[.](#10.sentence-6)

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

[11](#11)

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

These forms can be used in the same way asT is for further composition of types[.](#11.sentence-1)

[*Example [7](#example-7)*:

X<int> (*)(char[6]) is of the form[*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]")<T> (*)(*type*[i]) which is a variant of*type* (*)(T) where type isX<int> andT ischar[6][.](#11.sentence-2)

â *end example*]

[12](#12)

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

Template arguments cannot be deduced from function arguments involving
constructs other than the ones specified above[.](#12.sentence-1)

[13](#13)

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

When the value of the argument
corresponding to a constant template parameter P that is declared with a dependent type
is deduced from an expression,
the template parameters in the type of P are deduced from the type of the value[.](#13.sentence-1)

[*Example [8](#example-8)*: template<long n> struct A { };

template<typename T> struct C;template<typename T, T n> struct C<A<n>> {using Q = T;};

using R = long;using R = C<A<2>>::Q; // OK; T was deduced as long from the// template argument value in the type A<2> â *end example*]

[14](#14)

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

The type of N in the type T[N] is std​::​size_t[.](#14.sentence-1)

[*Example [9](#example-9)*: template<typename T> struct S;template<typename T, T n> struct S<int[n]> {using Q = T;};

using V = decltype(sizeof 0);using V = S<int[42]>::Q; // OK; T was deduced as std​::​size_t from the type int[42] â *end example*]

[15](#15)

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

The type of B in the [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")noexcept(B) of a function type is bool[.](#15.sentence-1)

[*Example [10](#example-10)*: template<bool> struct A { };template<auto> struct B;template<auto X, void (*F)() noexcept(X)> struct B<F> { A<X> ax;};void f_nothrow() noexcept;
B<f_nothrow> bn; // OK, type of X deduced as bool â *end example*]

[16](#16)

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

[*Example [11](#example-11)*: template<class T, T i> void f(int (&a)[i]);int v[10];void g() { f(v); // OK, T is std​::​size_t} â *end example*]

[17](#17)

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

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

Except for reference and pointer types, a major array bound is not part of a
function parameter type and cannot be deduced from an argument:template<int i> void f1(int a[10][i]);template<int i> void f2(int a[i][20]);template<int i> void f3(int (&a)[i][20]);

void g() {int v[10][20];
 f1(v); // OK, i deduced as 20 f1<20>(v); // OK f2(v); // error: cannot deduce template-argument i f2<10>(v); // OK f3(v); // OK, i deduced as 10}

â *end note*]

[18](#18)

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

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

If, in the declaration of a function template with a constant
template parameter, the constant template parameter
is used in a subexpression in the function parameter list,
the expression is a non-deduced context as specified above[.](#18.sentence-1)

[*Example [12](#example-12)*: template <int i> class A { /* ... */ };template <int i> void g(A<i+1>);template <int i> void f(A<i>, A<i+1>);void k() { A<1> a1;
 A<2> a2;
 g(a1); // error: deduction fails for expression i+1 g<0>(a1); // OK f(a1, a2); // OK} â *end example*]

â *end note*]

[19](#19)

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

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

Template parameters do not participate in template argument deduction if
they are used only in non-deduced contexts[.](#19.sentence-1)

For example,

template<int i, typename T> T deduce(typename A<T>::X x, // T is not deduced here T t, // but T is deduced heretypename B<i>::Y y); // i is not deduced here A<int> a;
B<77> b;

int x = deduce<77>(a.xm, 62, b.ym);// T deduced as int; a.xm must be convertible to A<int>​::​X// i is explicitly specified to be 77; b.ym must be convertible to B<77>​::​Y â *end note*]

[20](#20)

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

If P has a form that contains <i>, and
if the type of i differs from the type
of the corresponding template parameter
of the template named by the enclosing [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") or[*splice-specialization-specifier*](basic.splice#nt:splice-specialization-specifier "6.6 Splice specifiers [basic.splice]"), deduction fails[.](#20.sentence-1)

If P has a form that contains [i], and if the type ofi is not an integral type, deduction fails[.](#20.sentence-2)[120](#footnote-120 "Although the template-argument corresponding to a template parameter of type bool can be deduced from an array bound, the resulting value will always be true because the array bound will be nonzero.")

If P has a form that includes noexcept(i) and
the type of i is not bool, deduction fails[.](#20.sentence-3)

[*Example [13](#example-13)*: template<int i> class A { /* ... */ };template<short s> void f(A<s>);void k1() { A<1> a;
 f(a); // error: deduction fails for conversion from int to short f<1>(a); // OK}template<const short cs> class B { };template<short s> void g(B<s>);void k2() { B<1> b;
 g(b); // OK, cv-qualifiers are ignored on template parameter types} â *end example*]

[21](#21)

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

A[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") can be deduced from a function, pointer to function, or
pointer-to-member-function type[.](#21.sentence-1)

[*Example [14](#example-14)*: template<class T> void f(void(*)(T,int));template<class T> void foo(T,int);void g(int,int);void g(char,int);

void h(int,int,int);void h(char,int);int m() { f(&g); // error: ambiguous f(&h); // OK, void h(char,int) is a unique match f(&foo); // error: type deduction fails because foo is a template} â *end example*]

[22](#22)

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

A template[*type-parameter*](temp.param#nt:type-parameter "13.2 Template parameters [temp.param]") cannot be deduced from the type of a function default argument[.](#22.sentence-1)

[*Example [15](#example-15)*: template <class T> void f(T = 5, T = 7);void g() { f(1); // OK, calls f<int>(1,7) f(); // error: cannot deduce T f<int>(); // OK, calls f<int>(5,7)} â *end example*]

[23](#23)

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

The[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") corresponding to a template template parameter
is deduced from the type of the[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") of a class template specialization used in the argument list of a function call[.](#23.sentence-1)

[*Example [16](#example-16)*: template <template <class T> class X> struct A { };template <template <class T> class X> void f(A<X>) { }template<class T> struct B { };
A<B> ab;
f(ab); // calls f(A<B>) â *end example*]

[24](#24)

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

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

Template argument deduction involving parameter
packs ([[temp.variadic]](temp.variadic "13.7.4 Variadic templates")) can deduce zero or more arguments for
each parameter pack[.](#24.sentence-1)

â *end note*]

[*Example [17](#example-17)*: template<class> struct X { };template<class R, class ... ArgTypes> struct X<R(int, ArgTypes ...)> { };template<class ... Types> struct Y { };template<class T, class ... Types> struct Y<T, Types& ...> { };

template<class ... Types> int f(void (*)(Types ...));void g(int, float);

X<int> x1; // uses primary template X<int(int, float, double)> x2; // uses partial specialization; ArgTypes contains float, double X<int(float, int)> x3; // uses primary template Y<> y1; // uses primary template; Types is empty Y<int&, float&, double&> y2; // uses partial specialization; T is int&, Types contains float, double Y<int, float, double> y3; // uses primary template; Types contains int, float, doubleint fv = f(g); // OK; Types contains int, float â *end example*]

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

Although the[*template-argument*](temp.names#nt:template-argument "13.3 Names of template specializations [temp.names]") corresponding to a template parameter of typebool can be deduced from an array bound, the resulting value will always betrue because the array bound will be nonzero[.](#footnote-120.sentence-1)
