[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:
- 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]).
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_]