template-parameter: type-parameter parameter-declaration
type-parameter: type-parameter-key ... identifier type-parameter-key identifier = type-id template < template-parameter-list > type-parameter-key ... identifier template < template-parameter-list > type-parameter-key identifier = id-expression
type-parameter-key: class typename
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 }
template<const X& x, int i> void f() { i++; // error: change of template-parameter value &x; // OK &i; // error: address of non-reference template-parameter int& ri = i; // error: non-const reference bound to temporary const int& cri = i; // OK: const reference bound to temporary }
template<double d> class X; // error template<double* pd> class Y; // OK template<double& rd> class Z; // OK
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
template<class T1, class T2 = int> class A; template<class T1 = int, class T2> class A;
template<class T1 = int, class T2 = int> class A;
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
template<class T = int> class X; template<class T = int> class X { /* ... */ }; // error
template<int i = 3 > 4 > // syntax error class X { /* ... */ }; template<int i = (3 > 4) > // OK class Y { /* ... */ };
template <class T = float> struct B {}; 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> }
template <class... Types> class Tuple; // Types is a template type parameter pack // but not a pack expansion template <class T, int... Dims> struct multi_array; // Dims is a non-type template parameter pack // but not a pack expansion template<class... T> struct value_holder { template<T... Values> struct apply { }; // Values is a non-type template parameter pack // and a pack expansion }; template<class... T, T... Values> struct static_array;// error: Values expands template type parameter // pack T within the same template parameter list