Template parameters and template arguments

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:

[edit] Non-type template parameter

type name  (optional) (1)
type name  (optional) = default (2)
type . name  (optional) (3) (since C++11)
1) A non-type template parameter. 2) A non-type template parameter with a default template argument. 3) A non-type template parameter pack.

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 }

[edit] Type template parameter

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
1) A type template parameter without a default.
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 && . )

[edit] Template template parameter

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)
1) A template template parameter with an optional name. 2) A template template parameter with an optional name and a default. 3) A template template parameter pack with an optional name.

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; };

[edit] Name resolution for template parameters

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 };

[edit] Template arguments

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 }

[edit] Template non-type arguments

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

[edit] Template type arguments

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 }

[edit] Template template arguments

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

[edit] Default template arguments

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*

[edit] Template argument equivalence

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:

[edit] Notes

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

[edit] Examples

Run this code
#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

[edit] Defect reports

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