Every template is parameterized by one or more template parameters, indicated in the parameter-list of the template declaration syntax:
template parameter-list > declaration | (1) | |
template parameter-list > requires constraint declaration | (2) | (since C++20) |
Each parameter in parameter-list may be:
type name (optional) | (1) | |
type name (optional) = default | (2) | |
type . name (optional) | (3) | (since C++11) |
A structural type is one of the following types (optionally cv-qualified, the qualifiers are ignored):
Array and function types may be written in a template declaration, but they are automatically replaced by pointer to object and pointer to function as appropriate.
When the name of a non-type template parameter is used in an expression within the body of the class template, it is an unmodifiable prvalue unless its type was an lvalue reference type , or unless its type is a class type (since C++20) .
A template parameter of the form class Foo is not an unnamed non-type template parameter of type Foo , even if otherwise class Foo is an elaborated type specifier and class Foo x ; declares x to be of type Foo .
An identifier that names a non-type template parameter of class type T denotes a static storage duration object of type const T , called a template parameter object, which is template-argument-equivalent to the corresponding template argument after it has been converted to the type of the template parameter. No two template parameter objects are template-argument-equivalent.
struct A { friend bool operator==(const A&, const A&) = default; }; templateA a> void f() { &a; // OK const A& ra = a, &rb = a; // Both bound to the same template parameter object assert(&ra == &rb); // passes }
type-parameter-key name (optional) | (1) | |
type-parameter-key name (optional) = default | (2) | |
type-parameter-key . name (optional) | (3) | (since C++11) |
type-constraint name (optional) | (4) | (since C++20) |
type-constraint name (optional) = default | (5) | (since C++20) |
type-constraint . name (optional) | (6) | (since C++20) |
type-parameter-key | - | either typename or class . There is no difference between these keywords in a type template parameter declaration |
type-constraint | - | either the name of a concept or the name of a concept followed by a list of template arguments (in angle brackets). Either way, the concept name may be optionally qualified |
name | - | the name of the type template parameter |
default | - | the default template argument |
templateclass T> class My_vector { /* . */ };2) A type template parameter with a default.
templateclass T = void> struct My_op_functor { /* . */ };3) A type template parameter pack.
templatetypename. Ts> class My_tuple { /* . */ };4) A constrained type template parameter without a default.
templateMy_concept T> class My_constrained_vector { /* . */ };5) A constrained type template parameter with a default.
templateMy_concept T = void> class My_constrained_op_functor { /* . */ };6) A constrained type template parameter pack.
templateMy_concept. Ts> class My_constrained_tuple { /* . */ };
The name of the parameter is optional:
// Declarations of the templates shown above: templateclass> class My_vector; templateclass = void> struct My_op_functor; templatetypename. > class My_tuple;
In the body of the template declaration, the name of a type parameter is a typedef-name which aliases the type supplied when the template is instantiated.
Each constrained parameter P whose type-constraint is Q designating the concept C introduces a constraint-expression E according to the following rules:
templatetypename T> concept C1 = true; templatetypename. Ts> // variadic concept concept C2 = true; templatetypename T, typename U> concept C3 = true; templateC1 T> struct s1; // constraint-expression is C1 templateC1. T> struct s2; // constraint-expression is (C1 && . ) templateC2. T> struct s3; // constraint-expression is (C2 && . ) templateC3int> T> struct s4; // constraint-expression is C3 templateC3int>. T> struct s5; // constraint-expression is (C3 && . )
template parameter-list > type-parameter-key name (optional) | (1) | |
template parameter-list > type-parameter-key name (optional) = default | (2) | |
template parameter-list > type-parameter-key . name (optional) | (3) | (since C++11) |
type-parameter-key | - | class or typename (since C++17) |
In the body of the template declaration, the name of this parameter is a template-name (and needs arguments to be instantiated).
templatetypename T> class my_array {}; // two type template parameters and one template template parameter: templatetypename K, typename V, templatetypename> typename C = my_array> class Map { CK> key; CV> value; };
The name of a template parameter is not allowed to be redeclared within its scope (including nested scopes). A template parameter is not allowed to have the same name as the template name.
templateclass T, int N> class Y { int T; // error: template parameter redeclared void f() { char T; // error: template parameter redeclared } }; templateclass X> class X; // error: template parameter redeclared
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 a template parameter of any enclosing class templates, but not a template parameter of the member if the member is a class or function template.
templateclass T> struct A { struct B {}; typedef void C; void f(); templateclass U> void g(U); }; templateclass B> void AB>::f() { B b; // A's B, not the template parameter } templateclass B> templateclass C> void AB>::g(C) { B b; // A's B, not the template parameter C c; // the template parameter C, not A's C }
In the definition of a member of a class template that appears outside of the namespace containing the class template definition, the name of a template parameter hides the name of a member of this namespace.
namespace N { class C {}; templateclass T> class B { void f(T); }; } templateclass C> void N::BC>::f(C) { C b; // C is the template parameter, not N::C }
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, if the name of the base class or the name of a member of the base class is the same as the name of a template parameter, the base class name or member name hides the template parameter name.
struct A { struct B {}; int C; int Y; }; templateclass B, class C> struct X : A { B b; // A's B C b; // error: A's C isn't a type name };
In order for a template to be instantiated, every template parameter (type, non-type, or template) must be replaced by a corresponding template argument. For class templates, the arguments are either explicitly provided , deduced from the initializer, (since C++17) or defaulted. For function templates, the arguments are explicitly provided, deduced from the context, or defaulted.
If an argument can be interpreted as both a type-id and an expression, it is always interpreted as a type-id, even if the corresponding template parameter is non-type:
templateclass T> void f(); // #1 templateint I> void f(); // #2 void g() { fint()>(); // "int()" is both a type and an expression, // calls #1 because it is interpreted as a type }
The template argument that can be used with a non-type template parameter can be any manifestly constant-evaluated expression.
The template argument that can be used with a non-type template parameter can be any initializer clause. If the initializer clause is an expression, it must be manifestly constant-evaluated.
If T contains a placeholder type, or is a placeholder for a deduced class type, the type of the template parameter is the type deduced for the variable x in the invented declaration T x = E ; , where E is the template argument provided for the parameter.
If a deduced parameter type is not a structural type, the program is ill-formed.
templateauto n> struct B { /* . */ }; B5> b1; // OK: non-type template parameter type is int B'a'> b2; // OK: non-type template parameter type is char B2.5> b3; // error (until C++20): non-type template parameter type cannot be double // C++20 deduced class type placeholder, class template arguments are deduced at the // call site templatestd::array arr> void f(); fstd::arraydouble, 8>{}>();
For non-type template parameter packs whose type uses a placeholder type, the type is independently deduced for each template argument and need not match:
templateauto. > struct C {}; C'C', 0, 2L, nullptr> x; // OK
The value of a non-type template parameter P of (possibly deduced) (since C++17) type T is determined from its template argument A as follows:
templateint i> struct C { /* . */ }; C{42}> c1; // OK templateauto n> struct B { /* . */ }; struct J1 { J1* self = this; }; BJ1{}> j1; // error: initialization of the template parameter object // is not a constant expression struct J2 { J2 *self = this; constexpr J2() {} constexpr J2(const J2&) {} }; BJ2{}> j2; // error: the template parameter object is not // template-argument-equivalent to introduced temporary
The following limitations apply when instantiating templates that have non-type template parameters:
In particular, this implies that string literals, addresses of array elements, and addresses of non-static members cannot be used as template arguments to instantiate templates whose corresponding non-type template parameters are pointers to objects.
Non-type template parameters of reference or pointer type and non-static data members of reference or pointer type in a non-type template parameter of class type and its subobjects (since C++20) cannot refer to/be the address of
templateconst int* pci> struct X {}; int ai[10]; Xai> xi; // OK: array to pointer conversion and cv-qualification conversion struct Y {}; templateconst Y& b> struct Z {}; Y y; Zy> z; // OK: no conversion templateint (&pa)[5]> struct W {}; int b[5]; Wb> w; // OK: no conversion void f(char); void f(int); templatevoid (*pf)(int)> struct A {}; A&f> a; // OK: overload resolution selects f(int)
templateclass T, const char* p> class X {}; Xint, "Studebaker"> x1; // error: string literal as template-argument templateint* p> class X {}; int a[10]; struct S { int m; static int s; } s; X&a[2]> x3; // error (until C++20): address of array element X&s.m> x4; // error (until C++20): address of non-static member X&s.s> x5; // OK: address of static member X&S::s> x6; // OK: address of static member templateconst int& CRI> struct B {}; B1> b2; // error: temporary would be required for template argument int c = 1; Bc> b1; // OK
A template argument for a type template parameter must be a type-id, which may name an incomplete type:
templatetypename T> class X {}; // class template struct A; // incomplete type typedef struct {} B; // type alias to an unnamed type int main() { XA> x1; // OK: 'A' names a type XA*> x2; // OK: 'A*' names a type XB> x3; // OK: 'B' names a type }
A template argument for a template template parameter must be an id-expression which names a class template or a template alias.
When the argument is a class template, only the primary template is considered when matching the parameter. The partial specializations, if any, are only considered when a specialization based on this template template parameter happens to be instantiated.
templatetypename T> // primary template class A { int x; }; templatetypename T> // partial specialization class AT*> { long x; }; // class template with a template template parameter V templatetemplatetypename> class V> class C { Vint> y; // uses the primary template Vint*> z; // uses the partial specialization }; CA> c; // c.y.x has type int, c.z.x has type long
To match a template template argument A to a template template parameter P , P must be at least as specialized as A (see below). If P 's parameter list includes a parameter pack, zero or more template parameters (or parameter packs) from A 's template parameter list are matched by it. (since C++11)
Formally, a template template-parameter P is at least as specialized as a template template argument A if, given the following rewrite to two function templates, the function template corresponding to P is at least as specialized as the function template corresponding to A according to the partial ordering rules for function templates. Given an invented class template X with the template parameter list of A (including default arguments):
If the rewrite produces an invalid type, then P is not at least as specialized as A .
templatetypename T> struct eval; // primary template templatetemplatetypename, typename. > class TT, typename T1, typename. Rest> struct evalTTT1, Rest. >> {}; // partial specialization of eval templatetypename T1> struct A; templatetypename T1, typename T2> struct B; templateint N> struct C; templatetypename T1, int N> struct D; templatetypename T1, typename T2, int N = 17> struct E; evalAint>> eA; // OK: matches partial specialization of eval evalBint, float>> eB; // OK: matches partial specialization of eval evalC17>> eC; // error: C does not match TT in partial specialization // because TT's first parameter is a // type template parameter, while 17 does not name a type evalDint, 17>> eD; // error: D does not match TT in partial specialization // because TT's second parameter is a // type parameter pack, while 17 does not name a type evalEint, float>> eE; // error: E does not match TT in partial specialization // because E's third (default) parameter is a non-type
Before the adoption of P0522R0, each of the template parameters of A must match corresponding template parameters of P exactly. This hinders many reasonable template argument from being accepted.
Although it was pointed out very early (CWG#150), by the time it was resolved, the changes were applied to the C++17 working paper and the resolution became a de facto C++17 feature. Many compilers disable it by default:
templateclass T> class A { /* . */ }; templateclass T, class U = T> class B { /* . */ }; templateclass. Types> class C { /* . */ }; templatetemplateclass> class P> class X { /* . */ }; XA> xa; // OK XB> xb; // OK after P0522R0 // Error earlier: not an exact match XC> xc; // OK after P0522R0 // Error earlier: not an exact match templatetemplateclass. > class Q> class Y { /* . */ }; YA> ya; // OK YB> yb; // OK YC> yc; // OK templateauto n> class D { /* . */ }; // note: C++17 templatetemplateint> class R> class Z { /* . */ }; ZD> zd; // OK after P0522R0: the template parameter // is more specialized than the template argument templateint> struct SI { /* . */ }; templatetemplateauto> class> void FA(); // note: C++17 FASI>(); // Error
Default template arguments are specified in the parameter lists after the = sign. Defaults can be specified for any kind of template parameter (type, non-type, or template) , but not to parameter packs (since C++11) .
If the default is specified for a template parameter of a primary class template , primary variable template, (since C++14) or alias template, each subsequent template parameter must have a default argument , except the very last one may be a template parameter pack (since C++11) . In a function template, there are no restrictions on the parameters that follow a default , and a parameter pack may be followed by more type parameters only if they have defaults or can be deduced from the function arguments (since C++11) .
Default parameters are not allowed
On a friend function template declaration, default template arguments are allowed only if the declaration is a definition, and no other declarations of this function appear in this translation unit.
Default template arguments that appear in the declarations are merged similarly to default function arguments:
templatetypename T1, typename T2 = int> class A; templatetypename T1 = int, typename T2> class A; // the above is the same as the following: templatetypename T1 = int, typename T2 = int> class A;
But the same parameter cannot be given default arguments twice in the same scope:
templatetypename T = int> class X; templatetypename T = int> class X {}; // error
When parsing a default template argument for a non-type template parameter, the first non-nested > is taken as the end of the template parameter list rather than a greater-than operator:
templateint i = 3 > 4> // syntax error class X { /* . */ }; templateint i = (3 > 4)> // OK class Y { /* . */ };
The template parameter lists of template template parameters can have their own default arguments, which are only in effect where the template template parameter itself is in scope:
// class template, with a type template parameter with a default templatetypename T = float> struct B {}; // template template parameter T has a parameter list, which // consists of one type template parameter with a default templatetemplatetypename = float> typename T> struct A { void f(); void g(); }; // out-of-body member function template definitions templatetemplatetypename TT> class T> void AT>::f() { T<> t; // error: TT has no default in scope } templatetemplatetypename TT = char> class T> void AT>::g() { T<> t; // OK: t is T }
Member access for the names used in a default template parameter is checked at the declaration, not at the point of use:
class B {}; templatetypename T> class C { protected: typedef T TT; }; templatetypename U, typename V = typename U::TT> class D: public U {}; DCB>>* d; // error: C::TT is protected
The default template argument is implicitly instantiated when the value of that default argument is needed, except if the template is used to name a function:
templatetypename T, typename U = int> struct S {}; Sbool>* p; // The default argument for U is instantiated at this point // the type of p is S*
Template argument equivalence is used to determine whether two template identifiers are same.
Two values are template-argument-equivalent if they are of the same type and any of the following conditions is satisfied:
In template parameters, type constraints could be used for both type and non-type parameters, depending on whether auto is present.
templatetypename> concept C = true; templateC, // type parameter C auto // non-type parameter > struct S{}; Sint, 0> s;
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_nontype_template_parameter_auto | 201606L | (C++17) | Declaring non-type template parameters with auto |
__cpp_template_template_args | 201611L | (c++17) (DR) | Matching of template template-arguments |
__cpp_nontype_template_args | 201411L | (C++17) | Allow constant evaluation for all non-type template arguments |
201911L | (C++20) | Class types and floating-point types in non-type template parameters |
#include #include #include // simple non-type template parameter templateint N> struct S { int a[N]; }; templateconst char*> struct S2 {}; // complicated non-type example template char c, // integral type int (&ra)[5], // lvalue reference to object (of array type) int (*pf)(int), // pointer to function int (S10>::*a)[10] // pointer to member object (of type int[10]) > struct Complicated { // calls the function selected at compile time // and stores the result in the array selected at compile time void foo(char base) { ra[4] = pf(c - base); } }; // S2 s2; // error: string literal cannot be used char okay[] = "okay"; // static object with linkage // S2 s3; // error: array element has no linkage S2okay> s4; // works int a[5]; int f(int n) { return n; } // C++20: NTTP can be a literal class type templatestd::array arr> constexpr auto sum() { return std::accumulate(arr.cbegin(), arr.cend(), 0); } // C++20: class template arguments are deduced at the call site static_assert(sumstd::arraydouble, 8>{3, 1, 4, 1, 5, 9, 2, 6}>() == 31.0); // C++20: NTTP argument deduction and CTAD static_assert(sumstd::array{2, 7, 1, 8, 2, 8}>() == 28); int main() { S10> s; // s.a is an array of 10 int s.a[9] = 4; Complicated'2', a, f, &S10>::a> c; c.foo('0'); std::cout a [9] [4] <'\n'; }
This section is incomplete Reason: more examples |
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 150 (P0522R0) | C++98 | template-template arguments had to match parameter lists of template-template parameters exactly | more specialized also allowed |
CWG 184 | C++98 | whether the template parameters of template template parameters are allowed to have default arguments is unspecified | specification added |
CWG 354 | C++98 | null pointer values could not be non-type template arguments | allowed |
CWG 1398 | C++11 | template non-type arguments could not have type std::nullptr_t | allowed |
CWG 1570 | C++98 | template non-type arguments could designate addresses of subobjects | not allowed |
CWG 1922 | C++98 | it was unclear whether a class template whose name is an injected-class-name can use the default arguments in prior declarations | allowed |
CWG 2032 | C++14 | for variable templates, there was no restriction on the template parameters after a template parameter with a default argument | apply the same restriction as on class templates and alias templates |
CWG 2542 | C++20 | it was unclear whether the closure type is structural | it is not structural |
CWG 2845 | C++20 | the closure type was not structural | it is structural if capture-less |
P2308R1 | C++11 C++20 | list-initialization was not allowed for non-type template arguments it was unclear how non-type template parameters of class types are initialized | allowed made clear |