[temp] (original) (raw)
13 Templates [temp]
13.1 Preamble [temp.pre]
A template defines a family of classes, functions, or variables, an alias for a family of types, or a concept.
[Note 1:
The > token following thetemplate-parameter-list of atemplate-declarationcan be the product of replacing a>> token by two consecutive >tokens ([temp.names]).
— _end note_]
Thedeclarationin atemplate-declaration(if any) shall
- declare or define a function, a class, or a variable, or
- define a member function, a member class, a member enumeration, or a static data member of a class template or of a class nested within a class template, or
- define a member template of a class or class template, or
- be a deduction-guide, or
- be an alias-declaration.
A declaration introduced by a template declaration of avariable is a variable template.
A variable template at class scope is astatic data member template.
[Example 1: template<class T> constexpr T pi = T(3.1415926535897932385L);template<class T> T circular_area(T r) { return pi<T> * r * r;} struct matrix_constants { template<class T> using pauli = hermitian_matrix<T, 2>;template<class T> constexpr static pauli<T> sigma1 = { { 0, 1 }, { 1, 0 } };template<class T> constexpr static pauli<T> sigma2 = { { 0, -1i }, { 1i, 0 } };template<class T> constexpr static pauli<T> sigma3 = { { 1, 0 }, { 0, -1 } };}; — _end example_]
Atemplate-declarationcan appear only as a namespace scope or class scope declaration.
In a function template declaration, the last component of thedeclarator-idshall not be atemplate-id.
[Note 2:
In a class template declaration, if the class name is asimple-template-id, the declaration declares a class template partial specialization.
— _end note_]
In atemplate-declaration, explicit specialization, or explicit instantiation theinit-declarator-listin the declaration shall contain at most one declarator.
When such a declaration is used to declare a class template, no declarator is permitted.
Specializations (explicit or implicit) of a template that has internal linkage are distinct from all specializations in other translation units.
A template, a template explicit specialization, and a class template partial specialization shall not have C linkage.
Use of a linkage specification other than "C" or "C++" with any of these constructs is conditionally-supported, withimplementation-defined semantics.
[Note 3:
Default arguments for function templates and for member functions of class templates are considered definitions for the purpose of template instantiation ([temp.decls]) and must also obey the one-definition rule.
— _end note_]
A class template shall not have the same name as any other template, class, function, variable, enumeration, enumerator, namespace, or type in the same scope ([basic.scope]), except as specified in [temp.class.spec].
Except that a function template can be overloaded either by non-template functions ([dcl.fct]) with the same name or by other function templates with the same name ([temp.over]), a template name declared in namespace scope or in class scope shall be unique in that scope.
An entity is templatedif it is
- a template,
- an entity defined ([basic.def]) or created ([class.temporary]) in a templated entity,
- a member of a templated entity,
- an enumerator for an enumeration that is a templated entity, or
- the closure type of a lambda-expression ([expr.prim.lambda.closure]) appearing in the declaration of a templated entity.
[Note 4:
A local class, a local variable, or a friend function defined in a templated entity is a templated entity.
— _end note_]
A template-declaration is written in terms of its template parameters.
The optional requires-clause following atemplate-parameter-list allows the specification of constraints ([temp.constr.decl]) on template arguments ([temp.arg]).
The requires-clause introduces theconstraint-expression that results from interpreting the constraint-logical-or-expression as aconstraint-expression.
[Note 5:
The expression in a requires-clauseuses a restricted grammar to avoid ambiguities.
Parentheses can be used to specify arbitrary expressions in a requires-clause.
[Example 2: template<int N> requires N == sizeof new unsigned short int f(); — _end example_]
— _end note_]
A definition of a function template, member function of a class template, variable template, or static data member of a class template shall be reachable from the end of every definition domain ([basic.def.odr]) in which it is implicitly instantiated ([temp.inst]) unless the corresponding specialization is explicitly instantiated ([temp.explicit]) in some translation unit; no diagnostic is required.
13.2 Template parameters [temp.param]
The syntax fortemplate-parameter_s_is:
type-parameter-key:
class
typename
[Note 1:
The > token following thetemplate-parameter-list of atype-parametercan be the product of replacing a>> token by two consecutive >tokens ([temp.names]).
— _end note_]
There is no semantic difference betweenclassandtypenamein atype-parameter-key.
typenamefollowed by anunqualified-idnames a template type parameter.
[Example 1: class T { };int i;template<class T, T i> void f(T t) { T t1 = i; ::T t2 = ::i; }
Here, the template f has a type-parametercalled T, rather than an unnamed non-typetemplate-parameter of class T.
— _end example_]
A storage class shall not be specified in atemplate-parameterdeclaration.
Types shall not be defined in a template-parameterdeclaration.
Atype-parameterwhose identifier does not follow an ellipsis defines itsidentifierto be atypedef-name(if declared withouttemplate) ortemplate-name(if declared withtemplate) in the scope of the template declaration.
[Note 2:
A template argument can be a class template or alias template.
For example,
template<class T> class myarray { };template<class K, class V, template<class T> class C = myarray> class Map { C<K> key; C<V> value;}; — _end note_]
A type-constraint Q that designates a concept Ccan be used to constrain a contextually-determined type or template type parameter pack Twith a constraint-expression E defined as follows.
If Q is of the form C<A, ⋯, A>, then let E be C<T, A, ⋯, A>.
Otherwise, let E be C<T>.
If T is not a pack, then E is E, otherwise E is (E && ...).
This constraint-expression E is called theimmediately-declared constraintof Q for T.
The concept designated by a type-constraintshall be a type concept ([temp.concept]).
A type-parameter that starts with a type-constraintintroduces the immediately-declared constraint of the type-constraint for the parameter.
[Example 2: template<typename T> concept C1 = true;template<typename... Ts> concept C2 = true;template<typename T, typename U> concept C3 = true;template<C1 T> struct s1; template<C1... T> struct s2; template<C2... T> struct s3; template<C3<int> T> struct s4; template<C3<int>... T> struct s5; — _end example_]
A non-type template-parametershall have one of the following (possibly cv-qualified) types:
- a structural type (see below),
- a type that contains a placeholder type ([dcl.spec.auto]), or
- a placeholder for a deduced class type ([dcl.type.class.deduct]).
The top-levelcv-qualifier_s_on thetemplate-parameterare ignored when determining its type.
A structural type is one of the following:
- a scalar type, or
- an lvalue reference type, or
- a literal class type with the following properties:
- all base classes and non-static data members are public and non-mutable and
- the types of all bases classes and non-static data members are structural types or (possibly multi-dimensional) array thereof.
An id-expression naming a non-type template-parameter of class type Tdenotes a static storage duration object of type const T, known as a template parameter object, whose value is that of the corresponding template argument after it has been converted to the type of the template-parameter.
All such template parameters in the program of the same type with the same value denote the same template parameter object.
A template parameter object shall have constant destruction ([expr.const]).
[Note 3:
If an id-expression names a non-type non-reference template-parameter, then it is a prvalue if it has non-class type.
Otherwise, if it is of class type T, it is an lvalue and has type const T ([expr.prim.id.unqual]).
— _end note_]
[Example 3: using X = int;struct A {};template<const X& x, int i, A a> void f() { i++; &x; &i; &a; int& ri = i; const int& cri = i; const A& ra = a; } — _end example_]
[Note 4:
A non-typetemplate-parametercannot be declared to have type cv void.
[Example 4: template<void v> class X; template<void* pv> class Y; — _end example_]
— _end note_]
A non-typetemplate-parameter of type “array of T” orof function type Tis adjusted to be of type “pointer to T”.
[Example 5: template<int* a> struct R { };template<int b[5]> struct S { };int p; R<&p> w; S<&p> x; int v[5]; R<v> y; S<v> z; — _end example_]
A non-type template parameter declared with a type that contains a placeholder type with a type-constraintintroduces the immediately-declared constraint of the type-constraintfor the invented type corresponding to the placeholder ([dcl.fct]).
Adefault template-argumentis atemplate-argument ([temp.arg]) specified after=in atemplate-parameter.
A defaulttemplate-argumentmay be specified for any kind oftemplate-parameter(type, non-type, template) that is not a template parameter pack.
A defaulttemplate-argumentmay be specified in a template declaration.
A defaulttemplate-argumentshall not be specified in thetemplate-parameter-list_s_of the definition of a member of a class template that appears outside of the member's class.
A defaulttemplate-argumentshall not be specified in a friend class template declaration.
If a friend function template declaration specifies a defaulttemplate-argument, that declaration shall be a definition and shall be the only declaration of the function template in the translation unit.
The set of defaulttemplate-argument_s_available for use is obtained by merging the default arguments from all prior declarations of the template in the same way default function arguments are ([dcl.fct.default]).
[Example 6:
template<class T1, class T2 = int> class A;template<class T1 = int, class T2> class A;is equivalent totemplate<class T1 = int, class T2 = int> class A;
— _end example_]
If atemplate-parameterof a class template, variable template, or alias template has a defaulttemplate-argument, each subsequenttemplate-parametershall either have a defaulttemplate-argumentsupplied or be a template parameter pack.
If a template-parameterof a primary class template, primary variable template, or alias template is a template parameter pack, it shall be the lasttemplate-parameter.
A template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced from the parameter-type-list ([dcl.fct]) of the function template or has a default argument ([temp.deduct]).
A template parameter of a deduction guide template ([temp.deduct.guide]) that does not have a default argument shall be deducible from the parameter-type-list of the deduction guide template.
[Example 7: template<class T1 = int, class T2> class B; template<class... T, class... U> void f() { } template<class... T, class U> void g() { } — _end example_]
Atemplate-parametershall not be given default arguments by two different declarations in the same scope.
[Example 8: template<class T = int> class X;template<class T = int> class X { }; — _end example_]
When parsing a defaulttemplate-argumentfor a non-typetemplate-parameter, the first non-nested>is taken as the end of thetemplate-parameter-listrather than a greater-than operator.
[Example 9: template<int i = 3 > 4 > class X { };template<int i = (3 > 4) > class Y { }; — _end example_]
Atemplate-parameterof a templatetemplate-parameteris permitted to have a defaulttemplate-argument.
When such default arguments are specified, they apply to the templatetemplate-parameterin the scope of the templatetemplate-parameter.
[Example 10: template <template <class TT = float> class T> struct A { inline void f();inline void g();};template <template <class TT> class T> void A<T>::f() { T<> t; } template <template <class TT = char> class T> void A<T>::g() { T<> t; } — _end example_]
A template parameter pack that is a parameter-declaration whose type contains one or more unexpanded packs is a pack expansion.
Similarly, a template parameter pack that is a type-parameter with atemplate-parameter-list containing one or more unexpanded packs is a pack expansion.
A type parameter pack with a type-constraint that contains an unexpanded parameter pack is a pack expansion.
A template parameter pack that is a pack expansion shall not expand a template parameter pack declared in the sametemplate-parameter-list.
[Example 11: template <class... Types> class Tuple; template <class T, int... Dims> struct multi_array; template <class... T> struct value_holder { template <T... Values> struct apply { }; }; template <class... T, T... Values> struct static_array; — _end example_]
13.3 Names of template specializations [temp.names]
A template specialization can be referred to by atemplate-id:
An identifier is a template-nameif it is associated by name lookup with a template or an overload set that contains a function template, or the identifier is followed by <, the template-id would form an unqualified-id, and name lookup either finds one or more functions or finds nothing.
[Note 1:
Whether a name actually refers to a template cannot be known in some cases until after argument dependent lookup is done ([basic.lookup.argdep]).
— _end note_]
When a name is considered to be atemplate-name, and it is followed by a <, the <is always taken as the delimiter of atemplate-argument-listand never as the less-than operator.
When parsing a template-argument-list, the first non-nested>132is taken as the ending delimiter rather than a greater-than operator.
Similarly, the first non-nested >> is treated as two consecutive but distinct > tokens, the first of which is taken as the end of the template-argument-list and completes the template-id.
[Note 2:
The second >token produced by this replacement rule could terminate an enclosingtemplate-id construct or it could be part of a different construct (e.g., a cast).
— _end note_]
[Example 1: template<int i> class X { }; X< 1>2 > x1; X<(1>2)> x2; template<class T> class Y { }; Y<X<1>> x3; Y<X<6>>1>> x4; Y<X<(6>>1)>> x5; — _end example_]
In these contexts, a < token is always assumed to introduce atemplate-argument-list.
In all other contexts, when naming a template specialization of a member of an unknown specialization ([temp.dep.type]), the member template name shall be prefixed by the keyword template.
[Example 2: struct X { templatestd::size\_t\ X* alloc();templatestd::size\_t\ static X* adjust();};template<class T> void f(T* p) { T* p1 = p->alloc<200>(); T* p2 = p->template alloc<200>(); T::adjust<100>(); T::template adjust<100>(); } — _end example_]
A name prefixed by the keywordtemplateshall be a template-id or the name shall refer to a class template or an alias template.
[Note 3:
The keywordtemplatecannot be applied to non-template members of class templates.
— _end note_]
[Note 4:
As is the case with thetypenameprefix, thetemplateprefix is allowed in cases where it is not strictly necessary; i.e., when the nested-name-specifier or the expression on the left of the->or.is not dependent on atemplate-parameter, or the use does not appear in the scope of a template.
— _end note_]
[Example 3: template <class T> struct A { void f(int);template <class U> void f(U);};template <class T> void f(T t) { A<T> a; a.template f<>(t); a.template f(t); } template <class T> struct B { template <class T2> struct C { };};template <class T, template <class X> class TT = T::template C> struct D { }; D<B<int> > db; — _end example_]
A template-id is valid if
- there are at most as many arguments as there are parameters or a parameter is a template parameter pack ([temp.variadic]),
- there is an argument for each non-deducible non-pack parameter that does not have a default template-argument,
- each template-argument matches the correspondingtemplate-parameter ([temp.arg]),
- substitution of each template argument into the following template parameters (if any) succeeds, and
- if the template-id is non-dependent, the associated constraints are satisfied as specified in the next paragraph.
A simple-template-id shall be valid unless it names a function template specialization ([temp.deduct]).
[Example 4: template<class T, T::type n = 0> class X;struct S { using type = int;};using T1 = X<S, int, int>; using T2 = X<>; using T3 = X<1>; using T4 = X<int>; using T5 = X<S>; — _end example_]
When the template-nameof a simple-template-idnames a constrained non-function template or a constrained template template-parameter, but not a member template that is a member of an unknown specialization ([temp.res]), and all template-argument_s_in the simple-template-idare non-dependent ([temp.dep.temp]), the associated constraints ([temp.constr.decl]) of the constrained template shall be satisfied ([temp.constr.constr]).
[Example 5: template<typename T> concept C1 = sizeof(T) != sizeof(int);template<C1 T> struct S1 { };template<C1 T> using Ptr = T*; S1<int>* p; Ptr<int> p; template<typename T> struct S2 { Ptr<int> x; }; template<typename T> struct S3 { Ptr<T> x; }; S3<int> x; template<template<C1 T> class X> struct S4 { X<int> x; };template<typename T> concept C2 = sizeof(T) == 1;template<C2 T> struct S { };template struct S<char[2]>; template<> struct S<char[2]> { }; — _end example_]
A concept-id is a simple-template-idwhere the template-name is a concept-name.
A concept-id is a prvalue of type bool, and does not name a template specialization.
A concept-id evaluates to trueif the concept's normalized constraint-expression ([temp.constr.decl]) is satisfied ([temp.constr.constr]) by the specified template arguments andfalse otherwise.
[Note 5:
Since a constraint-expression is an unevaluated operand, a concept-id appearing in a constraint-expressionis not evaluated except as necessary to determine whether the normalized constraints are satisfied.
— _end note_]
[Example 6: template<typename T> concept C = true;static_assert(C<int>); — _end example_]
13.4 Template arguments [temp.arg]
13.4.1 General [temp.arg.general]
There are three forms oftemplate-argument, corresponding to the three forms oftemplate-parameter: type, non-type and template.
The type and form of eachtemplate-argumentspecified in atemplate-idshall match the type and form specified for the corresponding parameter declared by the template in itstemplate-parameter-list.
When the parameter declared by the template is atemplate parameter pack, it will correspond to zero or moretemplate-arguments.
[Example 1: template<class T> class Array { T* v;int sz;public: explicit Array(int); T& operator[](int); T& elem(int i) { return v[i]; } }; Array<int> v1(20);typedef std::complex<double> dcomplex; Array<dcomplex> v2(30); Array<dcomplex> v3(40);void bar() { v1[3] = 7; v2[3] = v3.elem(4) = dcomplex(7,8);} — _end example_]
In atemplate-argument, an ambiguity between atype-idand an expression is resolved to atype-id, regardless of the form of the correspondingtemplate-parameter.133
[Example 2: template<class T> void f();template<int I> void f();void g() { f<int()>(); } — _end example_]
The name of atemplate-argumentshall be accessible at the point where it is used as atemplate-argument.
[Note 1:
If the name of thetemplate-argumentis accessible at the point where it is used as atemplate-argument, there is no further access restriction in the resulting instantiation where the correspondingtemplate-parametername is used.
— _end note_]
[Example 3: template<class T> class X { static T t;};class Y { private: struct S { }; X<S> x; }; X<Y::S> y; — _end example_]
For atemplate-argumentthat is a class type or a class template, the template definition has no special access rights to the members of the template-argument.
[Example 4: template <template <class TT> class T> class A { typename T<int>::S s;};template <class U> class B { private: struct S { };}; A<B> b; — _end example_]
When template argument packs or defaulttemplate-argument_s_are used, atemplate-argumentlist can be empty.
In that case the empty<>brackets shall still be used as thetemplate-argument-list.
[Example 5: template<class T = char> class String; String<>* p; String* q; template<class ... Elements> class Tuple; Tuple<>* t; Tuple* u; — _end example_]
An explicit destructor call ([class.dtor]) for an object that has a type that is a class template specialization may explicitly specify thetemplate-arguments.
[Example 6: template<class T> struct A { ~A();};void f(A<int>* p, A<int>* q) { p->A<int>::~A(); q->A<int>::~A<int>(); } — _end example_]
If the use of atemplate-argumentgives rise to an ill-formed construct in the instantiation of a template specialization, the program is ill-formed.
When name lookup for the name in atemplate-idfinds an overload set, both non-template functions in the overload set and function templates in the overload set for which thetemplate-argument_s_do not match thetemplate-parameter_s_are ignored.
If none of the function templates have matchingtemplate-parameters, the program is ill-formed.
When a simple-template-id does not name a function, a default template-argument isimplicitly instantiatedwhen the value of that default argument is needed.
[Example 7: template<typename T, typename U = int> struct S { }; S<bool>* p;
The default argument for U is instantiated to form the type S<bool, int>*.
— _end example_]
A template-argument followed by an ellipsis is a pack expansion.
13.4.2 Template type arguments [temp.arg.type]
[Example 1: template <class T> class X { };template <class T> void f(T t) { } struct { } unnamed_obj;void f() { struct A { };enum { e1 };typedef struct { } B; B b; X<A> x1; X<A*> x2; X<B> x3; f(e1); f(unnamed_obj); f(b); } — _end example_]
[Note 1:
A template type argument can be an incomplete type ([basic.types]).
— _end note_]
13.4.3 Template non-type arguments [temp.arg.nontype]
If the type T of a template-parameter ([temp.param]) contains a placeholder type ([dcl.spec.auto]) or a placeholder for a deduced class type ([dcl.type.class.deduct]), the type of the parameter is the type deduced for the variable x in the invented declarationT x = template-argument ;
If a deduced parameter type is not permitted for a template-parameter declaration ([temp.param]), the program is ill-formed.
A template-argumentfor a non-type template-parametershall be a converted constant expression ([expr.const]) of the type of the template-parameter.
[Note 1:
If the template-argumentis an overload set (or the address of such, including forming a pointer-to-member), the matching function is selected from the set ([over.over]).
— _end note_]
For a non-type template-parameter of reference or pointer type, or for each non-static data member of reference or pointer type in a non-type template-parameter of class type or subobject thereof, the reference or pointer value shall not refer to or be the address of (respectively):
- a temporary object ([class.temporary]),
- a string literal object ([lex.string]),
- the result of a typeid expression ([expr.typeid]),
- a predefined __func__ variable ([dcl.fct.def.general]), or
- a subobject ([intro.object]) of one of the above.
[Example 1: template<const int* pci> struct X { };int ai[10]; X<ai> xi; struct Y { };template<const Y& b> struct Z { }; Y y; Z<y> z; template<int (&pa)[5]> struct W { };int b[5]; W<b> w; void f(char);void f(int);template<void (*pf)(int)> struct A { }; A<&f> a; template<auto n> struct B { }; B<5> b1; B<'a'> b2; B<2.5> b3; B<void(0)> b4; — _end example_]
[Note 2:
[Example 2: template<class T, T p> class X { }; X<const char*, "Studebaker"> x; X<const char*, "Knope" + 1> x2; const char p[] = "Vivisectionist"; X<const char*, p> y; struct A { constexpr A(const char*) {} }; X<A, "Pyrophoricity"> z; — _end example_]
— _end note_]
[Note 3:
A temporary object is not an acceptabletemplate-argumentwhen the correspondingtemplate-parameterhas reference type.
[Example 3: template<const int& CRI> struct B { }; B<1> b1; int c = 1; B<c> b2; struct X { int n; };struct Y { const int &r; };template<Y y> struct C { }; C<Y{X{1}.n}> c; — _end example_]
— _end note_]
13.4.4 Template template arguments [temp.arg.template]
Atemplate-argumentfor a templatetemplate-parametershall be the name of a class template or an alias template, expressed asid-expression.
When the template-argument names a class template, only primary class templates are considered when matching the template template argument with the corresponding parameter; partial specializations are not considered even if their parameter lists match that of the template template parameter.
Any partial specializations associated with the primary class template or primary variable template are considered when a specialization based on the templatetemplate-parameteris instantiated.
If a specialization is not visible at the point of instantiation, and it would have been selected had it been visible, the program is ill-formed, no diagnostic required.
[Example 1: template<class T> class A { int x;};template<class T> class A<T*> { long x;};template<template<class U> class V> class C { V<int> y; V<int*> z;}; C<A> c; — _end example_]
A template-argument matches a templatetemplate-parameter P whenP is at least as specialized as the template-argument A.
In this comparison, if P is unconstrained, the constraints on A are not considered.
If P contains a template parameter pack, then A also matches Pif each of A's template parameters matches the corresponding template parameter in thetemplate-head of P.
Two template parameters match if they are of the same kind (type, non-type, template), for non-type template-parameters, their types are equivalent ([temp.over.link]), and for template template-parameters, each of their corresponding template-parameters matches, recursively.
When P's template-head contains a template parameter pack ([temp.variadic]), the template parameter pack will match zero or more template parameters or template parameter packs in the template-head ofA with the same type and form as the template parameter pack in P(ignoring whether those template parameters are template parameter packs).
[Example 2: template<class T> class A { };template<class T, class U = T> class B { };template<class ... Types> class C { };template<auto n> class D { };template<template<class> class P> class X { };template<template<class ...> class Q> class Y { };template<template<int> class R> class Z { }; X<A> xa; X<B> xb; X<C> xc; Y<A> ya; Y<B> yb; Y<C> yc; Z<D> zd; — _end example_]
[Example 3: template <class T> struct eval;template <template <class, class...> class TT, class T1, class... Rest> struct eval<TT<T1, Rest...>> { };template <class T1> struct A;template <class T1, class T2> struct B;template <int N> struct C;template <class T1, int N> struct D;template <class T1, class T2, int N = 17> struct E; eval<A<int>> eA; eval<B<int, float>> eB; eval<C<17>> eC; eval<D<int, 17>> eD; eval<E<int, float>> eE; — _end example_]
[Example 4: template<typename T> concept C = requires (T t) { t.f(); };template<typename T> concept D = C<T> && requires (T t) { t.g(); };template<template<C> class P> struct S { };template<C> struct X { };template<D> struct Y { };template<typename T> struct Z { }; S<X> s1; S<Y> s2; S<Z> s3; — _end example_]
A template template-parameter P is at least as specialized as a template template-argument Aif, given the following rewrite to two function templates, the function template corresponding to Pis at least as specialized as the function template corresponding to Aaccording to the partial ordering rules for function templates.
Given an invented class template Xwith the template-head of A (including default arguments and requires-clause, if any):
- Each of the two function templates has the same template parameters and requires-clause (if any), respectively, as P or A.
- Each function template has a single function parameter whose type is a specialization of Xwith template arguments corresponding to the template parameters from the respective function template where, for each template parameter PPin the template-head of the function template, a corresponding template argument AA is formed.
If PP declares a template parameter pack, then AA is the pack expansion PP... ([temp.variadic]); otherwise, AA is the id-expression PP.
If the rewrite produces an invalid type, then P is not at least as specialized as A.
13.5 Template constraints [temp.constr]
13.5.1 General [temp.constr.general]
[Note 1:
Subclause [temp.constr] defines the meaning of constraints on template arguments.
The abstract syntax and satisfaction rules are defined in [temp.constr.constr].
Constraints are associated with declarations in [temp.constr.decl].
Declarations are partially ordered by their associated constraints ([temp.constr.order]).
— _end note_]
13.5.2 Constraints [temp.constr.constr]
13.5.2.1 General [temp.constr.constr.general]
A constraint is a sequence of logical operations and operands that specifies requirements on template arguments.
The operands of a logical operation are constraints.
There are three different kinds of constraints:
In order for a constrained template to be instantiated ([temp.spec]), its associated constraintsshall be satisfied as described in the following subclauses.
[Note 1:
Forming the name of a specialization of a class template, a variable template, or an alias template ([temp.names]) requires the satisfaction of its constraints.
Overload resolutionrequires the satisfaction of constraints on functions and function templates.
— _end note_]
13.5.2.2 Logical operations [temp.constr.op]
There are two binary logical operations on constraints: conjunction and disjunction.
[Note 1:
These logical operations have no corresponding C++ syntax.
For the purpose of exposition, conjunction is spelled using the symbol ∧ and disjunction is spelled using the symbol ∨.
The operands of these operations are called the left and right operands.
In the constraint ,A is the left operand, and B is the right operand.
— _end note_]
A conjunction is a constraint taking two operands.
To determine if a conjunction issatisfied, the satisfaction of the first operand is checked.
If that is not satisfied, the conjunction is not satisfied.
Otherwise, the conjunction is satisfied if and only if the second operand is satisfied.
A disjunction is a constraint taking two operands.
To determine if a disjunction issatisfied, the satisfaction of the first operand is checked.
If that is satisfied, the disjunction is satisfied.
Otherwise, the disjunction is satisfied if and only if the second operand is satisfied.
[Example 1: template<typename T> constexpr bool get_value() { return T::value; } template<typename T> requires (sizeof(T) > 1) && (get_value<T>()) void f(T); void f(int); f('a');
In the satisfaction of the associated constraintsof f, the constraint sizeof(char) > 1 is not satisfied; the second operand is not checked for satisfaction.
— _end example_]
[Note 2:
A logical negation expression ([expr.unary.op]) is an atomic constraint; the negation operator is not treated as a logical operation on constraints.
As a result, distinct negation constraint-expression_s_that are equivalent under [temp.over.link]do not subsume one another under [temp.constr.order].
Furthermore, if substitution to determine whether an atomic constraint is satisfied ([temp.constr.atomic]) encounters a substitution failure, the constraint is not satisfied, regardless of the presence of a negation operator.
[Example 2: template <class T> concept sad = false;template <class T> int f1(T) requires (!sad<T>);template <class T> int f1(T) requires (!sad<T>) && true;int i1 = f1(42); template <class T> concept not_sad = !sad<T>;template <class T> int f2(T) requires not_sad<T>;template <class T> int f2(T) requires not_sad<T> && true;int i2 = f2(42); template <class T> int f3(T) requires (!sad<typename T::type>);int i3 = f3(42); template <class T> concept sad_nested_type = sad<typename T::type>;template <class T> int f4(T) requires (!sad_nested_type<T>);int i4 = f4(42);
Here,requires (!sad<typename T::type>) requires that there is a nested type that is not sad, whereasrequires (!sad_nested_type<T>) requires that there is no sad nested type.
— _end example_]
— _end note_]
13.5.2.3 Atomic constraints [temp.constr.atomic]
An atomic constraint is formed from an expression Eand a mapping from the template parameters that appear within E to template arguments that are formed via substitution during constraint normalization in the declaration of a constrained entity (and, therefore, can involve the unsubstituted template parameters of the constrained entity), called the parameter mapping ([temp.constr.decl]).
[Note 1:
Atomic constraints are formed by constraint normalization.
— _end note_]
Two atomic constraints, and , areidenticalif they are formed from the same appearance of the sameexpressionand if, given a hypothetical template Awhose template-parameter-list consists oftemplate-parameters corresponding and equivalent ([temp.over.link]) to those mapped by the parameter mappings of the expression, a template-id naming Awhose template-arguments are the targets of the parameter mapping of is the same ([temp.type]) as a template-id naming Awhose template-arguments are the targets of the parameter mapping of .
[Note 2:
The comparison of parameter mappings of atomic constraints operates in a manner similar to that of declaration matching with alias template substitution ([temp.alias]).
[Example 1: template <unsigned N> constexpr bool Atomic = true;template <unsigned N> concept C = Atomic<N>;template <unsigned N> concept Add1 = C<N + 1>;template <unsigned N> concept AddOne = C<N + 1>;template <unsigned M> void f() requires Add1<2 * M>;template <unsigned M> int f() requires AddOne<2 * M> && true;int x = f<0>(); template <unsigned N> struct WrapN;template <unsigned N> using Add1Ty = WrapN<N + 1>;template <unsigned N> using AddOneTy = WrapN<N + 1>;template <unsigned M> void g(Add1Ty<2 * M> *);template <unsigned M> void g(AddOneTy<2 * M> *);void h() { g<0>(nullptr); } — _end example_]
This similarity includes the situation where a program is ill-formed, no diagnostic required, when the meaning of the program depends on whether two constructs are equivalent, and they are functionally equivalent but not equivalent.
[Example 2: template <unsigned N> void f2() requires Add1<2 * N>;template <unsigned N> int f2() requires Add1<N * 2> && true;void h2() { f2<0>(); } — _end example_]
— _end note_]
To determine if an atomic constraint issatisfied, the parameter mapping and template arguments are first substituted into its expression.
If substitution results in an invalid type or expression, the constraint is not satisfied.
Otherwise, the lvalue-to-rvalue conversionis performed if necessary, and E shall be a constant expression of type bool.
The constraint is satisfied if and only if evaluation of Eresults in true.
If, at different points in the program, the satisfaction result is different for identical atomic constraints and template arguments, the program is ill-formed, no diagnostic required.
[Example 3: template<typename T> concept C = sizeof(T) == 4 && !true; template<typename T> struct S { constexpr operator bool() const { return true; } };template<typename T> requires (S<T>{}) void f(T); void f(int); void g() { f(0); } — _end example_]
13.5.3 Constrained declarations [temp.constr.decl]
A template declaration ([temp.pre]) or templated function declaration ([dcl.fct]) can be constrained by the use of a requires-clause.
This allows the specification of constraints for that declaration as an expression:
Constraints can also be associated with a declaration through the use oftype-constraint_s_in a template-parameter-list or parameter-type-list.
Each of these forms introduces additional constraint-expression_s_that are used to constrain the declaration.
A declaration's associated constraints are defined as follows:
- If there are no introduced constraint-expressions, the declaration has no associated constraints.
- Otherwise, if there is a single introduced constraint-expression, the associated constraints are the normal formof that expression.
- Otherwise, the associated constraints are the normal form of a logical AND expression whose operands are in the following order:
- the constraint-expression introduced by each type-constraint ([temp.param]) in the declaration's template-parameter-list, in order of appearance, and
- the constraint-expression introduced by a requires-clause following a template-parameter-list ([temp.pre]), and
- the constraint-expression introduced by each type-constraint in the parameter-type-list of a function declaration, and
- the constraint-expression introduced by a trailing requires-clause ([dcl.decl]) of a function declaration ([dcl.fct]).
The formation of the associated constraints establishes the order in which constraints are instantiated when checking for satisfaction ([temp.constr.constr]).
[Example 1: template<typename T> concept C = true;template<C T> void f1(T);template<typename T> requires C<T> void f2(T);template<typename T> void f3(T) requires C<T>;
The functions f1, f2, and f3 have the associated constraint C<T>.
template<typename T> concept C1 = true;template<typename T> concept C2 = sizeof(T) > 0;template<C1 T> void f4(T) requires C2<T>;template<typename T> requires C1<T> && C2<T> void f5(T);
The associated constraints of f4 and f5are C1<T> ∧ C2<T>.
template<C1 T> requires C2<T> void f6();template<C2 T> requires C1<T> void f7();
The associated constraints off6 are C1<T> ∧ C2<T>, and those off7 are C2<T> ∧ C1<T>.
— _end example_]
When determining whether a given introducedconstraint-expression of a declaration in an instantiated specialization of a templated class is equivalent ([temp.over.link]) to the correspondingconstraint-expression of a declaration outside the class body, is instantiated.
If the instantiation results in an invalid expression, the constraint-expressions are not equivalent.
[Note 1:
This can happen when determining which member template is specialized by an explicit specialization declaration.
— _end note_]
[Example 2: template <class T> concept C = true;template <class T> struct A { template <class U> U f(U) requires C<typename T::type>; template <class U> U f(U) requires C<T>; };template <> template <class U>U A<int>::f(U u) requires C<int> { return u; }
Substituting int for T in C<typename T::type>produces an invalid expression, so the specialization does not match #1.
Substituting int for T in C<T> produces C<int>, which is equivalent to the constraint-expression for the specialization, so it does match #2.
— _end example_]
13.5.4 Constraint normalization [temp.constr.normal]
The normal form of an expression E is a constraint that is defined as follows:
- The normal form of an expression ( E ) is the normal form of E.
- The normal form of an expression E1 || E2 is the disjunction of the normal forms of E1 and E2.
- The normal form of an expression E1 && E2is the conjunction of the normal forms of E1 and E2.
- The normal form of a concept-id C<A, A, ..., A>is the normal form of the constraint-expression of C, after substituting A, A, ..., A forC's respective template parameters in the parameter mappings in each atomic constraint.
If any such substitution results in an invalid type or expression, the program is ill-formed; no diagnostic is required.
[Example 1: template<typename T> concept A = T::value || true;template<typename U> concept B = A<U*>;template<typename V> concept C = B<V&>;
Normalization of B's constraint-expressionis valid and results inT::value (with the mapping )∨ true (with an empty mapping), despite the expression T::value being ill-formed for a pointer type T.
Normalization of C's constraint-expressionresults in the program being ill-formed, because it would form the invalid type V&*in the parameter mapping.
— _end example_] - The normal form of any other expression E is the atomic constraint whose expression is E and whose parameter mapping is the identity mapping.
The process of obtaining the normal form of aconstraint-expressionis callednormalization.
[Note 1:
Normalization of constraint-expression_s_is performed when determining the associated constraints ([temp.constr.constr]) of a declaration and when evaluating the value of an id-expressionthat names a concept specialization ([expr.prim.id]).
— _end note_]
[Example 2: template<typename T> concept C1 = sizeof(T) == 1;template<typename T> concept C2 = C1<T> && 1 == 2;template<typename T> concept C3 = requires { typename T::type; };template<typename T> concept C4 = requires (T x) { ++x; } template<C2 U> void f1(U); template<C3 U> void f2(U); template<C4 U> void f3(U);
The associated constraints of #1 aresizeof(T) == 1 (with mapping ) ∧ 1 == 2.
The associated constraints of #2 arerequires { typename T::type; } (with mapping ).
The associated constraints of #3 arerequires (T x) { ++x; } (with mapping ).
— _end example_]
13.5.5 Partial ordering by constraints [temp.constr.order]
A constraint P subsumes a constraint Qif and only if, for every disjunctive clause in the disjunctive normal form134of P, subsumes every conjunctive clause in the conjunctive normal form135of Q, where
- a disjunctive clause subsumes a conjunctive clause if and only if there exists an atomic constraint in for which there exists an atomic constraint in such that subsumes , and
- an atomic constraint A subsumes another atomic constraintB if and only if A and B are identical using the rules described in [temp.constr.atomic].
[Example 1:
Let A and B be atomic constraints.
The constraint subsumes A, but A does not subsume .
The constraint A subsumes , but does not subsume A.
Also note that every constraint subsumes itself.
— _end example_]
[Note 1:
The subsumption relation defines a partial ordering on constraints.
This partial ordering is used to determine
- the best viable candidate of non-template functions ([over.match.best]),
- the address of a non-template function ([over.over]),
- the matching of template template arguments,
- the partial ordering of class template specializations, and
- the partial ordering of function templates.
— _end note_]
A declaration D1 isat least as constrained as a declaration D2 if
- D1 and D2 are both constrained declarations andD1's associated constraints subsume those of D2; or
- D2 has no associated constraints.
A declaration D1 is more constrainedthan another declaration D2 when D1 is at least as constrained as D2, and D2 is not at least as constrained as D1.
[Example 2: template<typename T> concept C1 = requires(T t) { --t; };template<typename T> concept C2 = C1<T> && requires(T t) { *t; };template<C1 T> void f(T); template<C2 T> void f(T); template<typename T> void g(T); template<C1 T> void g(T); f(0); f((int*)0); g(true); g(0); — _end example_]
13.6 Type equivalence [temp.type]
Two template-ids are the same if
- their template-names,operator-function-ids, orliteral-operator-id_s_refer to the same template, and
- their corresponding type template-argument_s_are the same type, and
- their corresponding non-type template-argument_s_are template-argument-equivalent (see below) after conversion to the type of the template-parameter, and
- their corresponding template template-argument_s_refer to the same template.
Two template-ids that are the same refer to the same class, function, or variable.
Two values are template-argument-equivalent if they are of the same type and
- they are of integral type and their values are the same, or
- they are of floating-point type and their values are identical, or
- they are of type std::nullptr_t, or
- they are of enumeration type and their values are the same,136or
- they are of pointer type and they have the same pointer value, or
- they are of pointer-to-member type and they refer to the same class member or are both the null member pointer value, or
- they are of reference type and they refer to the same object or function, or
- they are of array type and their corresponding elements are template-argument-equivalent,137or
- they are of union type and either they both have no active member or they have the same active member and their active members are template-argument-equivalent, or
- they are of class type and their corresponding direct subobjects and reference members are template-argument-equivalent.
[Example 1:
template<class E, int size> class buffer { }; buffer<char,2*512> x; buffer<char,1024> y;declaresxandyto be of the same type, andtemplate<class T, void(*err_fct)()> class list { }; list<int,&error_handler1> x1; list<int,&error_handler2> x2; list<int,&error_handler2> x3; list<char,&error_handler2> x4;declaresx2andx3to be of the same type.
Their type differs from the types ofx1andx4.
template<class T> struct X { };template<class> struct Y { };template<class T> using Z = Y<T>; X<Y<int> > y; X<Z<int> > z;declares y and z to be of the same type.
— _end example_]
If an expression e is type-dependent,decltype(e)denotes a unique dependent type.
[Note 1:
However, such a type might be aliased, e.g., by a typedef-name.
— _end note_]
13.7 Template declarations [temp.decls]
13.7.1 General [temp.decls.general]
Atemplate-id, that is, thetemplate-namefollowed by atemplate-argument-listshall not be specified in the declaration of a primary template declaration.
[Example 1: template<class T1, class T2, int I> class A<T1, T2, I> { }; template<class T1, int I> void sort<T1, I>(T1 data[I]); — _end example_]
[Note 1:
However, this syntax is allowed in class template partial specializations.
— _end note_]
For purposes of name lookup and instantiation, default arguments,type-constraints,requires-clauses ([temp.pre]), andnoexcept-specifier_s_of function templates and of member functions of class templates are considered definitions; each default argument,type-constraint,requires-clause, ornoexcept-specifieris a separate definition which is unrelated to the templated function definition or to any other default argumentstype-constraints,requires-clauses, ornoexcept-specifiers.
For the purpose of instantiation, the substatements of aconstexpr if statement are considered definitions.
Because an alias-declaration cannot declare atemplate-id, it is not possible to partially or explicitly specialize an alias template.
13.7.2 Class templates [temp.class]
13.7.2.1 General [temp.class.general]
Aclass templatedefines the layout and operations for an unbounded set of related types.
[Example 1:
A single class templateListmight provide an unbounded set of class definitions: one class List<T> for every type T, each describing a linked list of elements of type T.
Similarly, a class template Array describing a contiguous, dynamic array might be defined like this:template<class T> class Array { T* v;int sz;public: explicit Array(int); T& operator[](int); T& elem(int i) { return v[i]; } };
The prefix template<class T>specifies that a template is being declared and that atype-name Tmay be used in the declaration.
In other words,Arrayis a parameterized type withTas its parameter.
— _end example_]
When a member function, a member class, a member enumeration, a static data member or a member template of a class template is defined outside of the class template definition, the member definition is defined as a template definition in which thetemplate-head is equivalent to that of the class template ([temp.over.link]).
The names of the template parameters used in the definition of the member may be different from the template parameter names used in the class template definition.
The template argument list following the class template name in the member definition shall name the parameters in the same order as the one used in the template parameter list of the member.
Each template parameter pack shall be expanded with an ellipsis in the template argument list.
[Example 2: template<class T1, class T2> struct A { void f1();void f2();};template<class T2, class T1> void A<T2,T1>::f1() { } template<class T2, class T1> void A<T1,T2>::f2() { }
template<class ... Types> struct B { void f3();void f4();};template<class ... Types> void B<Types ...>::f3() { } template<class ... Types> void B<Types>::f4() { }
template<typename T> concept C = true;template<typename T> concept D = true;template<C T> struct S { void f();void g();void h();template<D U> struct Inner;};template<C A> void S<A>::f() { } template<typename T> void S<T>::g() { } template<typename T> requires C<T> void S<T>::h() { } template<C X> template<D Y> struct S<X>::Inner { }; — _end example_]
In a redeclaration, partial specialization, explicit specialization or explicit instantiation of a class template, theclass-keyshall agree in kind with the original class template declaration ([dcl.type.elab]).
13.7.2.2 Member functions of class templates [temp.mem.func]
A member function of a class template may be defined outside of the class template definition in which it is declared.
[Example 1: template<class T> class Array { T* v;int sz;public: explicit Array(int); T& operator[](int); T& elem(int i) { return v[i]; } };
declares three member functions of a class template.
The subscript function might be defined like this:template<class T> T& Array<T>::operator[](int i) { if (i<0 || sz<=i) error("Array: range error");return v[i];}
A constrained member function can be defined out of line:template<typename T> concept C = requires { typename T::type;};template<typename T> struct S { void f() requires C<T>;void g() requires C<T>;};template<typename T> void S<T>::f() requires C<T> { } template<typename T> void S<T>::g() { }
— _end example_]
Thetemplate-argument_s_for a member function of a class template are determined by thetemplate-argument_s_of the type of the object for which the member function is called.
[Example 2:
Thetemplate-argumentforArray<T>::operator[]will be determined by theArrayto which the subscripting operation is applied.
Array<int> v1(20); Array<dcomplex> v2(30); v1[3] = 7; v2[3] = dcomplex(7,8); — _end example_]
13.7.2.3 Deduction guides [temp.deduct.guide]
Deduction guides are used when a template-name appears as a type specifier for a deduced class type ([dcl.type.class.deduct]).
Deduction guides are not found by name lookup.
Instead, when performing class template argument deduction ([over.match.class.deduct]), any deduction guides declared for the class template are considered.
[Example 1: template<class T, class D = int> struct S { T data;};template<class U>S(U) -> S<typename U::type>;struct A { using type = short;operator type();}; S x{A()}; — _end example_]
The simple-template-idshall name a class template specialization.
A deduction-guideshall be declared in the same scope as the corresponding class template and, for a member class template, with the same access.
Two deduction guide declarations in the same translation unit for the same class template shall not have equivalent parameter-declaration-clauses.
13.7.2.4 Member classes of class templates [temp.mem.class]
A member class of a class template may be defined outside the class template definition in which it is declared.
[Note 1:
The member class must be defined before its first use that requires an instantiation ([temp.inst]).
For example,template<class T> struct A { class B;}; A<int>::B* b1; template<class T> class A<T>::B { }; A<int>::B b2;
— _end note_]
13.7.2.5 Static data members of class templates [temp.static]
A definition for a static data member or static data member template may be provided in a namespace scope enclosing the definition of the static member's class template.
[Example 1: template<class T> class X { static T s;};template<class T> T X<T>::s = 0;struct limits { template<class T> static const T min; };template<class T> const T limits::min = { }; — _end example_]
An explicit specialization of a static data member declared as an array of unknown bound can have a different bound from its definition, if any.
[Example 2: template <class T> struct A { static int i[];};template <class T> int A<T>::i[4]; template <> int A<int>::i[] = { 1 }; — _end example_]
13.7.2.6 Enumeration members of class templates [temp.mem.enum]
An enumeration member of a class template may be defined outside the class template definition.
[Example 1: template<class T> struct A { enum E : T;}; A<int> a;template<class T> enum A<T>::E : T { e1, e2 }; A<int>::E e = A<int>::e1; — _end example_]
13.7.3 Member templates [temp.mem]
A template can be declared within a class or class template; such a template is called a member template.
A member template can be defined within or outside its class definition or class template definition.
A member template of a class template that is defined outside of its class template definition shall be specified with a template-head equivalent to that of the class template followed by a template-head equivalent to that of the member template ([temp.over.link]).
[Example 1: template<class T> struct string { template<class T2> int compare(const T2&);template<class T2> string(const string<T2>& s) { } };template<class T> template<class T2> int string<T>::compare(const T2& s) { } — _end example_]
[Example 2: template<typename T> concept C1 = true;template<typename T> concept C2 = sizeof(T) <= 4;template<C1 T> struct S { template<C2 U> void f(U);template<C2 U> void g(U);};template<C1 T> template<C2 U> void S<T>::f(U) { } template<C1 T> template<typename U> void S<T>::g(U) { } — _end example_]
A local class of non-closure type shall not have member templates.
A destructor shall not be a member template.
A non-template member function ([dcl.fct]) with a given name and type and a member function template of the same name, which could be used to generate a specialization of the same type, can both be declared in a class.
When both exist, a use of that name and type refers to the non-template member unless an explicit template argument list is supplied.
[Example 3: template <class T> struct A { void f(int);template <class T2> void f(T2);};template <> void A<int>::f(int) { } template <> template <> void A<int>::f<>(int) { } int main() { A<char> ac; ac.f(1); ac.f('c'); ac.f<>(1); } — _end example_]
A member function template shall not be declared virtual.
[Example 4: template <class T> struct AA { template <class C> virtual void g(C); virtual void f(); }; — _end example_]
A specialization of a member function template does not override a virtual function from a base class.
[Example 5: class B { virtual void f(int);};class D : public B { template <class T> void f(T); void f(int i) { f<>(i); } }; — _end example_]
A specialization of a conversion function template is referenced in the same way as a non-template conversion function that converts to the same type.
[Example 6: struct A { template <class T> operator T*();};template <class T> A::operator T*(){ return 0; } template <> A::operator char*(){ return 0; } template A::operator void*(); int main() { A a;int* ip; ip = a.operator int*(); } — _end example_]
[Note 1:
There is no syntax to form a template-id ([temp.names]) by providing an explicit template argument list ([temp.arg.explicit]) for a conversion function template ([class.conv.fct]).
— _end note_]
A specialization of a conversion function template is not found by name lookup.
Instead, any conversion function templates visible in the context of the use are considered.
For each such operator, if argument deduction succeeds ([temp.deduct.conv]), the resulting specialization is used as if found by name lookup.
A using-declaration in a derived class cannot refer to a specialization of a conversion function template in a base class.
Overload resolution and partial ordering are used to select the best conversion function among multiple specializations of conversion function templates and/or non-template conversion functions.
13.7.4 Variadic templates [temp.variadic]
A template parameter pack is a template parameter that accepts zero or more template arguments.
[Example 1: template<class ... Types> struct Tuple { }; Tuple<> t0; Tuple<int> t1; Tuple<int, float> t2; Tuple<0> error; — _end example_]
A function parameter pack is a function parameter that accepts zero or more function arguments.
[Example 2: template<class ... Types> void f(Types ... args); f(); f(1); f(2, 1.0); — _end example_]
[Example 3: template <typename... Args> void foo(Args... args) { [...xs=args]{ bar(xs...); };}foo(); foo(1); — _end example_]
A pack is a template parameter pack, a function parameter pack, or an init-capture pack.
The number of elements of a template parameter pack or a function parameter pack is the number of arguments provided for the parameter pack.
The number of elements of an init-capture pack is the number of elements in the pack expansion of its initializer.
A pack expansionconsists of a pattern and an ellipsis, the instantiation of which produces zero or more instantiations of the pattern in a list (described below).
The form of the pattern depends on the context in which the expansion occurs.
Pack expansions can occur in the following contexts:
- In a template parameter pack that is a pack expansion ([temp.param]):
- if the template parameter pack is a parameter-declaration; the pattern is the parameter-declaration without the ellipsis;
- if the template parameter pack is a type-parameter; the pattern is the corresponding type-parameterwithout the ellipsis.
- In a template-argument-list ([temp.arg]); the pattern is a template-argument.
[Example 4: template<class ... Types> void f(Types ... rest);template<class ... Types> void g(Types ... rest) { f(&rest ...); } — _end example_]
For the purpose of determining whether a pack satisfies a rule regarding entities other than packs, the pack is considered to be the entity that would result from an instantiation of the pattern in which it appears.
A pack whose name appears within the pattern of a pack expansion is expanded by that pack expansion.
An appearance of the name of a pack is only expanded by the innermost enclosing pack expansion.
The pattern of a pack expansion shall name one or more packs that are not expanded by a nested pack expansion; such packs are calledunexpanded packs in the pattern.
All of the packs expanded by a pack expansion shall have the same number of arguments specified.
An appearance of a name of a pack that is not expanded is ill-formed.
[Example 5: template<typename...> struct Tuple {};template<typename T1, typename T2> struct Pair {};template<class ... Args1> struct zip { template<class ... Args2> struct with { typedef Tuple<Pair<Args1, Args2> ... > type;};};typedef zip<short, int>::with<unsigned short, unsigned>::type T1;typedef zip<short>::with<unsigned short, unsigned>::type T2;template<class ... Args> void g(Args ... args) { f(const_cast<const Args*>(&args)...); f(5 ...); f(args); f(h(args ...) + args ...); } — _end example_]
The instantiation of a pack expansion that is neither a sizeof... expression nor a fold-expressionproduces a list of elements , whereN is the number of elements in the pack expansion parameters.
Each is generated by instantiating the pattern and replacing each pack expansion parameter with its element.
Such an element, in the context of the instantiation, is interpreted as follows:
- if the pack is a template parameter pack, the element is a template parameter ([temp.param]) of the corresponding kind (type or non-type) designating the corresponding type or value template argument;
- if the pack is a function parameter pack, the element is anid-expressiondesignating the function parameter that resulted from instantiation of the function parameter pack declaration; otherwise
- if the pack is an init-capture pack, the element is an id-expressiondesignating the variable introduced by the init-capturethat resulted from instantiation of the init-capture pack.
All of the become items in the enclosing list.
When N is zero, the instantiation of the expansion produces an empty list.
Such an instantiation does not alter the syntactic interpretation of the enclosing construct, even in cases where omitting the list entirely would otherwise be ill-formed or would result in an ambiguity in the grammar.
[Example 6: template<class... T> struct X : T... { };template<class... T> void f(T... values) { X<T...> x(values...);} template void f<>(); — _end example_]
The instantiation of a sizeof... expression ([expr.sizeof]) produces an integral constant containing the number of elements in the pack it expands.
The instantiation of a fold-expression produces:
- (( op ) op ⋯) op for a unary left fold,
- op (⋯ op ( op ))for a unary right fold,
- (((E op ) op ) op ⋯) op for a binary left fold, and
- op (⋯ op ( op ( op E)))for a binary right fold.
In each case,op is the fold-operator,N is the number of elements in the pack expansion parameters, and each is generated by instantiating the pattern and replacing each pack expansion parameter with its element.
For a binary fold-expression,E is generated by instantiating the cast-expressionthat did not contain an unexpanded pack.
[Example 7: template<typename ...Args> bool all(Args ...args) { return (... && args); } bool b = all(true, true, true, false);
Within the instantiation of all, the returned expression expands to((true && true) && true) && false, which evaluates to false.
— _end example_]
If N is zero for a unary fold-expression, the value of the expression is shown in Table 17; if the operator is not listed in Table 17, the instantiation is ill-formed.
Table 17: Value of folding empty sequences [tab:temp.fold.empty]
| 🔗 | Operator | Value when pack is empty |
|---|---|---|
| 🔗 | && | true |
| 🔗 | | | |
| 🔗 | , | void() |
13.7.5 Friends [temp.friend]
A friend of a class or class template can be a function template or class template, a specialization of a function template or class template, or a non-template function or class.
For a friend function declaration that is not a template declaration:
- if the name of the friend is a qualified or unqualified template-id, the friend declaration refers to a specialization of a function template, otherwise,
- if the name of the friend is a qualified-id and a matching non-template function is found in the specified class or namespace, the friend declaration refers to that function, otherwise,
- if the name of the friend is a qualified-id and a matching function template is found in the specified class or namespace, the friend declaration refers to the deduced specialization of that function template ([temp.deduct.decl]), otherwise,
- the name shall be an unqualified-id that declares (or redeclares) a non-template function.
[Example 1: template<class T> class task;template<class T> task<T>* preempt(task<T>*);template<class T> class task { friend void next_time();friend void process(task<T>*);friend task<T>* preempt<T>(task<T>*);template<class C> friend int func(C);friend class task<int>;template<class P> friend class frd;};
Here, each specialization of thetaskclass template has the functionnext_timeas a friend; becauseprocessdoes not have explicittemplate-arguments, each specialization of thetaskclass template has an appropriately typed functionprocessas a friend, and this friend is not a function template specialization; because the friendpreempthas an explicittemplate-argument T, each specialization of thetaskclass template has the appropriate specialization of the function templatepreemptas a friend; and each specialization of thetaskclass template has all specializations of the function templatefuncas friends.
Similarly, each specialization of thetaskclass template has the class template specializationtask<int>as a friend, and has all specializations of the class templatefrdas friends.
— _end example_]
A friend template may be declared within a class or class template.
A friend function template may be defined within a class or class template, but a friend class template may not be defined in a class or class template.
In these cases, all specializations of the friend class or friend function template are friends of the class or class template granting friendship.
[Example 2: class A { template<class T> friend class B; template<class T> friend void f(T){ } }; — _end example_]
A template friend declaration specifies that all specializations of that template, whether they are implicitly instantiated, partially specialized or explicitly specialized, are friends of the class containing the template friend declaration.
[Example 3: class X { template<class T> friend struct A;class Y { };};template<class T> struct A { X::Y ab; }; template<class T> struct A<T*> { X::Y ab; }; — _end example_]
A template friend declaration may declare a member of a dependent type to be a friend.
The friend declaration shall declare a function or specify a type with an elaborated-type-specifier, in either case with a nested-name-specifierending with a simple-template-id, C, whose template-name names a class template.
The template parameters of the template friend declaration shall be deducible from C ([temp.deduct.type]).
In this case, a member of a specialization S of the class template is a friend of the class granting friendship if deduction of the template parameters of C from S succeeds, and substituting the deduced template arguments into the friend declaration produces a declaration that would be a valid redeclaration of the member of the specialization.
[Example 4: template<class T> struct A { struct B { };void f();struct D { void g();}; T h();template<T U> T i();};template<> struct A<int> { struct B { };int f();struct D { void g();};template<int U> int i();};template<> struct A<float*> { int *h();};class C { template<class T> friend struct A<T>::B; template<class T> friend void A<T>::f(); template<class T> friend void A<T>::D::g(); template<class T> friend int *A<T*>::h(); template<class T> template<T U> friend T A<T>::i(); }; — _end example_]
[Note 1:
A friend declaration can first declare a member of an enclosing namespace scope ([temp.inject]).
— _end note_]
A friend template shall not be declared in a local class.
Friend declarations shall not declare partial specializations.
[Example 5: template<class T> class A { };class X { template<class T> friend class A<T*>; }; — _end example_]
When a friend declaration refers to a specialization of a function template, the function parameter declarations shall not include default arguments, nor shall the inline, constexpr, or consteval specifiers be used in such a declaration.
A non-template friend declaration with a requires-clauseshall be a definition.
A friend function template with a constraint that depends on a template parameter from an enclosing template shall be a definition.
Such a constrained friend function or function template declaration does not declare the same function or function template as a declaration in any other scope.
13.7.6 Class template partial specializations [temp.class.spec]
13.7.6.1 General [temp.class.spec.general]
Aprimary class templatedeclaration is one in which the class template name is an identifier.
A template declaration in which the class template name is asimple-template-idis apartial specializationof the class template named in thesimple-template-id.
A partial specialization of a class template provides an alternative definition of the template that is used instead of the primary definition when the arguments in a specialization match those given in the partial specialization ([temp.class.spec.match]).
The primary template shall be declared before any specializations of that template.
A partial specialization shall be declared before the first use of a class template specialization that would make use of the partial specialization as the result of an implicit or explicit instantiation in every translation unit in which such a use occurs; no diagnostic is required.
Each class template partial specialization is a distinct template and definitions shall be provided for the members of a template partial specialization ([temp.class.spec.mfunc]).
[Example 1: template<class T1, class T2, int I> class A { };template<class T, int I> class A<T, T*, I> { };template<class T1, class T2, int I> class A<T1*, T2, I> { };template<class T> class A<int, T*, 5> { };template<class T1, class T2, int I> class A<T1, T2*, I> { };
The first declaration declares the primary (unspecialized) class template.
The second and subsequent declarations declare partial specializations of the primary template.
— _end example_]
A class template partial specialization may be constrained ([temp.pre]).
[Example 2: template<typename T> concept C = true;template<typename T> struct X { };template<typename T> struct X<T*> { }; template<C T> struct X<T> { };
Both partial specializations are more specialized than the primary template.
#1 is more specialized because the deduction of its template arguments from the template argument list of the class template specialization succeeds, while the reverse does not.
#2 is more specialized because the template arguments are equivalent, but the partial specialization is more constrained ([temp.constr.order]).
— _end example_]
The template parameters are specified in the angle bracket enclosed list that immediately follows the keywordtemplate.
For partial specializations, the template argument list is explicitly written immediately following the class template name.
For primary templates, this list is implicitly described by the template parameter list.
Specifically, the order of the template arguments is the sequence in which they appear in the template parameter list.
[Example 3:
The template argument list for the primary template in the example above is<T1, T2, I>.
— _end example_]
[Note 1:
The template argument list cannot be specified in the primary template declaration.
For example,
template<class T1, class T2, int I> class A<T1, T2, I> { }; — _end note_]
A class template partial specialization may be declared in any scope in which the corresponding primary template may be defined ([namespace.memdef], [class.mem], [temp.mem]).
[Example 4: template<class T> struct A { struct C { template<class T2> struct B { };template<class T2> struct B<T2**> { }; };};template<class T> template<class T2> struct A<T>::C::B<T2*> { }; A<short>::C::B<int*> absip; — _end example_]
Partial specialization declarations themselves are not found by name lookup.
Rather, when the primary template name is used, any previously-declared partial specializations of the primary template are also considered.
One consequence is that ausing-declarationwhich refers to a class template does not restrict the set of partial specializations which may be found through theusing-declaration.
[Example 5: namespace N { template<class T1, class T2> class A { }; } using N::A; namespace N { template<class T> class A<T, T*> { }; }A<int,int*> a; — _end example_]
A non-type argument is non-specialized if it is the name of a non-type parameter.
All other non-type arguments are specialized.
Within the argument list of a class template partial specialization, the following restrictions apply:
- The type of a template parameter corresponding to a specialized non-type argument shall not be dependent on a parameter of the specialization.
[Example 6: template <class T, T t> struct C {};template <class T> struct C<T, 1>; template< int X, int (*array_ptr)[X] > class A {};int array[5];template< int X > class A<X,&array> { }; — _end example_] - The specialization shall be more specializedthan the primary template.
- The template parameter list of a specialization shall not contain default template argument values.138
- An argument shall not contain an unexpanded pack.
If an argument is a pack expansion ([temp.variadic]), it shall be the last argument in the template argument list.
The usual access checking rules do not apply to non-dependent names used to specify template arguments of the simple-template-idof the partial specialization.
[Note 2:
The template arguments can be private types or objects that would normally not be accessible.
Dependent names cannot be checked when declaring the partial specialization, but will be checked when substituting into the partial specialization.
— _end note_]
13.7.6.2 Matching of class template partial specializations [temp.class.spec.match]
When a class template is used in a context that requires an instantiation of the class, it is necessary to determine whether the instantiation is to be generated using the primary template or one of the partial specializations.
This is done by matching the template arguments of the class template specialization with the template argument lists of the partial specializations.
- If exactly one matching specialization is found, the instantiation is generated from that specialization.
- If more than one matching specialization is found, the partial order rules are used to determine whether one of the specializations is more specialized than the others.
If none of the specializations is more specialized than all of the other matching specializations, then the use of the class template is ambiguous and the program is ill-formed. - If no matches are found, the instantiation is generated from the primary template.
A partial specialization matches a given actual template argument list if the template arguments of the partial specialization can bededuced from the actual template argument list, and the deduced template arguments satisfy the associated constraintsof the partial specialization, if any.
[Example 1: template<class T1, class T2, int I> class A { }; template<class T, int I> class A<T, T*, I> { }; template<class T1, class T2, int I> class A<T1*, T2, I> { }; template<class T> class A<int, T*, 5> { }; template<class T1, class T2, int I> class A<T1, T2*, I> { }; A<int, int, 1> a1; A<int, int*, 1> a2; A<int, char*, 5> a3; A<int, char*, 1> a4; A<int*, int*, 2> a5; — _end example_]
[Example 2: template<typename T> concept C = requires (T t) { t.f(); };template<typename T> struct S { }; template<C T> struct S<T> { }; struct Arg { void f(); }; S<int> s1; S<Arg> s2; — _end example_]
If the template arguments of a partial specialization cannot be deduced because of the structure of its template-parameter-listand the template-id, the program is ill-formed.
[Example 3: template <int I, int J> struct A {};template <int I> struct A<I+5, I*2> {}; template <int I> struct A<I, I> {}; template <int I, int J, int K> struct B {};template <int I> struct B<I, I*2, 2> {}; — _end example_]
In a type name that refers to a class template specialization, (e.g.,A<int, int, 1>) the argument list shall match the template parameter list of the primary template.
The template arguments of a specialization are deduced from the arguments of the primary template.
13.7.6.3 Partial ordering of class template specializations [temp.class.order]
For two class template partial specializations, the first is more specialized than the second if, given the following rewrite to two function templates, the first function template is more specialized than the second according to the ordering rules for function templates:
- Each of the two function templates has the same template parameters and associated constraintsas the corresponding partial specialization.
- Each function template has a single function parameter whose type is a class template specialization where the template arguments are the corresponding template parameters from the function template for each template argument in the template-argument-listof the simple-template-idof the partial specialization.
[Example 1: template<int I, int J, class T> class X { };template<int I, int J> class X<I, J, int> { }; template<int I> class X<I, I, int> { }; template<int I0, int J0> void f(X<I0, J0, int>); template<int I0> void f(X<I0, I0, int>); template <auto v> class Y { };template <auto* p> class Y<p> { }; template <auto** pp> class Y<pp> { }; template <auto* p0> void g(Y<p0>); template <auto** pp0> void g(Y<pp0>);
According to the ordering rules for function templates, the function template_B_is more specialized than the function template_A_and the function template_D_is more specialized than the function template_C_.
Therefore, the partial specialization #2 is more specialized than the partial specialization #1 and the partial specialization #4 is more specialized than the partial specialization #3.
— _end example_]
[Example 2: template<typename T> concept C = requires (T t) { t.f(); };template<typename T> concept D = C<T> && requires (T t) { t.f(); };template<typename T> class S { };template<C T> class S<T> { }; template<D T> class S<T> { }; template<C T> void f(S<T>); template<D T> void f(S<T>);
The partial specialization #2 is more specialized than #1 because B is more specialized than A.
— _end example_]
13.7.6.4 Members of class template specializations [temp.class.spec.mfunc]
The template parameter list of a member of a class template partial specialization shall match the template parameter list of the class template partial specialization.
The template argument list of a member of a class template partial specialization shall match the template argument list of the class template partial specialization.
A class template partial specialization is a distinct template.
The members of the class template partial specialization are unrelated to the members of the primary template.
Class template partial specialization members that are used in a way that requires a definition shall be defined; the definitions of members of the primary template are never used as definitions for members of a class template partial specialization.
An explicit specialization of a member of a class template partial specialization is declared in the same way as an explicit specialization of the primary template.
[Example 1: template<class T, int I> struct A { void f();};template<class T, int I> void A<T,I>::f() { } template<class T> struct A<T,2> { void f();void g();void h();};template<class T> void A<T,2>::g() { } template<> void A<char,2>::h() { } int main() { A<char,0> a0; A<char,2> a2; a0.f(); a2.g(); a2.h(); a2.f(); } — _end example_]
If a member template of a class template is partially specialized, the member template partial specializations are member templates of the enclosing class template; if the enclosing class template is instantiated ([temp.inst], [temp.explicit]), a declaration for every member template partial specialization is also instantiated as part of creating the members of the class template specialization.
If the primary member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the partial specializations of the member template are ignored for this specialization of the enclosing class template.
If a partial specialization of the member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the primary member template and its other partial specializations are still considered for this specialization of the enclosing class template.
[Example 2: template<class T> struct A { template<class T2> struct B {}; template<class T2> struct B<T2*> {}; };template<> template<class T2> struct A<short>::B {}; A<char>::B<int*> abcip; A<short>::B<int*> absip; A<char>::B<int> abci; — _end example_]
13.7.7 Function templates [temp.fct]
13.7.7.1 General [temp.fct.general]
A function template defines an unbounded set of related functions.
[Example 1:
A family of sort functions might be declared like this:template<class T> class Array { };template<class T> void sort(Array<T>&);
— _end example_]
A function template can be overloaded with other function templates and with non-template functions ([dcl.fct]).
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.139
13.7.7.2 Function template overloading [temp.over.link]
It is possible to overload function templates so that two different function template specializations have the same type.
[Example 1:
template<class T> void f(T*);void g(int* p) { f(p); }
template<class T> void f(T);void h(int* p) { f(p); }
— _end example_]
The signature of a function template is defined in [intro.defs].
The names of the template parameters are significant only for establishing the relationship between the template parameters and the rest of the signature.
[Note 1:
Two distinct function templates can have identical function return types and function parameter lists, even if overload resolution alone cannot distinguish them.
template<class T> void f();template<int I> void f(); — _end note_]
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.
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.
[Example 2: template <int I, int J> A<I+J> f(A<I>, A<J>); template <int K, int L> A<K+L> f(A<K>, A<L>); template <int I, int J> A<I-J> f(A<I>, A<J>); — _end example_]
[Note 2:
Most expressions that use template parameters use non-type template parameters, but it is possible for an expression to reference a type parameter.
For example, a template type parameter can be used in thesizeof operator.
— _end note_]
Two expressions involving template parameters are consideredequivalentif two function definitions containing the expressions would satisfy the one-definition rule, 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.
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 may differ as long as the two template-ids are the same ([temp.type]).
[Note 3:
For instance, A<42> and A<40+2> name the same type.
— _end note_]
[Note 4:
The intent is to avoid lambda-expressions appearing in the signature of a function template with external linkage.
— _end note_]
For determining whether two dependent names ([temp.dep]) are equivalent, only the name itself is considered, not the result of name lookup in the context of the template.
If multiple declarations of the same function template differ in the result of this name lookup, the result for the first declaration is used.
[Example 3: template <int I, int J> void f(A<I+J>); template <int K, int L> void f(A<K+L>); template <class T> decltype(g(T())) h();int g(int);template <class T> decltype(g(T())) h() { return g(T()); } int i = h<int>(); template <int N> void foo(const char (*s)[([]{}, N)]);template <int N> void foo(const char (*s)[([]{}, N)]);template <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 arefunctionally equivalentif, for any given set of template arguments, the evaluation of the expression results in the same value.
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.
[Note 5:
For instance, one could have redundant parentheses.
— _end note_]
Two template-heads areequivalent if their template-parameter-lists have the same length, corresponding template-parameters are equivalent and are both declared with type-constraints that are equivalent if either template-parameteris declared with a type-constraint, and if either template-head has a requires-clause, they both haverequires-clauses and the correspondingconstraint-expressions are equivalent.
Two template-parameters areequivalentunder the following conditions:
- they declare template parameters of the same kind,
- if either declares a template parameter pack, they both do,
- if they declare non-type template parameters, they have equivalent types ignoring the use of type-constraints for placeholder types, and
- if they declare template template parameters, their template parameters are equivalent.
When determining whether types or type-constraint_s_are equivalent, the rules above are used to compare expressions involving template parameters.
Two template-heads arefunctionally equivalentif they accept and are satisfied by ([temp.constr.constr]) the same set of template argument lists.
Two function templates areequivalentif they are declared in the same scope, have the same name, have equivalent template-heads, and have return types, parameter lists, and trailing requires-clauses (if any) that are equivalent using the rules described above to compare expressions involving template parameters.
Two function templates arefunctionally equivalentif they are declared in the same scope, have the same name, accept and are satisfied by the same set of template argument lists, and have return types and parameter lists that are functionally equivalent using the rules described above to compare expressions involving template parameters.
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.
[Note 6:
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.
For example, the last two declarations are functionally equivalent and would cause a program to be ill-formed: template <int I> void f(A<I>, A<I+10>);template <int I> void f(A<I>, A<I+10>);template <int I> void f(A<I>, A<I+10>);template <int I> void f(A<I>, A<I+11>);template <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 Partial ordering of function templates [temp.func.order]
If a function template is overloaded, the use of a function template specialization can be ambiguous because template argument deduction ([temp.deduct]) may associate the function template specialization with more than one function template declaration.
Partial orderingof overloaded function template declarations is used in the following contexts to select the function template to which a function template specialization refers:
- during overload resolution for a call to a function template specialization ([over.match.best]);
- when the address of a function template specialization is taken;
- when a placement operator delete that is a function template specialization is selected to match a placement operator new ([basic.stc.dynamic.deallocation], [expr.new]);
- when a friend function declaration, anexplicit instantiation or an explicit specialization refers to a function template specialization.
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.
The deduction process determines whether one of the templates is more specialized than the other.
If so, the more specialized template is the one chosen by the partial ordering process.
If both deductions succeed, the partial ordering selects the more constrained template (if one exists) as determined below.
To produce the transformed template, for each type, non-type, or template template parameter (includingtemplate parameter packsthereof) synthesize a unique type, value, or class template respectively and substitute it for each occurrence of that parameter in the function type of the template.
[Note 1:
The type replacing the placeholder in the type of the value synthesized for a non-type template parameter is also a unique synthesized type.
— _end note_]
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.
If exactly one of the function templates was considered by overload resolution via a rewritten candidate ([over.match.oper]) with a reversed order of parameters, then the order of the function parameters in its transformed template is reversed.
For a function template M with cv-qualifiers cvthat is a member of a class A:
- The type X(M) is “rvalue reference to cv A” if the optional ref-qualifier ofM is && or if M has no ref-qualifier 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.
- Otherwise, X(M) is “lvalue reference to cv A”.
[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.
— _end note_]
[Example 1: struct A { };template<class T> struct B { template<class R> int operator*(R&); };template<class T, class R> int operator*(T&, R&); int main() { A a; B<A> b; b * a; } — _end example_]
Using the transformed function template's function type, perform type deduction against the other template as described in [temp.deduct.partial].
[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); float x; g(x); A<int> z; h(z); const A<int> z2; h(z2); } — _end example_]
[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).
[Example 3: template<class T> void f(T); template<class T> void f(T*, int=1); template<class T> void g(T); template<class T> void g(T*, ...); int main() { int* ip; f(ip); g(ip); } — _end example_]
[Example 4: template<class T, class U> struct A { };template<class T, class U> void f(U, A<U, T>* p = 0); template< class U> void f(U, A<U, U>* p = 0); template<class T > void g(T, T = T()); template<class T, class... U> void g(T, U ...); void h() { f<int>(42, (A<int, int>*)0); f<int>(42); g(42); } — _end example_]
[Example 5: template<class T, class... U> void f(T, U...); template<class T > void f(T); template<class T, class... U> void g(T*, U...); template<class T > void g(T); void h(int i) { f(&i); g(&i); } — _end example_]
— _end note_]
If deduction against the other template succeeds for both transformed templates, constraints can be considered as follows:
- If their template-parameter-lists(possibly including template-parameter_s_invented for an abbreviated function template ([dcl.fct])) or function parameter lists differ in length, neither template is more specialized than the other.
- Otherwise:
- If exactly one of the templates was considered by overload resolution via a rewritten candidate with reversed order of parameters:
* If, for either template, some of the template parameters are not deducible from their function parameters, neither template is more specialized than the other.
* If there is either no reordering or more than one reordering of the associated template-parameter-listsuch that
* the corresponding template-parameter_s_of the template-parameter-lists are equivalent and
* the function parameters that positionally correspond between the two templates are of the same type,
neither template is more specialized than the other. - Otherwise, if the corresponding template-parameter_s_of the template-parameter-list_s_are not equivalent ([temp.over.link]) 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.
- If exactly one of the templates was considered by overload resolution via a rewritten candidate with reversed order of parameters:
- 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.
- Otherwise, if one template is more constrained than the other ([temp.constr.order]), the more constrained template is more specialized than the other.
- Otherwise, neither template is more specialized than the other.
[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); } 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; } — _end example_]
13.7.8 Alias templates [temp.alias]
An alias template is a name for a family of types.
The name of the alias template is a template-name.
When a template-id refers to the specialization of an alias template, it is equivalent to the associated type obtained by substitution of its template-arguments for thetemplate-parameters in the defining-type-id of the alias template.
[Note 1:
An alias template name is never deduced.
— _end note_]
[Example 1: template<class T> struct Alloc { };template<class T> using Vec = vector<T, Alloc<T>>; Vec<int> v; template<class T> void process(Vec<T>& v) { } template<class T> void process(vector<T, Alloc<T>>& w) { } template<template<class> class TT> void f(TT<int>); f(v); template<template<class,class> class TT> void g(TT<int, Alloc<int>>); g(v); — _end example_]
However, if the template-id is dependent, subsequent template argument substitution still applies to the template-id.
[Example 2: template<typename...> using void_t = void;template<typename T> void_t<typename T::foo> f(); f<int>(); — _end example_]
The defining-type-id in an alias template declaration shall not refer to the alias template being declared.
The type produced by an alias template specialization shall not directly or indirectly make use of that specialization.
[Example 3: template <class T> struct A;template <class T> using B = typename A<T>::U;template <class T> struct A { typedef B<T> U;}; B<short> b; — _end example_]
The type of a lambda-expressionappearing in an alias template declaration is different between instantiations of that template, even when the lambda-expression is not dependent.
[Example 4: template <class T> using A = decltype([] { }); — _end example_]
13.7.9 Concept definitions [temp.concept]
A concept is a template that defines constraints on its template arguments.
A concept-definitiondeclares a concept.
Its identifier becomes a concept-namereferring to that concept within its scope.
[Example 1: template<typename T> concept C = requires(T x) { { x == x } -> std::convertible_to<bool>;};template<typename T> requires C<T>T f1(T x) { return x; } template<C T>T f2(T x) { return x; } — _end example_]
A concept shall not have associated constraints.
A concept is not instantiated ([temp.spec]).
[Note 1:
A concept-id ([temp.names]) is evaluated as an expression.
A concept cannot be explicitly instantiated ([temp.explicit]), explicitly specialized ([temp.expl.spec]), or partially specialized.
— _end note_]
The first declared template parameter of a concept definition is itsprototype parameter.
A type conceptis a concept whose prototype parameter is a type template-parameter.
13.8 Name resolution [temp.res]
13.8.1 General [temp.res.general]
Three kinds of names can be used within a template definition:
- The name of the template itself, and names declared within the template itself.
- Names dependent on atemplate-parameter ([temp.dep]).
- Names from scopes which are visible within the template definition.
A name used in a template declaration or definition and that is dependent on atemplate-parameteris assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keywordtypename.
[Example 1: class X;template<class T> class Y { class Z; void f() { X* a1; T* a2; Y* a3; Z* a4; typedef typename T::A TA; TA* a5; typename T::A* a6; T::A* a7; B* a8; } }; — _end example_]
[Example 2: struct A { struct X { };int X;};struct B { struct X { };};template<class T> void f(T t) { typename T::X x;} void foo() { A a; B b; f(b); f(a); } — _end example_]
[Note 1:
Thetypenamekeyword is not permitted by the syntax of these constructs.
— _end note_]
A qualified-idis assumed to name a type if
- it is a qualified name in a type-id-only context (see below), or
- it is a decl-specifier of the decl-specifier-seq of a
- simple-declaration or a function-definition in namespace scope,
- member-declaration,
- parameter-declaration in a member-declaration140, unless that parameter-declaration appears in a default argument,
- parameter-declaration in a declaratorof a function or function template declaration whose declarator-id is qualified, unless that parameter-declarationappears in a default argument,
- parameter-declaration in a lambda-declaratoror requirement-parameter-list, unless that parameter-declaration appears in a default argument, or
- parameter-declaration of a (non-type) template-parameter.
A qualified name is said to be in a type-id-only contextif it appears in atype-id,new-type-id, ordefining-type-idand the smallest enclosingtype-id,new-type-id, ordefining-type-idis anew-type-id,defining-type-id,trailing-return-type, default argument of a type-parameter of a template, ortype-id of astatic_cast,const_cast,reinterpret_cast, ordynamic_cast.
[Example 3: template<class T> T::R f(); template<class T> void f(T::R); template<class T> struct S { using Ptr = PtrTraits<T>::Ptr; T::R f(T::P p) { return static_cast<T::R>(p); } auto g() -> S<T*>::Ptr; };template<typename T> void f() { void (*pf)(T::X); void g(T::X); } — _end example_]
A qualified-id that refers to a member of an unknown specialization, that is not prefixed by typename, and that is not otherwise assumed to name a type (see above) denotes a non-type.
[Example 4: template <class T> void f(int i) { T::x * i; } struct Foo { typedef int x;};struct Bar { static int const x = 5;};int main() { f<Bar>(1); f<Foo>(1); } — _end example_]
Within the definition of a class template or within the definition of a member of a class template following the declarator-id, the keywordtypenameis not required when referring to a member of the current instantiation ([temp.dep.type]).
[Example 5: template<class T> struct A { typedef int B; B b; }; — _end example_]
The validity of a template may be checked prior to any instantiation.
[Note 2:
Knowing which names are type names allows the syntax of every template to be checked in this way.
— _end note_]
The program is ill-formed, no diagnostic required, if:
- no valid specialization can be generated for a template or a substatement of a constexpr if statement within a template and the template is not instantiated, or
- no substitution of template arguments into a type-constraint or requires-clausewould result in a valid expression, or
- every valid specialization of a variadic template requires an empty template parameter pack, or
- a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, or
- the interpretation of such a construct in the hypothetical instantiation is different from the interpretation of the corresponding construct in any actual instantiation of the template.
[Note 3:
This can happen in situations including the following:- a type used in a non-dependent name is incomplete at the point at which a template is defined but is complete at the point at which an instantiation is performed, or
- lookup for a name in the template definition found a using-declaration, but the lookup in the corresponding scope in the instantiation does not find any declarations because the using-declarationwas a pack expansion and the corresponding pack is empty, or
- an instantiation uses a default argument or default template argument that had not been defined at the point at which the template was defined, or
- constant expression evaluation within the template instantiation uses
* the value of a const object of integral or unscoped enumeration type or
* the value of a constexpr object or
* the value of a reference or
* the definition of a constexpr function,
and that entity was not defined when the template was defined, or
- a class template specialization or variable template specialization that is specified by a non-dependent simple-template-id is used by the template, and either it is instantiated from a partial specialization that was not defined when the template was defined or it names an explicit specialization that was not declared when the template was defined.
— _end note_]
Otherwise, no diagnostic shall be issued for a template for which a valid specialization can be generated.
[Note 4:
If a template is instantiated, errors will be diagnosed according to the other rules in this document.
Exactly when these errors are diagnosed is a quality of implementation issue.
— _end note_]
[Example 6: int j;template<class T> class X { void f(T t, int i, char* p) { t = i; p = i; p = j; } void g(T t) { +; } };template<class... T> struct A { void operator++(int, T... t); };template<class... T> union X : T... { }; template<class... T> struct A : T..., T... { }; — _end example_]
When looking for the declaration of a name used in a template definition, the usual lookup rules ([basic.lookup.unqual], [basic.lookup.argdep]) are used for non-dependent names.
The lookup of names dependent on the template parameters is postponed until the actual template argument is known ([temp.dep]).
[Example 7: #include <iostream> using namespace std;template<class T> class Set { T* p;int cnt;public: Set(); Set<T>(const Set<T>&);void printall() { for (int i = 0; i<cnt; i++) cout << p[i] << '\n';} };
In the example,iis the local variableideclared inprintall,cntis the membercntdeclared inSet, andcoutis the standard output stream declared iniostream.
However, not every declaration can be found this way; the resolution of some names is postponed until the actualtemplate-argument_s_are known.
For example, even though the nameoperator<<is known within the definition ofprintall()and a declaration of it can be found in, the actual declaration ofoperator<<needed to printp[i]cannot be known until it is known what typeTis ([temp.dep]).
— _end example_]
If a name does not depend on atemplate-parameter(as defined in [temp.dep]), a declaration (or set of declarations) for that name shall be in scope at the point where the name appears in the template definition; the name is bound to the declaration (or declarations) found at that point and this binding is not affected by declarations that are visible at the point of instantiation.
[Example 8: void f(char);template<class T> void g(T t) { f(1); f(T(1)); f(t); dd++; } enum E { e };void f(E);double dd;void h() { g(e); g('a'); } — _end example_]
[Note 5:
For purposes of name lookup, default arguments andnoexcept-specifiers of function templates and default arguments and noexcept-specifiers of member functions of class templates are considered definitions ([temp.decls]).
— _end note_]
13.8.2 Locally declared names [temp.local]
Like normal (non-template) classes, class templates have an injected-class-name ([class.pre]).
The injected-class-name can be used as a template-name or a type-name.
When it is used with atemplate-argument-list, as a template-argument for a template template-parameter, or as the final identifier in the elaborated-type-specifier of a friend class template declaration, it is a template-name that refers to the class template itself.
Otherwise, it is a type-nameequivalent to the template-namefollowed by the template-parameters of the class template enclosed in <>.
Within the scope of a class template specialization or partial specialization, when the injected-class-name is used as a type-name, it is equivalent to the template-name followed by thetemplate-argument_s_of the class template specialization or partial specialization enclosed in<>.
[Example 1: template<template<class> class T> class A { };template<class T> class Y;template<> class Y<int> { Y* p; Y<char>* q; A<Y>* a; class B { template<class> friend class Y; };}; — _end example_]
The injected-class-name of a class template or class template specialization can be used as either a template-name or a type-namewherever it is in scope.
[Example 2: template <class T> struct Base { Base* p;};template <class T> struct Derived: public Base<T> { typename Derived::Base* p; };template<class T, template<class> class U = T::template Base> struct Third { }; Third<Derived<int> > t; — _end example_]
A lookup that finds an injected-class-name ([class.member.lookup]) can result in an ambiguity in certain cases (for example, if it is found in more than one base class).
If all of the injected-class-names that are found refer to specializations of the same class template, and if the name is used as a template-name, the reference refers to the class template itself and not a specialization thereof, and is not ambiguous.
[Example 3: template <class T> struct Base { };template <class T> struct Derived: Base<int>, Base<char> { typename Derived::Base b; typename Derived::Base<double> d; }; — _end example_]
When the normal name of the template (i.e., the name from the enclosing scope, not the injected-class-name) is used, it always refers to the class template itself and not a specialization of the template.
[Example 4: template<class T> class X { X* p; X<T>* p2; X<int>* p3;::X* p4; }; — _end example_]
The name of atemplate-parametershall not be redeclared within its scope (including nested scopes).
Atemplate-parametershall not have the same name as the template name.
[Example 5: template<class T, int i> class Y { int T; void f() { char T; } };template<class X> class X; — _end example_]
In the definition of a member of a class template that appears outside of the class template definition, the name of a member of the class template hides the name of atemplate-parameterof any enclosing class templates (but not a template-parameter of the member if the member is a class or function template).
[Example 6: template<class T> struct A { struct B { };typedef void C;void f();template<class U> void g(U);};template<class B> void A<B>::f() { B b; } template<class B> template<class C> void A<B>::g(C) { B b; C c; } — _end example_]
In the definition of a member of a class template that appears outside of the namespace containing the class template definition, the name of atemplate-parameterhides the name of a member of this namespace.
[Example 7: namespace N { class C { };template<class T> class B { void f(T);};} template<class C> void N::B<C>::f(C) { C b; } — _end example_]
In the definition of a class template or in the definition of a member of such a template that appears outside of the template definition, for each non-dependent base class ([temp.dep.type]), if the name of the base class or the name of a member of the base class is the same as the name of atemplate-parameter, the base class name or member name hides thetemplate-parametername.
[Example 8: struct A { struct B { };int a;int Y;};template<class B, class a> struct X : A { B b; a b; }; — _end example_]
13.8.3 Dependent names [temp.dep]
13.8.3.1 General [temp.dep.general]
Inside a template, some constructs have semantics which may differ from one instantiation to another.
Such a constructdependson the template parameters.
In particular, types and expressions may depend on the type and/or value of template parameters (as determined by the template arguments) and this determines the context for name lookup for certain names.
An expression may betype-dependent(that is, its type may depend on a template parameter) orvalue-dependent(that is, its value when evaluated as a constant expression ([expr.const]) may depend on a template parameter) as described below.
If an operand of an operator is a type-dependent expression, the operator also denotes a dependent name.
[Note 1:
Such names are unbound and are looked up at the point of the template instantiation ([temp.point]) in both the context of the template definition and the context of the point of instantiation ([temp.dep.candidate]).
— _end note_]
[Example 1: template<class T> struct X : B<T> { typename T::A* pa;void f(B<T>* pb) { static int i = B<T>::i; pb->j++;} };
The base class nameB<T>, the type nameT::A, the namesB<T>::iandpb->jexplicitly depend on thetemplate-parameter.
— _end example_]
In the definition of a class or class template, the scope of a dependent base classis not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member.
[Example 2: typedef double A;template<class T> class B { typedef int A;};template<class T> struct X : B<T> { A a; };
The type nameAin the definition ofX<T>binds to the typedef name defined in the global namespace scope, not to the typedef name defined in the base classB<T>.
— _end example_]
[Example 3: struct A { struct B { };int a;int Y;};int a;template<class T> struct Y : T { struct B { }; B b; void f(int i) { a = i; } Y* p; }; Y<A> ya;
The membersA::B,A::a, andA::Yof the template argumentAdo not affect the binding of names inY<A>.
— _end example_]
13.8.3.2 Dependent types [temp.dep.type]
A name refers to thecurrent instantiationif it is
- in the definition of a class template, a nested class of a class template, a member of a class template, or a member of a nested class of a class template, the injected-class-name of the class template or nested class,
- in the definition of a primary class template or a member of a primary class template, the name of the class template followed by the template argument list of the primary template (as described below) enclosed in<> (or an equivalent template alias specialization),
- in the definition of a nested class of a class template, the name of the nested class referenced as a member of the current instantiation, or
- in the definition of a partial specialization or a member of a partial specialization, the name of the class template followed by the template argument list of the partial specialization enclosed in<> (or an equivalent template alias specialization).
If the template parameter is a template parameter pack, the template argument is a pack expansion ([temp.variadic]) whose pattern is the name of the template parameter pack.
The template argument list of a primary template is a template argument list in which thetemplate argument has the value of thetemplate parameter of the class template.
If the template parameter is atemplate parameter pack, the template argument is apack expansion whose pattern is the name of the template parameter pack.
A template argument that is equivalent to a template parameter can be used in place of that template parameter in a reference to the current instantiation.
For a template type-parameter, a template argument is equivalent to a template parameter if it denotes the same type.
For a non-type template parameter, a template argument is equivalent to a template parameter if it is an identifier that names a variable that is equivalent to the template parameter.
A variable is equivalent to a template parameter if
- it has the same type as the template parameter (ignoring cv-qualification) and
- its initializer consists of a single identifier that names the template parameter or, recursively, such a variable.
[Note 1:
Using a parenthesized variable name breaks the equivalence.
— _end note_]
[Example 1: template <class T> class A { A* p1; A<T>* p2; A<T*> p3; ::A<T>* p4; class B { B* p1; A<T>::B* p2; typename A<T*>::B* p3; };};template <class T> class A<T*> { A<T*>* p1; A<T>* p2; };template <class T1, class T2, int I> struct B { B<T1, T2, I>* b1; B<T2, T1, I>* b2; typedef T1 my_T1;static const int my_I = I;static const int my_I2 = I+0;static const int my_I3 = my_I;static const long my_I4 = I;static const int my_I5 = (I); B<my_T1, T2, my_I>* b3; B<my_T1, T2, my_I2>* b4; B<my_T1, T2, my_I3>* b5; B<my_T1, T2, my_I4>* b6; B<my_T1, T2, my_I5>* b7; }; — _end example_]
A dependent base class is a base class that is a dependent type and is not the current instantiation.
[Note 2:
A base class can be the current instantiation in the case of a nested class naming an enclosing class as a base.
[Example 2: template<class T> struct A { typedef int M;struct B { typedef void M;struct C;};};template<class T> struct A<T>::B::C : A<T> { M m; }; — _end example_]
— _end note_]
A name is amember of the current instantiationif it is
- An unqualified name that, when looked up, refers to at least one member of a class that is the current instantiation or a non-dependent base class thereof.
[Note 3:
This can only occur when looking up a name in a scope enclosed by the definition of a class template.
— _end note_] - Aqualified-idin which thenested-name-specifierrefers to the current instantiation and that, when looked up, refers to at least one member of a class that is the current instantiation or a non-dependent base class thereof.
[Note 4:
If no such member is found, and the current instantiation has any dependent base classes, then the qualified-id is a member of an unknown specialization; see below.
— _end note_] - An id-expression denoting the member in a class member accessexpression for which the type of the object expression is the current instantiation, and the id-expression, when looked up, refers to at least one member of a class that is the current instantiation or a non-dependent base class thereof.
[Note 5:
If no such member is found, and the current instantiation has any dependent base classes, then the id-expression is a member of an unknown specialization; see below.
— _end note_]
[Example 3: template <class T> class A { static const int i = 5;int n1[i]; int n2[A::i]; int n3[A<T>::i]; int f();};template <class T> int A<T>::f() { return i; } — _end example_]
A name is a dependent member of the current instantiation if it is a member of the current instantiation that, when looked up, refers to at least one member of a class that is the current instantiation.
A name is amember of an unknown specializationif it is
- A qualified-id in which the nested-name-specifierrefers to the current instantiation, the current instantiation has at least one dependent base class, and name lookup of the qualified-id does not find any member of a class that is the current instantiation or a non-dependent base class thereof.
- An id-expression denoting the member in aclass member access expression in which either
- the type of the object expression is the current instantiation, the current instantiation has at least one dependent base class, and name lookup of the id-expression does not find a member of a class that is the current instantiation or a non-dependent base class thereof; or
- the type of the object expression is not the current instantiation and the object expression is type-dependent.
If a qualified-id in which the nested-name-specifierrefers to the current instantiation is not a member of the current instantiation or a member of an unknown specialization, the program is ill-formed even if the template containing the qualified-id is not instantiated; no diagnostic required.
Similarly, if the id-expression in a class member access expression for which the type of the object expression is the current instantiation does not refer to a member of the current instantiation or a member of an unknown specialization, the program is ill-formed even if the template containing the member access expression is not instantiated; no diagnostic required.
[Example 4: template<class T> class A { typedef int type;void f() { A<T>::type i; typename A<T>::other j; } }; — _end example_]
If, for a given set of template arguments, a specialization of a template is instantiated that refers to a member of the current instantiation with aqualified-id or class member access expression, the name in thequalified-id or class member access expression is looked up in the template instantiation context.
If the result of this lookup differs from the result of name lookup in the template definition context, name lookup is ambiguous.
[Example 5: struct A { int m;};struct B { int m;};template<typename T> struct C : A, T { int f() { return this->m; } int g() { return m; } };template int C<B>::f(); template int C<B>::g(); — _end example_]
A type is dependent if it is
- a template parameter,
- a member of an unknown specialization,
- a nested class or enumeration that is a dependent member of the current instantiation,
- a cv-qualified type where the cv-unqualified type is dependent,
- a compound type constructed from any dependent type,
- an array type whose element type is dependent or whose bound (if any) is value-dependent,
- a function type whose exception specification is value-dependent,
- denoted by a simple-template-idin which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent or is a pack expansion,141or
- denoted by decltype(expression), where expression is type-dependent.
[Note 6:
Because typedefs do not introduce new types, but instead simply refer to other types, a name that refers to a typedef that is a member of the current instantiation is dependent only if the type referred to is dependent.
— _end note_]
13.8.3.3 Type-dependent expressions [temp.dep.expr]
Except as described below, an expression is type-dependent if any subexpression is type-dependent.
thisis type-dependent if the class type of the enclosing member function is dependent ([temp.dep.type]).
Anid-expressionis type-dependent if it is not a concept-id and it contains
- anidentifierassociated by name lookup with one or more declarations declared with a dependent type,
- anidentifierassociated by name lookup with a non-type template-parameterdeclared with a type that contains a placeholder type,
- anidentifierassociated by name lookup with a variable declared with a type that contains a placeholder type ([dcl.spec.auto]) where the initializer is type-dependent,
- an identifier associated by name lookup with one or more declarations of member functions of the current instantiation declared with a return type that contains a placeholder type,
- an identifier associated by name lookup with a structured binding declaration whosebrace-or-equal-initializer is type-dependent,
- theidentifier __func__ ([dcl.fct.def.general]), where any enclosing function is a template, a member of a class template, or a generic lambda,
- atemplate-idthat is dependent,
- aconversion-function-idthat specifies a dependent type, or
- anested-name-specifieror aqualified-idthat names a member of an unknown specialization;
or if it names a dependent member of the current instantiation that is a static data member of type “array of unknown bound of T” for some T ([temp.static]).
Expressions of the following forms are never type-dependent (because the type of the expression cannot be dependent):
A class member access expression is type-dependent if the expression refers to a member of the current instantiation and the type of the referenced member is dependent, or the class member access expression refers to a member of an unknown specialization.
[Note 2:
In an expression of the formx.yorxp->ythe type of the expression is usually the type of the memberyof the class ofx(or the class pointed to byxp).
However, ifxorxprefers to a dependent type that is not the current instantiation, the type ofyis always dependent.
Ifxor xprefers to a non-dependent type or refers to the current instantiation, the type ofyis the type of the class member access expression.
— _end note_]
A braced-init-list is type-dependent if any element is type-dependent or is a pack expansion.
13.8.3.4 Value-dependent expressions [temp.dep.constexpr]
Except as described below, an expression used in a context where a constant expression is required is value-dependent if any subexpression is value-dependent.
Anid-expressionis value-dependent if:
- it is a concept-id and any of its arguments are dependent,
- it is type-dependent,
- it is the name of a non-type template parameter,
- it names a static data member that is a dependent member of the current instantiation and is not initialized in a member-declarator,
- it names a static member function that is a dependent member of the current instantiation, or
- it names a potentially-constant variable ([expr.const]) that is initialized with an expression that is value-dependent.
Expressions of the following form are value-dependent:
An expression of the form &qualified-id where thequalified-id names a dependent member of the current instantiation is value-dependent.
An expression of the form &cast-expressionis also value-dependent if evaluating cast-expressionas a core constant expression succeeds and the result of the evaluation refers to a templated entity that is an object with static or thread storage duration or a member function.
13.8.3.5 Dependent template arguments [temp.dep.temp]
A typetemplate-argumentis dependent if the type it specifies is dependent.
A non-typetemplate-argumentis dependent if its type is dependent or the constant expression it specifies is value-dependent.
Furthermore, a non-typetemplate-argumentis dependent if the corresponding non-type template-parameteris of reference or pointer type and the template-argumentdesignates or points to a member of the current instantiation or a member of a dependent type.
A templatetemplate-argumentis dependent if it names atemplate-parameteror is aqualified-idthat refers to a member of an unknown specialization.
13.8.4 Non-dependent names [temp.nondep]
Non-dependent names used in a template definition are found using the usual name lookup and bound at the point they are used.
[Example 1: void g(double);void h();template<class T> class Z { public: void f() { g(1); h++; } };void g(int); — _end example_]
13.8.5 Dependent name resolution [temp.dep.res]
13.8.5.1 Point of instantiation [temp.point]
For a function template specialization, a member function template specialization, or a specialization for a member function or static data member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization and the context from which it is referenced depends on a template parameter, the point of instantiation of the specialization is the point of instantiation of the enclosing specialization.
Otherwise, the point of instantiation for such a specialization immediately follows the namespace scope declaration or definition that refers to the specialization.
If a function template or member function of a class template is called in a way which uses the definition of a default argument of that function template or member function, the point of instantiation of the default argument is the point of instantiation of the function template or member function specialization.
For a noexcept-specifier of a function template specialization or specialization of a member function of a class template, if the noexcept-specifier is implicitly instantiated because it is needed by another template specialization and the context that requires it depends on a template parameter, the point of instantiation of thenoexcept-specifier is the point of instantiation of the specialization that requires it.
Otherwise, the point of instantiation for such a noexcept-specifier immediately follows the namespace scope declaration or definition that requires thenoexcept-specifier.
For a class template specialization, a class member template specialization, or a specialization for a class member of a class template, if the specialization is implicitly instantiated because it is referenced from within another template specialization, if the context from which the specialization is referenced depends on a template parameter, and if the specialization is not instantiated previous to the instantiation of the enclosing template, the point of instantiation is immediately before the point of instantiation of the enclosing template.
Otherwise, the point of instantiation for such a specialization immediately precedes the namespace scope declaration or definition that refers to the specialization.
If a virtual function is implicitly instantiated, its point of instantiation is immediately following the point of instantiation of its enclosing class template specialization.
An explicit instantiation definition is an instantiation point for the specialization or specializations specified by the explicit instantiation.
A specialization for a function template, a member function template, or of a member function or static data member of a class template may have multiple points of instantiations within a translation unit, and in addition to the points of instantiation described above,
- for any such specialization that has a point of instantiation within thedeclaration-seq of thetranslation-unit, prior to the private-module-fragment (if any), the point after the declaration-seqof the translation-unitis also considered a point of instantiation, and
- for any such specialization that has a point of instantiation within the private-module-fragment, the end of the translation unit is also considered a point of instantiation.
A specialization for a class template has at most one point of instantiation within a translation unit.
A specialization for any template may have points of instantiation in multiple translation units.
If two different points of instantiation give a template specialization different meanings according to the one-definition rule, the program is ill-formed, no diagnostic required.
13.8.5.2 Candidate functions [temp.dep.candidate]
[Note 1:
For the part of the lookup using associated namespaces ([basic.lookup.argdep]), function declarations found in the template instantiation context are found by this lookup, as described in [basic.lookup.argdep].
— _end note_]
If the call would be ill-formed or would find a better match had the lookup within the associated namespaces considered all the function declarations with external linkage introduced in those namespaces in all translation units, not just considering those declarations found in the template definition and template instantiation contexts, then the program has undefined behavior.
[Example 1:
Source file "X.h":namespace Q { struct X { };}
Source file "G.h":namespace Q { void g_impl(X, X);}
Module interface unit of M1:module;#include "X.h" #include "G.h" export module M1;export template<typename T> void g(T t) { g_impl(t, Q::X{ }); }
Module interface unit of M2:module;#include "X.h" export module M2;import M1;void h(Q::X x) { g(x); } — _end example_]
[Example 2:
Module interface unit of Std:export module Std;export template<typename Iter> void indirect_swap(Iter lhs, Iter rhs) { swap(*lhs, *rhs); }
Module interface unit of M:export module M;import Std;struct S { };void swap(S&, S&); void f(S* p, S* q) { indirect_swap(p, q); } — _end example_]
[Example 3:
Source file "X.h":struct X { }; X operator+(X, X);
Module interface unit of F:export module F;export template<typename T> void f(T t) { t + t;}
Module interface unit of M:module;#include "X.h" export module M;import F;void g(X x) { f(x); } — _end example_]
[Example 4:
Module interface unit of A:export module A;export template<typename T> void f(T t) { cat(t, t); dog(t, t); }
Module interface unit of B:export module B;import A;export template<typename T, typename U> void g(T t, U u) { f(t);}
Source file "foo.h", not an importable header:struct foo { friend int cat(foo, foo);};int dog(foo, foo);
Module interface unit of C1:module;#include "foo.h" export module C1;import B;export template<typename T> void h(T t) { g(foo{ }, t);}
Translation unit:import C1;void i() { h(0); }
Importable header "bar.h":struct bar { friend int cat(bar, bar);};int dog(bar, bar);
Module interface unit of C2:module;#include "bar.h" export module C2;import B;export template<typename T> void j(T t) { g(bar{ }, t);}
Translation unit:import C2;void k() { j(0); } — _end example_]
13.8.6 Friend names declared within a class template [temp.inject]
Friend classes or functions can be declared within a class template.
When a template is instantiated, the names of its friends are treated as if the specialization had been explicitly declared at its point of instantiation.
As with non-template classes, the names of namespace-scope friend functions of a class template specialization are not visible during an ordinary lookup unless explicitly declared at namespace scope ([class.friend]).
Such names may be found under the rules for associated classes ([basic.lookup.argdep]).142
[Example 1: template<typename T> struct number { number(int);friend number gcd(number x, number y) { return 0; };};void g() { number<double> a(3), b(4); a = gcd(a,b); b = gcd(3,4); } — _end example_]
13.9 Template instantiation and specialization [temp.spec]
13.9.1 General [temp.spec.general]
The act of instantiating a function, a variable, a class, a member of a class template, or a member template is referred to astemplate instantiation.
A function instantiated from a function template is called an instantiated function.
A class instantiated from a class template is called an instantiated class.
A member function, a member class, a member enumeration, or a static data member of a class template instantiated from the member definition of the class template is called, respectively, an instantiated member function, member class, member enumeration, or static data member.
A member function instantiated from a member function template is called an instantiated member function.
A member class instantiated from a member class template is called an instantiated member class.
A variable instantiated from a variable template is called an instantiated variable.
A static data member instantiated from a static data member template is called an instantiated static data member.
An explicit specialization may be declared for a function template, a variable template, a class template, a member of a class template, or a member template.
An explicit specialization declaration is introduced bytemplate<>.
In an explicit specialization declaration for a variable template, a class template, a member of a class template or a class member template, the name of the variable or class that is explicitly specialized shall be asimple-template-id.
In the explicit specialization declaration for a function template or a member function template, the name of the function or member function explicitly specialized may be atemplate-id.
[Example 1: template<class T = int> struct A { static int x;};template<class U> void g(U) { } template<> struct A<double> { }; template<> struct A<> { }; template<> void g(char) { } template<> void g<int>(int) { } template<> int A<char>::x = 0; template<class T = int> struct B { static int x;};template<> int B<>::x = 1; — _end example_]
An instantiated template specialization can be either implicitly instantiated ([temp.inst]) for a given argument list or be explicitly instantiated ([temp.explicit]).
A specialization is a class, variable, function, or class member that is either instantiated ([temp.inst]) from a templated entity or is an explicit specialization ([temp.expl.spec]) of a templated entity.
For a given template and a given set oftemplate-arguments,
- an explicit instantiation definition shall appear at most once in a program,
- an explicit specialization shall be defined at most once in a program, as specified in [basic.def.odr], and
- both an explicit instantiation and a declaration of an explicit specialization shall not appear in a program unless the explicit instantiation follows a declaration of the explicit specialization.
An implementation is not required to diagnose a violation of this rule.
The usual access checking rules do not apply to names in a declaration of an explicit instantiation or explicit specialization, with the exception of names appearing in a function body, default argument, base-clause, member-specification, enumerator-list, or static data member or variable template initializer.
[Note 1:
In particular, the template arguments and names used in the function declarator (including parameter types, return types and exception specifications) can be private types or objects that would normally not be accessible.
— _end note_]
Each class template specialization instantiated from a template has its own copy of any static members.
[Example 2: template<class T> class X { static T s;};template<class T> T X<T>::s = 0; X<int> aa; X<char*> bb;
X<int>has a static membersof typeintandX<char*>has a static membersof typechar*.
— _end example_]
If a function declaration acquired its function type through a dependent type without using the syntactic form of a function declarator, the program is ill-formed.
[Example 3: template<class T> struct A { static T t;};typedef int function(); A<function> a; — _end example_]
13.9.2 Implicit instantiation [temp.inst]
A template specialization E is a declared specializationif there is a reachable explicit instantiation definition ([temp.explicit]) or explicit specialization declaration ([temp.expl.spec]) for E, or if there is a reachable explicit instantiation declaration for E andE is not
- an inline function,
- declared with a type deduced from its initializer or return value ([dcl.spec.auto]),
- a potentially-constant variable ([expr.const]), or
- a specialization of a templated class.
[Note 1:
An implicit instantiation in an importing translation unit cannot use names with internal linkage from an imported translation unit ([basic.link]).
— _end note_]
Unless a class template specialization is a declared specialization, the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program.
[Note 2:
In particular, if the semantics of an expression depend on the member or base class lists of a class template specialization, the class template specialization is implicitly generated.
For instance, deleting a pointer to class type depends on whether or not the class declares a destructor, and a conversion between pointers to class type depends on the inheritance relationship between the two classes involved.
— _end note_]
[Example 1: template<class T> class B { };template<class T> class D : public B<T> { };void f(void*);void f(B<int>*);void g(D<int>* p, D<char>* pp, D<double>* ppp) { f(p); B<char>* q = pp; delete ppp; } — _end example_]
If a class template has been declared, but not defined, at the point of instantiation, the instantiation yields an incomplete class type ([basic.types]).
[Example 2: template<class T> class X; X<char> ch; — _end example_]
[Note 3:
Within a template declaration, a local class or enumeration and the members of a local class are never considered to be entities that can be separately instantiated (this includes their default arguments,noexcept-specifiers, and non-static data member initializers, if any, but not their type-constraints or requires-clauses).
As a result, the dependent names are looked up, the semantic constraints are checked, and any templates used are instantiated as part of the instantiation of the entity within which the local class or enumeration is declared.
— _end note_]
The implicit instantiation of a class template specialization causes
- the implicit instantiation of the declarations, but not of the definitions, of the non-deleted class member functions, member classes, scoped member enumerations, static data members, member templates, and friends; and
- the implicit instantiation of the definitions of deleted member functions, unscoped member enumerations, and member anonymous unions.
The implicit instantiation of a class template specialization does not cause the implicit instantiation of default arguments or noexcept-specifier_s_of the class member functions.
[Example 3: template<class T> struct C { void f() { T x; } void g() = delete;}; C<void> c; template<> void C<int>::g() { } — _end example_]
However, for the purpose of determining whether an instantiated redeclaration is valid according to [basic.def.odr] and [class.mem], a declaration that corresponds to a definition in the template is considered to be a definition.
[Example 4: template<class T, class U> struct Outer { template<class X, class Y> struct Inner;template<class Y> struct Inner<T, Y>; template<class Y> struct Inner<T, Y> { }; template<class Y> struct Inner<U, Y> { }; }; Outer<int, int> outer;
Outer<int, int>::Inner<int, Y> is redeclared at #1b.
(It is not defined but noted as being associated with a definition in Outer<T, U>.)
#2 is also a redeclaration of #1a.
It is noted as associated with a definition, so it is an invalid redeclaration of the same partial specialization.
template<typename T> struct Friendly { template<typename U> friend int f(U) { return sizeof(T); } }; Friendly<char> fc; Friendly<float> ff; — _end example_]
Unless a member of a class template or a member template is a declared specialization, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist or if the existence of the definition of the member affects the semantics of the program; in particular, the initialization (and any associated side effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist.
Unless a function template specialization is a declared specialization, the function template specialization is implicitly instantiated when the specialization is referenced in a context that requires a function definition to exist or if the existence of the definition affects the semantics of the program.
A function whose declaration was instantiated from a friend function definition is implicitly instantiated when it is referenced in a context that requires a function definition to exist or if the existence of the definition affects the semantics of the program.
Unless a call is to a function template explicit specialization or to a member function of an explicitly specialized class template, a default argument for a function template or a member function of a class template is implicitly instantiated when the function is called in a context that requires the value of the default argument.
[Note 4:
An inline function that is the subject of an explicit instantiation declaration is not a declared specialization; the intent is that it still be implicitly instantiated when odr-used ([basic.def.odr]) so that the body can be considered for inlining, but that no out-of-line copy of it be generated in the translation unit.
— _end note_]
[Example 5: template<class T> struct Z { void f();void g();};void h() { Z<int> a; Z<char>* p; Z<double>* q; a.f(); p->g(); }
Nothing in this example requiresclass Z<double>,Z<int>::g(), orZ<char>::f()to be implicitly instantiated.
— _end example_]
Unless a variable template specialization is a declared specialization, the variable template specialization is implicitly instantiated when it is referenced in a context that requires a variable definition to exist or if the existence of the definition affects the semantics of the program.
A default template argument for a variable template is implicitly instantiated when the variable template is referenced in a context that requires the value of the default argument.
The existence of a definition of a variable or function is considered to affect the semantics of the program if the variable or function is needed for constant evaluation by an expression ([expr.const]), even if constant evaluation of the expression is not required or if constant expression evaluation does not use the definition.
[Example 6: template<typename T> constexpr int f() { return T::value; } template<bool B, typename T> void g(decltype(B ? f<T>() : 0));template<bool B, typename T> void g(...);template<bool B, typename T> void h(decltype(int{B ? f<T>() : 0}));template<bool B, typename T> void h(...);void x() { g<false, int>(0); h<false, int>(0); } — _end example_]
If the function selected by overload resolutioncan be determined without instantiating a class template definition, it is unspecified whether that instantiation actually takes place.
[Example 7: template <class T> struct S { operator int();};void f(int);void f(S<int>&);void f(S<float>);void g(S<int>& sr) { f(sr); }; — _end example_]
If a function template or a member function template specialization is used in a way that involves overload resolution, a declaration of the specialization is implicitly instantiated ([temp.over]).
An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, a static data member of a class template, or a substatement of a constexpr if statement ([stmt.if]), unless such instantiation is required.
[Note 5:
The instantiation of a generic lambda does not require instantiation of substatements of a constexpr if statement within its compound-statementunless the call operator template is instantiated.
— _end note_]
It is unspecified whether or not an implementation implicitly instantiates a virtual member function of a class template if the virtual member function would not otherwise be instantiated.
The use of a template specialization in a default argument shall not cause the template to be implicitly instantiated except that a class template may be instantiated where its complete type is needed to determine the correctness of the default argument.
The use of a default argument in a function call causes specializations in the default argument to be implicitly instantiated.
Implicitly instantiated class, function, and variable template specializations are placed in the namespace where the template is defined.
Implicitly instantiated specializations for members of a class template are placed in the namespace where the enclosing class template is defined.
Implicitly instantiated member templates are placed in the namespace where the enclosing class or class template is defined.
[Example 8: namespace N { template<class T> class List { public: T* get();};} template<class K, class V> class Map { public: N::List<V> lt; V get(K);};void g(Map<const char*,int>& m) { int i = m.get("Nicholas");}
A call oflt.get()fromMap<const char*,int>::get()would placeList<int>::get()in the namespaceNrather than in the global namespace.
— _end example_]
If a function templatefis called in a way that requires a default argument to be used, the dependent names are looked up, the semantics constraints are checked, and the instantiation of any template used in the default argument is done as if the default argument had been an initializer used in a function template specialization with the same scope, the same template parameters and the same access as that of the function templatefused at that point, except that the scope in which a closure type is declared ([expr.prim.lambda.closure]) – and therefore its associated namespaces – remain as determined from the context of the definition for the default argument.
This analysis is calleddefault argument instantiation.
The instantiated default argument is then used as the argument off.
Each default argument is instantiated independently.
[Example 9: template<class T> void f(T x, T y = ydef(T()), T z = zdef(T()));class A { }; A zdef(A);void g(A a, A b, A c) { f(a, b, c); f(a, b); f(a); } — _end example_]
The noexcept-specifier of a function template specialization is not instantiated along with the function declaration; it is instantiated when needed ([except.spec]).
If such annoexcept-specifier is needed but has not yet been instantiated, the dependent names are looked up, the semantics constraints are checked, and the instantiation of any template used in thenoexcept-specifier is done as if it were being done as part of instantiating the declaration of the specialization at that point.
[Note 6:
[temp.point] defines the point of instantiation of a template specialization.
— _end note_]
There is an implementation-defined quantity that specifies the limit on the total depth of recursive instantiations ([implimits]), which could involve more than one template.
The result of an infinite recursion in instantiation is undefined.
[Example 10: template<class T> class X { X<T>* p; X<T*> a; }; — _end example_]
The type-constraints and requires-clauseof a template specialization or member function are not instantiated along with the specialization or function itself, even for a member function of a local class; substitution into the atomic constraints formed from them is instead performed as specified in [temp.constr.decl] and [temp.constr.atomic]when determining whether the constraints are satisfied or as specified in [temp.constr.decl] when comparing declarations.
[Note 7:
The satisfaction of constraints is determined during template argument deduction ([temp.deduct]) and overload resolution ([over.match]).
— _end note_]
[Example 11: template<typename T> concept C = sizeof(T) > 2;template<typename T> concept D = C<T> && sizeof(T) > 4;template<typename T> struct S { S() requires C<T> { } S() requires D<T> { } }; S<char> s1; S<char[8]> s2;
When S<char> is instantiated, both constructors are part of the specialization.
Their constraints are not satisfied, and they suppress the implicit declaration of a default constructor forS<char> ([class.default.ctor]), so there is no viable constructor for s1.
— _end example_]
[Example 12: template<typename T> struct S1 { template<typename U> requires false struct Inner1; };template<typename T> struct S2 { template<typename U> requires (sizeof(T[-(int)sizeof(T)]) > 1) struct Inner2; };
The class S1<T>::Inner1 is ill-formed, no diagnostic required, because it has no valid specializations.
S2 is ill-formed, no diagnostic required, since no substitution into the constraints of its Inner2 template would result in a valid expression.
— _end example_]
13.9.3 Explicit instantiation [temp.explicit]
A class, function, variable, or member template specialization can be explicitly instantiated from its template.
A member function, member class or static data member of a class template can be explicitly instantiated from the member definition associated with its class template.
The syntax for explicit instantiation is:
There are two forms of explicit instantiation: an explicit instantiation definition and an explicit instantiation declaration.
An explicit instantiation declaration begins with the extern keyword.
An explicit instantiation of a function template, member function of a class template, or variable template shall not use the inline, constexpr, or consteval specifiers.
If the explicit instantiation is for a function or member function, theunqualified-idin thedeclaratorshall be either atemplate-idor, where all template arguments can be deduced, atemplate-name or operator-function-id.
If the explicit instantiation is for a member function, a member class or a static data member of a class template specialization, the name of the class template specialization in thequalified-idfor the member name shall be a simple-template-id.
If the explicit instantiation is for a variable template specialization, the unqualified-id in the declaratorshall be a simple-template-id.
An explicit instantiation shall appear in an enclosing namespace of its template.
If the name declared in the explicit instantiation is an unqualified name, the explicit instantiation shall appear in the namespace where its template is declared or, if that namespace is inline ([namespace.def]), any namespace from its enclosing namespace set.
[Note 2:
Regarding qualified names in declarators, see [dcl.meaning].
— _end note_]
[Example 1: template<class T> class Array { void mf(); };template class Array<char>;template void Array<int>::mf();template<class T> void sort(Array<T>& v) { } template void sort(Array<char>&); namespace N { template<class T> void f(T&) { } } template void N::f<int>(int&); — _end example_]
A declaration of a function template, a variable template, a member function or static data member of a class template, or a member function template of a class or class template shall precede an explicit instantiation of that entity.
A definition of a class template, a member class of a class template, or a member class template of a class or class template shall precede an explicit instantiation of that entity unless the explicit instantiation is preceded by an explicit specialization of the entity with the same template arguments.
The declaration in an explicit-instantiation and the declaration produced by the corresponding substitution into the templated function, variable, or class are two declarations of the same entity.
[Note 3:
These declarations are required to have matching types as specified in [basic.link], except as specified in [except.spec].
[Example 2: template<typename T> T var = {};template float var<float>; template int var<int[16]>[]; template int *var<int>; template<typename T> auto av = T();template int av<int>; template<typename T> auto f() {} template void f<int>(); — _end example_]
— _end note_]
Despite its syntactic form, the declaration in an explicit-instantiation for a variable is not itself a definition and does not conflict with the definition instantiated by an explicit instantiation definition for that variable.
For a given set of template arguments, if an explicit instantiation of a template appears after a declaration of an explicit specialization for that template, the explicit instantiation has no effect.
Otherwise, for an explicit instantiation definition, the definition of a function template, a variable template, a member function template, or a member function or static data member of a class template shall be present in every translation unit in which it is explicitly instantiated.
An explicit instantiation of a class, function template, or variable template specialization is placed in the namespace in which the template is defined.
An explicit instantiation for a member of a class template is placed in the namespace where the enclosing class template is defined.
An explicit instantiation for a member template is placed in the namespace where the enclosing class or class template is defined.
[Example 3: namespace N { template<class T> class Y { void mf() { } };} template class Y<int>; using N::Y;template class Y<int>; template class N::Y<char*>; template void N::Y<double>::mf(); — _end example_]
A trailingtemplate-argumentcan be left unspecified in an explicit instantiation of a function template specialization or of a member function template specialization provided it can be deduced from the type of a function parameter ([temp.deduct]).
[Example 4: template<class T> class Array { };template<class T> void sort(Array<T>& v) { } template void sort<>(Array<int>&); — _end example_]
[Note 4:
An explicit instantiation of a constrained template is required to satisfy that template's associated constraints ([temp.constr.decl]).
The satisfaction of constraints is determined when forming the template name of an explicit instantiation in which all template arguments are specified ([temp.names]), or, for explicit instantiations of function templates, during template argument deduction ([temp.deduct.decl]) when one or more trailing template arguments are left unspecified.
— _end note_]
An explicit instantiation that names a class template specialization is also an explicit instantiation of the same kind (declaration or definition) of each of its members (not including members inherited from base classes and members that are templates) that has not been previously explicitly specialized in the translation unit containing the explicit instantiation, provided that the associated constraints, if any, of that member are satisfied by the template arguments of the explicit instantiation ([temp.constr.decl], [temp.constr.constr]), except as described below.
[Note 5:
In addition, it will typically be an explicit instantiation of certainimplementation-dependent data about the class.
— _end note_]
An explicit instantiation definition that names a class template specialization explicitly instantiates the class template specialization and is an explicit instantiation definition of only those members that have been defined at the point of instantiation.
An explicit instantiation of a prospective destructor ([class.dtor]) shall name the selected destructor of the class.
If an entity is the subject of both an explicit instantiation declaration and an explicit instantiation definition in the same translation unit, the definition shall follow the declaration.
An entity that is the subject of an explicit instantiation declaration and that is also used in a way that would otherwise cause an implicit instantiationin the translation unit shall be the subject of an explicit instantiation definition somewhere in the program; otherwise the program is ill-formed, no diagnostic required.
[Note 6:
This rule does apply to inline functions even though an explicit instantiation declaration of such an entity has no other normative effect.
This is needed to ensure that if the address of an inline function is taken in a translation unit in which the implementation chose to suppress the out-of-line body, another translation unit will supply the body.
— _end note_]
An explicit instantiation declaration shall not name a specialization of a template with internal linkage.
An explicit instantiation does not constitute a use of a default argument, so default argument instantiation is not done.
[Example 5: char* p = 0;template<class T> T g(T x = &p) { return x; } template int g<int>(int); — _end example_]
13.9.4 Explicit specialization [temp.expl.spec]
An explicit specialization of any of the following:
- function template
- class template
- variable template
- member function of a class template
- static data member of a class template
- member class of a class template
- member enumeration of a class template
- member class template of a class or class template
- member function template of a class or class template
can be declared by a declaration introduced bytemplate<>; that is:
[Example 1: template<class T> class stream;template<> class stream<char> { };template<class T> class Array { };template<class T> void sort(Array<T>& v) { } template<> void sort<char*>(Array<char*>&);
Given these declarations,stream<char>will be used as the definition of streams ofchars; other streams will be handled by class template specializations instantiated from the class template.
Similarly,sort<char*>will be used as the sort function for arguments of typeArray<char*>; otherArraytypes will be sorted by functions generated from the template.
— _end example_]
A declaration of a function template, class template, or variable template being explicitly specialized shall precede the declaration of the explicit specialization.
[Note 1:
A declaration, but not a definition of the template is required.
— _end note_]
The definition of a class or class template shall precede the declaration of an explicit specialization for a member template of the class or class template.
[Example 2: template<> class X<int> { }; template<class T> class X;template<> class X<char*> { }; — _end example_]
A member function, a member function template, a member class, a member enumeration, a member class template, a static data member, or a static data member template of a class template may be explicitly specialized for a class specialization that is implicitly instantiated; in this case, the definition of the class template shall precede the explicit specialization for the member of the class template.
If such an explicit specialization for the member of a class template names an implicitly-declared special member function ([special]), the program is ill-formed.
A member of an explicitly specialized class is not implicitly instantiated from the member declaration of the class template; instead, the member of the class template specialization shall itself be explicitly defined if its definition is required.
In this case, the definition of the class template explicit specialization shall be in scope at the point at which the member is defined.
The definition of an explicitly specialized class is unrelated to the definition of a generated specialization.
That is, its members need not have the same names, types, etc.
as the members of a generated specialization.
Members of an explicitly specialized class template are defined in the same manner as members of normal classes, and not using the template<> syntax.
The same is true when defining a member of an explicitly specialized member class.
However, template<> is used in defining a member of an explicitly specialized member class template that is specialized as a class template.
[Example 3: template<class T> struct A { struct B { };template<class U> struct C { };};template<> struct A<int> { void f(int);};void h() { A<int> a; a.f(16); } void A<int>::f(int) { } template<> struct A<char>::B { void f();};void A<char>::B::f() { } template<> template<class U> struct A<char>::C { void f();};template<> template<class U> void A<char>::C<U>::f() { } template<> struct A<short>::B { void f();};template<> void A<short>::B::f() { } template<> template<class U> struct A<short>::C { void f();};template<class U> void A<short>::C<U>::f() { } — _end example_]
If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.
If the program does not provide a definition for an explicit specialization and either the specialization is used in a way that would cause an implicit instantiation to take place or the member is a virtual member function, the program is ill-formed, no diagnostic required.
An implicit instantiation is never generated for an explicit specialization that is declared but not defined.
[Example 4: class String { };template<class T> class Array { };template<class T> void sort(Array<T>& v) { } void f(Array<String>& v) { sort(v); } template<> void sort<String>(Array<String>& v); template<> void sort<>(Array<char*>& v); template<class T> struct A { enum E : T;enum class S : T;};template<> enum A<int>::E : int { eint }; template<> enum class A<int>::S : int { sint }; template<class T> enum A<T>::E : T { eT };template<class T> enum class A<T>::S : T { sT };template<> enum A<char>::E : char { echar }; template<> enum class A<char>::S : char { schar }; — _end example_]
The placement of explicit specialization declarations for function templates, class templates, variable templates, member functions of class templates, static data members of class templates, member classes of class templates, member enumerations of class templates, member class templates of class templates, member function templates of class templates, static data member templates of class templates, member functions of member templates of class templates, member functions of member templates of non-template classes, static data member templates of non-template classes, member function templates of member classes of class templates, etc., and the placement of partial specialization declarations of class templates, variable templates, member class templates of non-template classes, static data member templates of non-template classes, member class templates of class templates, etc., can affect whether a program is well-formed according to the relative positioning of the explicit specialization declarations and their points of instantiation in the translation unit as specified above and below.
When writing a specialization, be careful about its location; or to make it compile will be such a trial as to kindle its self-immolation.
A template explicit specialization is in the scope of the namespace in which the template was defined.
[Example 5: namespace N { template<class T> class X { };template<class T> class Y { };template<> class X<int> { }; template<> class Y<double>; } template<> class N::Y<double> { }; template<> class N::Y<short> { }; — _end example_]
Asimple-template-idthat names a class template explicit specialization that has been declared but not defined can be used exactly like the names of other incompletely-defined classes ([basic.types]).
[Example 6: template<class T> class X; template<> class X<int>; X<int>* p; X<int> x; — _end example_]
A trailingtemplate-argumentcan be left unspecified in thetemplate-idnaming an explicit function template specialization provided it can be deduced from the function argument type.
[Example 7: template<class T> class Array { };template<class T> void sort(Array<T>& v);template<> void sort(Array<int>&); — _end example_]
[Note 2:
An explicit specialization of a constrained template is required to satisfy that template's associated constraints ([temp.constr.decl]).
The satisfaction of constraints is determined when forming the template name of an explicit specialization in which all template arguments are specified ([temp.names]), or, for explicit specializations of function templates, during template argument deduction ([temp.deduct.decl]) when one or more trailing template arguments are left unspecified.
— _end note_]
A function with the same name as a template and a type that exactly matches that of a template specialization is not an explicit specialization ([temp.fct]).
Whether an explicit specialization of a function or variable template is inline, constexpr, or an immediate function is determined by the explicit specialization and is independent of those properties of the template.
[Example 8: template<class T> void f(T) { } template<class T> inline T g(T) { } template<> inline void f<>(int) { } template<> int g<>(int) { } — _end example_]
An explicit specialization of a static data member of a template or an explicit specialization of a static data member template is a definition if the declaration includes an initializer; otherwise, it is a declaration.
[Note 3:
The definition of a static data member of a template for which default-initialization is desired can use functional cast notation ([expr.type.conv]):template<> X Q<int>::x; template<> X Q<int>::x (); template<> X Q<int>::x = X();
— _end note_]
A member or a member template of a class template may be explicitly specialized for a given implicit instantiation of the class template, even if the member or member template is defined in the class template definition.
An explicit specialization of a member or member template is specified using the syntax for explicit specialization.
[Example 9: template<class T> struct A { void f(T);template<class X1> void g1(T, X1);template<class X2> void g2(T, X2);void h(T) { } };template<> void A<int>::f(int);template<class T> template<class X1> void A<T>::g1(T, X1) { } template<> template<class X1> void A<int>::g1(int, X1);template<> template<> void A<int>::g1(int, char); template<> template<> void A<int>::g2<char>(int, char); template<> void A<int>::h(int) { } — _end example_]
A member or a member template may be nested within many enclosing class templates.
In an explicit specialization for such a member, the member declaration shall be preceded by atemplate<>for each enclosing class template that is explicitly specialized.
[Example 10: template<class T1> class A { template<class T2> class B { void mf();};};template<> template<> class A<int>::B<double>;template<> template<> void A<char>::B<char>::mf(); — _end example_]
In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well.
In such an explicit specialization declaration, the keywordtemplatefollowed by atemplate-parameter-listshall be provided instead of thetemplate<>preceding the explicit specialization declaration of the member.
The types of thetemplate-parameter_s_in thetemplate-parameter-listshall be the same as those specified in the primary template definition.
[Example 11: template <class T1> class A { template<class T2> class B { template<class T3> void mf1(T3);void mf2();};};template <> template <class X> class A<int>::B { template <class T> void mf1(T);};template <> template <> template<class T> void A<int>::B<double>::mf1(T t) { } template <class Y> template <> void A<Y>::B<double>::mf2() { } — _end example_]
A specialization of a member function template, member class template, or static data member template of a non-specialized class template is itself a template.
An explicit specialization declaration shall not be a friend declaration.
Default function arguments shall not be specified in a declaration or a definition for one of the following explicit specializations:
- the explicit specialization of a function template;
- the explicit specialization of a member function template;
- the explicit specialization of a member function of a class template where the class template specialization to which the member function specialization belongs is implicitly instantiated.
[Note 4:
Default function arguments can be specified in the declaration or definition of a member function of a class template specialization that is explicitly specialized.
— _end note_]
13.10 Function template specializations [temp.fct.spec]
13.10.1 General [temp.fct.spec.general]
A function instantiated from a function template is called a function template specialization; so is an explicit specialization of a function template.
Template arguments can be explicitly specified when naming the function template specialization, deduced from the context (e.g., deduced from the function arguments in a call to the function template specialization, see [temp.deduct]), or obtained from default template arguments.
Each function template specialization instantiated from a template has its own copy of any static variable.
[Example 1: template<class T> void f(T* p) { static T s;};void g(int a, char* b) { f(&a); f(&b); }
Heref<int>(int*)has a static variablesof typeintandf<char*>(char**)has a static variablesof typechar*.
— _end example_]
13.10.2 Explicit template argument specification [temp.arg.explicit]
Template arguments can be specified when referring to a function template specialization that is not a specialization of a constructor template by qualifying the function template name with the list oftemplate-argument_s_in the same way astemplate-argument_s_are specified in uses of a class template specialization.
[Example 1:
template<class T> void sort(Array<T>& v);void f(Array<dcomplex>& cv, Array<int>& ci) { sort<dcomplex>(cv); sort<int>(ci); } andtemplate<class U, class V> U convert(V v);void g(double d) { int i = convert<int,double>(d); char c = convert<char,double>(d); }
— _end example_]
Template arguments shall not be specified when referring to a specialization of a constructor template ([class.ctor], [class.qual]).
A template argument list may be specified when referring to a specialization of a function template
- when a function is called,
- when the address of a function is taken, when a function initializes a reference to function, or when a pointer to member function is formed,
- in an explicit specialization,
- in an explicit instantiation, or
- in a friend declaration.
Trailing template arguments that can be deduced or obtained from defaulttemplate-argument_s_may be omitted from the list of explicittemplate-arguments.
A trailing template parameter pack ([temp.variadic]) not otherwise deduced will be deduced as an empty sequence of template arguments.
If all of the template arguments can be deduced, they may all be omitted; in this case, the empty template argument list<>itself may also be omitted.
In contexts where deduction is done and fails, or in contexts where deduction is not done, if a template argument list is specified and it, along with any default template arguments, identifies a single function template specialization, then thetemplate-idis an lvalue for the function template specialization.
[Example 2: template<class X, class Y> X f(Y);template<class X, class Y, class ... Z> X g(Y);void h() { int i = f<int>(5.6); int j = f(5.6); f<void>(f<int, bool>); f<void>(f<int>); int k = g<int>(5.6); f<void>(g<int, bool>); } — _end example_]
[Note 1:
An empty template argument list can be used to indicate that a given use refers to a specialization of a function template even when a non-template function ([dcl.fct]) is visible that would otherwise be used.
For example:template <class T> int f(T); int f(int); int k = f(1); int l = f<>(1);
— _end note_]
Template arguments that are present shall be specified in the declaration order of their correspondingtemplate-parameters.
The template argument list shall not specify moretemplate-argument_s_than there are correspondingtemplate-parameter_s_unless one of the template-parameters is a template parameter pack.
[Example 3: template<class X, class Y, class Z> X f(Y,Z);template<class ... Args> void f2();void g() { f<int,const char*,double>("aa",3.0); f<int,const char*>("aa",3.0); f<int>("aa",3.0); f("aa",3.0); f2<char, short, int, long>(); } — _end example_]
Implicit conversions ([conv]) will be performed on a function argument to convert it to the type of the corresponding function parameter if the parameter type contains notemplate-parameter_s_that participate in template argument deduction.
[Note 2:
Template parameters do not participate in template argument deduction if they are explicitly specified.
For example,
template<class T> void f(T);class Complex { Complex(double);};void g() { f<Complex>(1); } — _end note_]
[Note 3:
Because the explicit template argument list follows the function template name, and because constructor templates ([class.ctor]) are named without using a function name ([class.qual]), there is no way to provide an explicit template argument list for these function templates.
— _end note_]
Template argument deduction can extend the sequence of template arguments corresponding to a template parameter pack, even when the sequence contains explicitly specified template arguments.
[Example 4: template<class ... Types> void f(Types ... values);void g() { f<int*, float*>(0, 0, 0); } — _end example_]
13.10.3 Template argument deduction [temp.deduct]
13.10.3.1 General [temp.deduct.general]
When a function template specialization is referenced, all of the template arguments shall have values.
The values can be explicitly specified or, in some cases, be deduced from the use or obtained from defaulttemplate-arguments.
[Example 1:
void f(Array<dcomplex>& cv, Array<int>& ci) { sort(cv); sort(ci); } andvoid g(double d) { int i = convert<int>(d); int c = convert<char>(d); }
— _end example_]
When an explicit template argument list is specified, if the given template-id is not valid ([temp.names]), type deduction fails.
Otherwise, the specified template argument values are substituted for the corresponding template parameters as specified below.
After this substitution is performed, the function parameter type adjustments described in [dcl.fct] are performed.
[Example 2:
A parameter type of “void (const int, int[5])” becomes “void(*)(int,int*)”.
— _end example_]
[Note 1:
A top-level qualifier in a function parameter declaration does not affect the function type but still affects the type of the function parameter variable within the function.
— _end note_]
[Example 3: template <class T> void f(T t);template <class X> void g(const X x);template <class Z> void h(Z, Z*);int main() { f<int>(1); f<const int>(1); g<int>(1); g<const int>(1); h<const int>(1,0);} — _end example_]
[Note 2:
f<int>(1) and f<const int>(1) call distinct functions even though both of the functions called have the same function type.
— _end note_]
The resulting substituted and adjusted function type is used as the type of the function template for template argument deduction.
If a template argument has not been deduced and its corresponding template parameter has a default argument, the template argument is determined by substituting the template arguments determined for preceding template parameters into the default argument.
If the substitution results in an invalid type, as described above, type deduction fails.
[Example 4: template <class T, class U = double> void f(T t = 0, U u = 0);void g() { f(1, 'c'); f(1); f(); f<int>(); f<int,char>(); } — _end example_]
When all template arguments have been deduced or obtained from default template arguments, all uses of template parameters in the template parameter list of the template and the function type are replaced with the corresponding deduced or default argument values.
If the substitution results in an invalid type, as described above, type deduction fails.
If the function template has associated constraints ([temp.constr.decl]), those constraints are checked for satisfaction ([temp.constr.constr]).
If the constraints are not satisfied, type deduction fails.
At certain points in the template argument deduction process it is necessary to take a function type that makes use of template parameters and replace those template parameters with the corresponding template arguments.
This is done at the beginning of template argument deduction when any explicitly specified template arguments are substituted into the function type, and again at the end of template argument deduction when any template arguments that were deduced or obtained from default arguments are substituted.
The substitution occurs in all types and expressions that are used in the function type and in template parameter declarations.
The expressions include not only constant expressions such as those that appear in array bounds or as nontype template arguments but also general expressions (i.e., non-constant expressions) inside sizeof, decltype, and other contexts that allow non-constant expressions.
The substitution proceeds in lexical order and stops when a condition that causes deduction to fail is encountered.
If substitution into different declarations of the same function template would cause template instantiations to occur in a different order or not at all, the program is ill-formed; no diagnostic required.
[Note 3:
The equivalent substitution in exception specifications is done only when the noexcept-specifier is instantiated, at which point a program is ill-formed if the substitution results in an invalid type or expression.
— _end note_]
[Example 5: template <class T> struct A { using X = typename T::X; };template <class T> typename T::X f(typename A<T>::X);template <class T> void f(...) { } template <class T> auto g(typename A<T>::X) -> typename T::X;template <class T> void g(...) { } template <class T> typename T::X h(typename A<T>::X);template <class T> auto h(typename A<T>::X) -> typename T::X; template <class T> void h(...) { } void x() { f<int>(0); g<int>(0); h<int>(0); } — _end example_]
If a substitution results in an invalid type or expression, type deduction fails.
An invalid type or expression is one that would be ill-formed, with a diagnostic required, if written using the substituted arguments.
[Note 4:
If no diagnostic is required, the program is still ill-formed.
Access checking is done as part of the substitution process.
— _end note_]
Only invalid types and expressions in the immediate context of the function type, its template parameter types, and its explicit-specifiercan result in a deduction failure.
[Note 5:
The substitution into types and expressions can result in effects such as the instantiation of class template specializations and/or function template specializations, the generation of implicitly-defined functions, etc.
Such effects are not in the “immediate context” and can result in the program being ill-formed.
— _end note_]
A lambda-expression appearing in a function type or a template parameter is not considered part of the immediate context for the purposes of template argument deduction.
[Note 6:
The intent is to avoid requiring implementations to deal with substitution failure involving arbitrary statements.
[Example 6: template <class T> auto f(T) -> decltype([]() { T::invalid; } ());void f(...); f(0); template <class T, std::size_t = sizeof([]() { T::invalid; })> void g(T);void g(...); g(0); template <class T> auto h(T) -> decltype([x = T::invalid]() { });void h(...); h(0); template <class T> auto i(T) -> decltype([]() -> typename T::invalid { });void i(...); i(0); template <class T> auto j(T t) -> decltype([](auto x) -> decltype(x.invalid) { } (t)); void j(...); j(0); — _end example_]
— _end note_]
[Example 7: struct X { };struct Y { Y(X){} };template <class T> auto f(T t1, T t2) -> decltype(t1 + t2); X f(Y, Y); X x1, x2; X x3 = f(x1, x2); — _end example_]
[Note 7:
Type deduction can fail for the following reasons:
- Attempting to instantiate a pack expansion containing multiple packs of differing lengths.
- Attempting to create an array with an element type that is void, a function type, or a reference type, or attempting to create an array with a size that is zero or negative.
[Example 8: template <class T> int f(T[5]);int I = f<int>(0);int j = f<void>(0); — _end example_] - Attempting to use a type that is not a class or enumeration type in a qualified name.
[Example 9: template <class T> int f(typename T::B*);int i = f<int>(0); — _end example_] - Attempting to use a type in a nested-name-specifier of aqualified-id when that type does not contain the specified member, or
- the specified member is not a type where a type is required, or
- the specified member is not a template where a template is required, or
- the specified member is not a non-type where a non-type is required.
[Example 10: template <int I> struct X { };template <template <class T> class> struct Z { };template <class T> void f(typename T::Y*){} template <class T> void g(X<T::N>*){} template <class T> void h(Z<T::template TT>*){} struct A {};struct B { int Y; };struct C { typedef int N;};struct D { typedef int TT;};int main() { f<A>(0); f<B>(0); g<C>(0); h<D>(0); } — _end example_]
- Attempting to create a pointer to reference type.
- Attempting to create a reference to void.
- Attempting to create “pointer to member of T” when T is not a class type.
[Example 11: template <class T> int f(int T::*);int i = f<int>(0); — _end example_] - Attempting to give an invalid type to a non-type template parameter.
[Example 12: template <class T, T> struct S {};template <class T> int f(S<T, T()>*);struct X {};int i0 = f<X>(0); — _end example_] - Attempting to perform an invalid conversion in either a template argument expression, or an expression used in the function declaration.
[Example 13: template <class T, T*> int f(int);int i2 = f<int,1>(0); — _end example_] - Attempting to create a function type in which a parameter has a type of void, or in which the return type is a function type or array type.
— _end note_]
[Example 14:
In the following example, assuming a signed charcannot represent the value 1000, a narrowing conversionwould be required to convert the template-argumentof type int to signed char, therefore substitution fails for the second template ([temp.arg.nontype]).
template <int> int f(int);template <signed char> int f(int);int i1 = f<1000>(0); int i2 = f<1>(0); — _end example_]
13.10.3.2 Deducing template arguments from a function call [temp.deduct.call]
Template argument deduction is done by comparing each function template parameter type (call itP) that contains template-parameters that participate in template argument deduction with the type of the corresponding argument of the call (call itA) as described below.
If removing references and cv-qualifiers from P givesor for some and N and the argument is a non-empty initializer list ([dcl.init.list]), then deduction is performed instead for each element of the initializer list independently, taking as separate function template parameter types and the initializer element as the corresponding argument.
In the case, if N is a non-type template parameter,N is deduced from the length of the initializer list.
Otherwise, an initializer list argument causes the parameter to be considered a non-deduced context ([temp.deduct.type]).
[Example 1: template<class T> void f(std::initializer_list<T>); f({1,2,3}); f({1,"asdf"}); template<class T> void g(T); g({1,2,3}); template<class T, int N> void h(T const(&)[N]); h({1,2,3}); template<class T> void j(T const(&)[3]); j({42}); struct Aggr { int i; int j; };template<int N> void k(Aggr const(&)[N]); k({1,2,3}); k({{1},{2},{3}}); template<int M, int N> void m(int const(&)[M][N]); m({{1,2},{3,4}}); template<class T, int N> void n(T const(&)[N], T); n({{1},{2},{3}},Aggr()); template<typename T, int N> void o(T (* const (&)[N])(T)) { } int f1(int);int f4(int);char f4(char); o({ &f1, &f4 }); o({ &f1, static_cast<char(*)(char)>(&f4) }); — _end example_]
For a function parameter pack that occurs at the end of the parameter-declaration-list, deduction is performed for each remaining argument of the call, taking the type Pof the declarator-id of the function parameter pack as the corresponding function template parameter type.
Each deduction deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack.
When a function parameter pack appears in a non-deduced context ([temp.deduct.type]), the type of that pack is never deduced.
[Example 2: template<class ... Types> void f(Types& ...);template<class T1, class ... Types> void g(T1, Types ...);template<class T1, class ... Types> void g1(Types ..., T1);void h(int x, float& y) { const int z = x; f(x, y, z); g(x, y, z); g1(x, y, z); g1<int, int, int>(x, y, z); } — _end example_]
IfPis not a reference type:
- IfAis an array type, the pointer type produced by the array-to-pointer standard conversion is used in place ofAfor type deduction; otherwise,
- IfAis a function type, the pointer type produced by thefunction-to-pointer standard conversion is used in place ofAfor type deduction; otherwise,
- IfAis a cv-qualified type, the top-level cv-qualifiers ofA's type are ignored for type deduction.
IfPis a cv-qualified type, the top-level cv-qualifiers ofP's type are ignored for type deduction.
IfPis a reference type, the type referred to byPis used for type deduction.
[Example 3: template<class T> int f(const T&);int n1 = f(5); const int i = 0;int n2 = f(i); template <class T> int g(volatile T&);int n3 = g(i); — _end example_]
A forwarding referenceis an rvalue reference to a cv-unqualified template parameter that does not represent a template parameter of a class template (during class template argument deduction ([over.match.class.deduct])).
If P is a forwarding reference and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction.
[Example 4: template <class T> int f(T&& heisenreference);template <class T> int g(const T&&);int i;int n1 = f(i); int n2 = f(0); int n3 = g(i); template <class T> struct A { template <class U> A(T&&, U&&, int*); A(T&&, int*); };template <class T> A(T&&, int*) -> A<T>; int *ip; A a{i, 0, ip}; A a0{0, 0, ip}; A a2{i, ip}; — _end example_]
In general, the deduction process attempts to find template argument values that will make the deducedAidentical toA(after the typeAis transformed as described above).
However, there are three cases that allow a difference:
- If the originalPis a reference type, the deducedA(i.e., the type referred to by the reference) can be more cv-qualified than the transformed A.
- IfPis a class andPhas the formsimple-template-id, then the transformed Acan be a derived class D of the deducedA.
Likewise, ifPis a pointer to a class of the formsimple-template-id, the transformed Acan be a pointer to a derived class D pointed to by the deducedA.
However, if there is a class C that is a (direct or indirect) base class of D and derived (directly or indirectly) from a class B and that would be a valid deduced A, the deduced A cannot be B or pointer to B, respectively.
[Example 5: template <typename... T> struct X;template <> struct X<> {};template <typename T, typename... Ts> struct X<T, Ts...> : X<Ts...> {};struct D : X<int> {};struct E : X<>, X<int> {};template <typename... T> int f(const X<T...>&);int x = f(D()); int z = f(E()); — _end example_]
These alternatives are considered only if type deduction would otherwise fail.
If they yield more than one possible deducedA, the type deduction fails.
[Note 1:
If atemplate-parameteris not used in any of the function parameters of a function template, or is used only in a non-deduced context, its correspondingtemplate-argumentcannot be deduced from a function call and thetemplate-argumentmust be explicitly specified.
— _end note_]
WhenPis a function type, function pointer type, or pointer-to-member-function type:
- If the argument is an overload set containing one or more function templates, the parameter is treated as a non-deduced context.
- If the argument is an overload set (not containing function templates), trial argument deduction is attempted using each of the members of the set.
If deduction succeeds for only one of the overload set members, that member is used as the argument value for the deduction.
If deduction succeeds for more than one member of the overload set the parameter is treated as a non-deduced context.
[Example 6: template <class T> int f(T (*p)(T));int g(int);int g(char);int i = f(g); — _end example_]
[Example 7: template <class T> int f(T, T (*p)(T));int g(int);char g(char);int i = f(1, g); — _end example_]
[Example 8: template <class T> int f(T, T (*p)(T));char g(char);template <class T> T g(T);int i = f(1, g); — _end example_]
If deduction succeeds for all parameters that containtemplate-parameters that participate in template argument deduction, and all template arguments are explicitly specified, deduced, or obtained from default template arguments, remaining parameters are then compared with the corresponding arguments.
For each remaining parameterP with a type that was non-dependent before substitution of any explicitly-specified template arguments, if the corresponding argumentA cannot be implicitly converted to P, deduction fails.
[Note 2:
Parameters with dependent types in which no template-parameter_s_participate in template argument deduction, and parameters that became non-dependent due to substitution of explicitly-specified template arguments, will be checked during overload resolution.
— _end note_]
[Example 9: template <class T> struct Z { typedef typename T::x xx;};template <class T> typename Z<T>::xx f(void *, T); template <class T> void f(int, T); struct A {} a;int main() { f(1, a); } — _end example_]
13.10.3.3 Deducing template arguments taking the address of a function template [temp.deduct.funcaddr]
Template arguments can be deduced from the type specified when taking the address of an overloaded function.
If there is a target, the function template's function type and the target type are used as the types ofPandA, and the deduction is done as described in [temp.deduct.type].
Otherwise, deduction is performed with empty sets of types P and A.
A placeholder type in the return type of a function template is a non-deduced context.
If template argument deduction succeeds for such a function, the return type is determined from instantiation of the function body.
13.10.3.4 Deducing conversion function template arguments [temp.deduct.conv]
Template argument deduction is done by comparing the return type of the conversion function template (call itP) with the type that is required as the result of the conversion (call itA; see [dcl.init], [over.match.conv], and [over.match.ref]for the determination of that type) as described in [temp.deduct.type].
If P is a reference type, the type referred to by P is used in place of P for type deduction and for any further references to or transformations ofP in the remainder of this subclause.
IfAis not a reference type:
- IfPis an array type, the pointer type produced by thearray-to-pointer standard conversion is used in place ofPfor type deduction; otherwise,
- IfPis a function type, the pointer type produced by thefunction-to-pointer standard conversion is used in place ofPfor type deduction; otherwise,
- IfPis a cv-qualified type, the top-level cv-qualifiers ofP's type are ignored for type deduction.
IfAis a cv-qualified type, the top-level cv-qualifiers ofA's type are ignored for type deduction.
IfAis a reference type, the type referred to byAis used for type deduction.
In general, the deduction process attempts to find template argument values that will make the deducedAidentical toA.
However, there are four cases that allow a difference:
- If the original A is a reference type,A can be more cv-qualified than the deduced A(i.e., the type referred to by the reference).
- If the original A is a function pointer type,A can be “pointer to function” even if the deduced A is “pointer to noexcept function”.
- If the original A is a pointer-to-member-function type,A can be “pointer to member of type function” even if the deduced A is “pointer to member of type noexcept function”.
- The deduced Acan be another pointer or pointer-to-member type that can be converted to A via a qualification conversion.
These alternatives are considered only if type deduction would otherwise fail.
If they yield more than one possible deducedA, the type deduction fails.
13.10.3.5 Deducing template arguments during partial ordering [temp.deduct.partial]
Template argument deduction is done by comparing certain types associated with the two function templates being compared.
Two sets of types are used to determine the partial ordering.
For each of the templates involved there is the original function type and the transformed function type.
[Note 1:
The creation of the transformed type is described in [temp.func.order].
— _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.
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.
The types used to determine the ordering depend on the context in which the partial ordering is done:
- In the context of a function call, the types used are those function parameter types for which the function call has arguments.143
- In the context of a call to a conversion function, the return types of the conversion function templates are used.
- In other contexts the function template's function type is used.
Each type nominated above from the parameter template and the corresponding type from the argument template are used as the types ofPandA.
Before the partial ordering is done, certain transformations are performed on the types used for partial ordering:
- IfPis a reference type,Pis replaced by the type referred to.
- IfAis a reference type,Ais replaced by the type referred to.
If bothPandAwere 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.
The result of this determination will be used below.
Remove any top-level cv-qualifiers:
- IfPis a cv-qualified type,Pis replaced by the cv-unqualified version ofP.
- IfAis a cv-qualified type,Ais replaced by the cv-unqualified version ofA.
Using the resulting typesPandA, the deduction is then done as described in [temp.deduct.type].
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 of the function parameter pack.
Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack.
Similarly, if A was transformed from a function parameter pack, it is compared with each remaining parameter type of the parameter template.
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.
[Example 1: template<class... Args> void f(Args... args); template<class T1, class... Args> void f(T1 a1, Args... args); template<class T1, class T2> void f(T1 a1, T2 a2); f(); f(1, 2, 3); f(1, 2); — _end example_]
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):
- 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,
- 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.
Function template Fis at least as specialized asfunction template G if, for each pair of types used to determine the ordering, the type from Fis at least as specialized as the type from G.
Fis more specialized than G ifFis at least as specialized asG andGis not at least as specialized asF.
If, after considering the above, function template Fis 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.
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.
[Note 2:
A template parameter used in a non-deduced context is considered used.
— _end note_]
[Example 2: template <class T> T f(int); template <class T, class U> T f(U); void g() { f<int>(1); } — _end example_]
[Note 3:
Partial ordering of function templates containing template parameter packs is independent of the number of deduced arguments for those template parameter packs.
— _end note_]
[Example 3: template<class ...> struct Tuple { };template<class ... Types> void g(Tuple<Types ...>); template<class T1, class ... Types> void g(Tuple<T1, Types ...>); template<class T1, class ... Types> void g(Tuple<T1, Types& ...>); g(Tuple<>()); g(Tuple<int, float>()); g(Tuple<int, float&>()); g(Tuple<int>()); — _end example_]
13.10.3.6 Deducing template arguments from a type [temp.deduct.type]
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 non-type parameter, or a template for a template parameter) that will makeP, after substitution of the deduced values (call it the deducedA), compatible withA.
In some cases, the deduction is done using a single set of typesPandA, in other cases, there will be a set of corresponding typesPandA.
Type deduction is done independently for eachP/Apair, and the deduced template argument values are then combined.
If type deduction cannot be done for anyP/Apair, 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.
The type of a type parameter is only deduced from an array bound if it is not otherwise deduced.
A given typePcan be composed from a number of other types, templates, and non-type values:
- A function type includes the types of each of the function parameters and the return type.
- A pointer-to-member type includes the type of the class object pointed to and the type of the member pointed to.
- A type that is a specialization of a class template (e.g.,A<int>) includes the types, templates, and non-type values referenced by the template argument list of the specialization.
- An array type includes the array element type and the value of the array bound.
In most cases, the types, templates, and non-type values that are used to composePparticipate in template argument deduction.
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.
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.
If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.
[Note 1:
Under [temp.deduct.call], if P contains no template-parameters that appear in deduced contexts, no deduction is done, so P and Aneed not have the same form.
— _end note_]
The non-deduced contexts are:
- A non-type template argument or an array bound in which a subexpression references a template parameter.
- 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.
- A function parameter for which the associated argument is an overload set ([over.over]), and one or more of the following apply:
- more than one function matches the function parameter type (resulting in an ambiguous deduction), or
- no function matches the function parameter type, or
- the overload set supplied as an argument contains one or more function templates.
- A function parameter for which the associated argument is an initializer list ([dcl.init.list]) but the parameter does not have a type for which deduction from an initializer list is specified ([temp.deduct.call]).
[Example 1: template<class T> void g(T); g({1,2,3}); — _end example_]
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.
However, a compound type can include both deduced and non-deduced types.
[Example 2:
If a type is specified asA<T>::B<T2>, bothTandT2are non-deduced.
Likewise, if a type is specified asA<I+J>::X<T>,I,J, andTare non-deduced.
If a type is specified asvoid f(typename A<T>::B, A<T>), theTinA<T>::Bis non-deduced but theTinA<T>is deduced.
— _end example_]
[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); f(b,a); f(a,a); f(b,b); }
Here is an example where two template arguments are deduced from a single function parameter/argument pair.
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); f(g2); f(g3); }
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); }
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); f(d2); }
— _end example_]
A template type argumentT, a template template argumentTTor a template non-type argumentican be deduced ifPandAhave one of the following forms:Tcv T T*T&T&&T[_integer-constant_] template-name<T> (where template-name refers to a class template) type(T)T()T(T)T type::* type T::*T T::*T (type::*)() type (T::*)() type (type::*)(T) type (T::*)(T)T (type::*)(T)T (T::*)()T (T::*)(T) _type_[i] template-name<i> (where template-name refers to a class template)TT<T>TT<i>TT<> where(T)represents a parameter-type-list ([dcl.fct]) where at least one parameter type contains aT, and()represents a parameter-type-list where no parameter type contains aT.
Similarly,<T>represents template argument lists where at least one argument contains aT,<i>represents template argument lists where at least one argument contains aniand<>represents template argument lists where no argument contains aTor ani.
If P has a form that contains <T>or <i>, then each argument of the respective template argument list of P is compared with the corresponding argument of the corresponding template argument list of A.
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.
If is a pack expansion, then the pattern of is compared with each remaining argument in the template argument list of A.
Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by .
During partial ordering, if was originally a pack expansion:
- if P does not contain a template argument corresponding to then is ignored;
- otherwise, if is not a pack expansion, template argument deduction fails.
[Example 4: template<class T1, class... Z> class S; template<class T1, class... Z> class S<T1, const Z&...> { }; template<class T1, class T2> class S<T1, const T2&> { }; S<int, const int&> s; template<class T, class... U> struct A { }; template<class T1, class T2, class... U> struct A<T1, T2*, U...> { }; template<class T1, class T2> struct A<T1, T2> { }; template struct A<int, int*>; — _end example_]
Similarly, if P has a form that contains(T), then each parameter type of the respective parameter-type-list ([dcl.fct]) ofP is compared with the corresponding parameter type of the corresponding parameter-type-list of A.
If P and A are function types that originated from deduction when taking the address of a function template ([temp.deduct.funcaddr]) or when deducing template arguments from a function declaration ([temp.deduct.decl]) and and are parameters of the top-level parameter-type-list of P and A, respectively, is adjusted if it is a forwarding reference ([temp.deduct.call]) and is an lvalue reference, in which case the type of is changed to be the template parameter type (i.e., T&& is changed to simply T).
[Note 2:
As a result, when is T&&and is X&, the adjusted will be T, causing T to be deduced as X&.
— _end note_]
[Example 5: template <class T> void f(T&&);template <> void f(int&) { } template <> void f(int&&) { } void g(int i) { f(i); f(0); } — _end example_]
If the parameter-declarationcorresponding to is a function parameter pack, then the type of its declarator-id is compared with each remaining parameter type in the parameter-type-list of A.
Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack.
During partial ordering, if was originally a function parameter pack:
- if P does not contain a function parameter type corresponding to then is ignored;
- otherwise, if is not a function parameter pack, template argument deduction fails.
[Example 6: template<class T, class... U> void f(T*, U...) { } template<class T> void f(T) { } template void f(int*); — _end example_]
These forms can be used in the same way asTis for further composition of types.
[Example 7:
X<int> (*)(char[6]) is of the formtemplate-name<T> (*)(type_[i]) which is a variant of_type (*)(T) where type isX<int>andTischar[6].
— _end example_]
Template arguments cannot be deduced from function arguments involving constructs other than the ones specified above.
When the value of the argument corresponding to a non-type template parameter Pthat is declared with a dependent type is deduced from an expression, the template parameters in the type of Pare deduced from the type of the value.
[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; — _end example_]
The type of N in the type T[N] is std::size_t.
[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; — _end example_]
[Example 10: template<class T, T i> void f(int (&a)[i]);int v[10];void g() { f(v); } — _end example_]
[Note 3:
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); f1<20>(v); f2(v); f2<10>(v); f3(v); }
— _end note_]
[Note 4:
If, in the declaration of a function template with a non-type template parameter, the non-type template parameter is used in a subexpression in the function parameter list, the expression is a non-deduced context as specified above.
[Example 11: 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); g<0>(a1); f(a1, a2); } — _end example_]
— _end note_]
[Note 5:
Template parameters do not participate in template argument deduction if they are used only in non-deduced contexts.
For example,
template<int i, typename T>T deduce(typename A<T>::X x, T t, typename B<i>::Y y); A<int> a; B<77> b;int x = deduce<77>(a.xm, 62, b.ym); — _end note_]
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, deduction fails.
If P has a form that contains [i], and if the type ofi is not an integral type, deduction fails.144
[Example 12: template<int i> class A { };template<short s> void f(A<s>);void k1() { A<1> a; f(a); f<1>(a); } template<const short cs> class B { };template<short s> void g(B<s>);void k2() { B<1> b; g(b); } — _end example_]
Atemplate-argumentcan be deduced from a function, pointer to function, or pointer-to-member-function type.
[Example 13: 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); f(&h); f(&foo); } — _end example_]
A templatetype-parametercannot be deduced from the type of a function default argument.
[Example 14: template <class T> void f(T = 5, T = 7);void g() { f(1); f(); f<int>(); } — _end example_]
Thetemplate-argumentcorresponding to a templatetemplate-parameteris deduced from the type of thetemplate-argumentof a class template specialization used in the argument list of a function call.
[Example 15: 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); — _end example_]
[Note 6:
Template argument deduction involving parameter packs ([temp.variadic]) can deduce zero or more arguments for each parameter pack.
— _end note_]
[Example 16: 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; X<int(int, float, double)> x2; X<int(float, int)> x3; Y<> y1; Y<int&, float&, double&> y2; Y<int, float, double> y3; int fv = f(g); — _end example_]
13.10.3.7 Deducing template arguments from a function declaration [temp.deduct.decl]
In a declaration whose declarator-id refers to a specialization of a function template, template argument deduction is performed to identify the specialization to which the declaration refers.
Specifically, this is done for explicit instantiations, explicit specializations, and certain friend declarations.
In all these cases, P is the type of the function template being considered as a potential match and A is either the function type from the declaration or the type of the deallocation function that would match the placementoperator new as described in [expr.new].
The deduction is done as described in [temp.deduct.type].
If, for the set of function templates so considered, there is either no match or more than one match after partial ordering has been considered ([temp.func.order]), deduction fails and, in the declaration cases, the program is ill-formed.
13.10.4 Overload resolution [temp.over]
When a call to the name of a function or function template is written (explicitly, or implicitly using the operator notation), template argument deduction ([temp.deduct]) and checking of any explicit template arguments ([temp.arg]) are performed for each function template to find the template argument values (if any) that can be used with that function template to instantiate a function template specialization that can be invoked with the call arguments.
For each function template, if the argument deduction and checking succeeds, thetemplate-arguments(deduced and/or explicit) are used to synthesize the declaration of a single function template specialization which is added to the candidate functions set to be used in overload resolution.
If, for a given function template, argument deduction fails or the synthesized function template specialization would be ill-formed, no such function is added to the set of candidate functions for that template.
The complete set of candidate functions includes all the synthesized declarations and all of the non-template overloaded functions of the same name.
The synthesized declarations are treated like any other functions in the remainder of overload resolution, except as explicitly noted in [over.match.best].145
[Example 1: template<class T> T max(T a, T b) { return a>b?a:b; } void f(int a, int b, char c, char d) { int m1 = max(a,b); char m2 = max(c,d); int m3 = max(a,c); }
Adding the non-template functionint max(int,int);to the example above would resolve the third call, by providing a function that could be called formax(a,c)after using the standard conversion ofchartointforc.
— _end example_]
[Example 2:
Here is an example involving conversions on a function argument involved intemplate-argumentdeduction:template<class T> struct B { };template<class T> struct D : public B<T> { };template<class T> void f(B<T>&);void g(B<int>& bi, D<int>& di) { f(bi); f(di); }
— _end example_]
[Example 3:
Here is an example involving conversions on a function argument not involved intemplate-parameterdeduction:template<class T> void f(T*,int); template<class T> void f(T,char); void h(int* pi, int i, char c) { f(pi,i); f(pi,c); f(i,c); f(i,i); }
— _end example_]
Only the signature of a function template specialization is needed to enter the specialization in a set of candidate functions.
Therefore only the function template declaration is needed to resolve a call for which a template specialization is a candidate.
[Example 4: template<class T> void f(T); void g() { f("Annemarie"); }
The call offis well-formed even if the templatefis only declared and not defined at the point of the call.
The program will be ill-formed unless a specialization forf<const char*>is explicitly instantiated in some translation unit ([temp.pre]).
— _end example_]