13 Templates [temp]

13.2 Template parameters [temp.param]

type-parameter-key:
class
typename
The component names of a type-constraint are its concept-name and those of its nested-name-specifier (if any).
[Note 1: 
The > token following the template-parameter-list of a type-tt-parameter, variable-tt-parameter, or concept-tt-parameter can be the product of replacing a >> token by two consecutive > tokens ([temp.names]).
— end note]
A template parameter is of one of the following kinds:
Type template template parameters, variable template template parameters, and concept template parameters are collectively referred to as template template parameters.
A concept template parameter shall not have associated constraints ([temp.constr.decl]).
If a template-parameter is a parameter-declaration that declares a pack ([dcl.fct]), or otherwise has an ellipsis prior to its optional identifier, then the template-parameter declares a template parameter pack ([temp.variadic]).
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 template template parameter with a template-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 same template-parameter-list.
[Example 1: template <class... Types> // Types is a template type parameter pack class Tuple; // but not a pack expansion template <class T, int... Dims> // Dims is a constant template parameter pack struct multi_array; // but not a pack expansion template <class... T> struct value_holder { template <T... Values> struct apply { }; // Values is a constant template parameter pack }; // and a pack expansion template <class... T, T... Values> // error: Values expands template type parameter struct static_array; // pack T within the same template parameter list — end example]
There is no semantic difference between class and typename in a type-parameter-key.
typename followed by an unqualified-id names a template type parameter.
typename followed by a qualified-id denotes the type in a parameter-declaration.
[Example 2: class T { /* ... */ }; int i; template<class T, T i> void f(T t) { T t1 = i; // template parameters T and i ::T t2 = ::i; // global namespace members T and i }
Here, the template f has a type template parameter called T, rather than an unnamed constant template parameter of class T.
— end example]
Types shall not be defined in a template parameter declaration.
The identifier in a template-parameter denoting a type or template is not looked up.
An identifier that does not follow an ellipsis is defined to be in the scope of the template declaration.
A type-constraint Q that designates a concept C can be used to constrain a contextually-determined type or template type parameter pack T with 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 && ...).
The concept designated by a type-constraint shall be a type concept ([temp.concept]).
A type-parameter that starts with a type-constraint introduces the immediately-declared constraint of the type-constraint for the parameter.
[Example 3: 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; // associates C1<T> template<C1... T> struct s2; // associates (C1<T> && ...) template<C2... T> struct s3; // associates (C2<T> && ...) template<C3<int> T> struct s4; // associates C3<T, int> template<C3<int>... T> struct s5; // associates (C3<T, int> && ...) — end example]
A constant template parameter shall have one of the following (possibly cv-qualified) types:
The top-level cv-qualifiers on the template-parameter are 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 base classes and non-static data members are structural types or (possibly multidimensional) arrays thereof.
An id-expression naming a constant template parameter of class type T denotes a static storage duration object of type const T, known as a template parameter object, which is template-argument-equivalent ([temp.type]) to the corresponding template argument after it has been converted to the type of the template parameter ([temp.arg.nontype]).
No two template parameter objects are template-argument-equivalent.
[Note 2: 
If an id-expression names a non-reference constant 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 4: using X = int; struct A {}; template<const X& x, int i, A a> void f() { i++; // error: change of template parameter value &x; // OK &i; // error: address of non-reference template parameter &a; // OK int& ri = i; // error: attempt to bind non-const reference to temporary const int& cri = i; // OK, const reference binds to temporary const A& ra = a; // OK, const reference binds to a template parameter object } — end example]
[Note 3: 
A constant template parameter cannot be declared to have type cv void.
[Example 5: template<void v> class X; // error template<void* pv> class Y; // OK — end example]
— end note]
A constant template parameter of type “array of T” or of function type T is adjusted to be of type “pointer to T.
[Example 6: template<int* a> struct R { /* ... */ }; template<int b[5]> struct S { /* ... */ }; int p; R<&p> w; // OK S<&p> x; // OK due to parameter adjustment int v[5]; R<v> y; // OK due to implicit argument conversion S<v> z; // OK due to both adjustment and conversion — end example]
A constant template parameter declared with a type that contains a placeholder type with a type-constraint introduces the immediately-declared constraint of the type-constraint for the invented type corresponding to the placeholder ([dcl.fct]).
A default template argument is a template argument ([temp.arg]) specified after = in a template-parameter.
A default template argument may be specified for any kind of template parameter that is not a template parameter pack ([temp.variadic]).
A default template argument may be specified in a template declaration.
A default template argument shall not be specified in the template-parameter-lists of the definition of a member of a class template that appears outside of the member's class.
A default template argument shall not be specified in a friend class template declaration.
If a friend function template declaration D specifies a default template argument, that declaration shall be a definition and there shall be no other declaration of the function template which is reachable from D or from which D is reachable.
The set of default template arguments 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 7: 
template<class T1, class T2 = int> class A; template<class T1 = int, class T2> class A; is equivalent to template<class T1 = int, class T2 = int> class A;
— end example]
If a template-parameter of a class template, variable template, or alias template has a default template argument, each subsequent template-parameter shall either have a default template argument supplied or declare a template parameter pack.
If a template-parameter of a primary class template, primary variable template, or alias template declares a template parameter pack, it shall be the last template-parameter.
If a template-parameter of a function template declares a template parameter pack, it shall not be followed by another template-parameter unless that template parameter is deducible 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 8: template<class T1 = int, class T2> class B; // error // U can be neither deduced from the parameter-type-list nor specified template<class... T, class... U> void f() { } // error template<class... T, class U> void g() { } // error — end example]
When parsing a default template argument for a constant template parameter, the first non-nested > is taken as the end of the template-parameter-list rather than a greater-than operator.
[Example 9: template<int i = 3 > 4 > // syntax error class X { /* ... */ }; template<int i = (3 > 4) > // OK class Y { /* ... */ }; — end example]
A template-parameter of a template template-parameter is permitted to have a default template argument.
When such default arguments are specified, they apply to the template template-parameter in the scope of the template template-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; // error: TT has no default template argument } template <template <class TT = char> class T> void A<T>::g() { T<> t; // OK, T<char> } — end example]
The associated constraints of a template template parameter shall not contain a concept-dependent constraint ([temp.constr.concept]).
[Example 11: template< template<typename> concept C, template<C> class TT // error: C forms a concept-dependent constraint > struct A {}; — end example]