[temp.param] (original) (raw)

13 Templates [temp]

13.2 Template parameters [temp.param]

The syntax fortemplate-parameter_s_is:

type-parameter-key:
class
typename

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 && ...).

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:

The top-levelcv-qualifier_s_on thetemplate-parameterare ignored when determining its type.

A structural type is one of the following:

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]).

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_]

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_]