Template parameters and template arguments
Every template is parametrized by one or more template parameters, indicated in the parameter-list of the template declaration syntax:
template < parameter-list > declaration
|
(1) | ||||||||
Each parameter in parameter-list may be:
- a non-type template parameter;
- a type template parameter;
- a template template parameter.
Non-type template parameter
type name(optional) | (1) | ||||||||
type name(optional) = default
|
(2) | ||||||||
type ... name(optional)
|
(3) | (since C++11) | |||||||
auto name
|
(4) | (since C++17) | |||||||
auto
)type is one of the following types (optionally cv-qualified, the qualifiers are ignored):
- std::nullptr_t (since C++11);
- integral type;
- lvalue reference type (to object or to function);
- pointer type (to object or to function);
- pointer to member type (to member object or to member function);
- enumeration type.
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.
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
.
The type of a non-type template parameter may be deduced if it includes the placeholder keyword template<auto n> struct B { /* ... */ }; B<5> b1; // OK: non-type template parameter type is int B<'a'> b2; // OK: non-type template parameter type is char B<2.5> b3; // error: non-type template parameter type cannot be double |
(since C++17) |
Type template parameter
typename name(optional)
|
(1) | ||||||||
class name(optional)
|
(2) | ||||||||
typename|class name(optional) = default
|
(3) | ||||||||
typename|class ... name(optional)
|
(4) | (since C++11) | |||||||
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.
There is no difference between the keywords class
and typename
in a type template parameter declaration.
Template template parameter
template < parameter-list > typename(C++17)|class name(optional)
|
(1) | ||||||||
template < parameter-list > typename(C++17)|class name(optional) = default
|
(2) | ||||||||
template < parameter-list > typename(C++17)|class ... name(optional)
|
(3) | (since C++11) | |||||||
Unlike type template parameter declaration, template template parameter declaration can only use the keyword |
(until C++17) |
In the body of the template declaration, the name of this parameter is a template-name (and needs arguments to be instantiated).
template<typename T> class my_array {}; // two type template parameters and one template template parameter: template<typename K, typename V, template<typename> typename C = my_array> class Map { C<K> key; C<V> value; };
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 a both a type-id and an expression, it is always interpreted as a type-id, even if the corresponding template parameter is non-type:
template<class T> void f(); // #1 template<int I> void f(); // #2 void g() { f<int()>(); // "int()" is both a type and an expression, // calls #1 because it is interpreted as a type }
Template non-type arguments
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. |
(until C++17) |
The template argument that can be used with a non-type template parameter can be any converted constant expression of the type of the template parameter. template<const int* pci> struct X {}; int ai[10]; X<ai> xi; // ok: array to pointer conversion and cv-qualification conversion struct Y {}; template<const Y& b> struct Z {}; Y y; Z<y> z; // ok: no conversion template<int (&pa)[5]> struct W {}; int b[5]; W<b> w; // ok: no conversion void f(char); void f(int); template<void (*pf)(int)> struct A {}; A<&f> a; // ok: overload resolution selects f(int) The only exceptions are that non-type template parameters of reference and pointer type cannot refer to/be the address of
template<class T, const char* p> class X {}; X<int, "Studebaker"> x1; // error: string literal as template-argument template<int* p> class X {}; int a[10]; struct S { int m; static int s; } s; X<&a[2]> x3; // error: address of array element X<&s.m> x4; // error: address of non-static member X<&s.s> x5; // ok: address of static member X<&S::s> x6; // ok: address of static member template<const int& CRI> struct B {}; B<1> b2; // error: temporary would be required for template argument int c = 1; B<c> b1; // ok |
(since C++17) |
Template type arguments
A template argument for a type template parameter must be a type-id, which may name an incomplete type:
template<typename T> class X {}; // class template struct A; // incomplete type typedef struct {} B; // type alias to an unnamed type int main() { X<A> x1; // ok: 'A' names a type X<A*> x2; // ok: 'A*' names a type X<B> x3; // ok: 'B' names a type }
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.
template<typename T> class A { int x; }; // primary template template<class T> class A<T*> { long x; }; // partial specialization // class template with a template template parameter V template<template<typename> class V> class C { V<int> y; // uses the primary template V<int*> z; // uses the partial specialization }; C<A> 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
, each of the template parameters of A
must match corresponding template parameters of P
exactly (until C++14)P
must be at least as specialized as A
(since C++14). 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.
template<typename T> struct eval; // primary template template<template<typename, typename...> class TT, typename T1, typename... Rest> struct eval<TT<T1, Rest...>> {}; // partial specialization of eval template<typename T1> struct A; template<typename T1, typename T2> struct B; template<int N> struct C; template<typename T1, int N> struct D; template<typename T1, typename T2, int N = 17> struct E; eval<A<int>> eA; // ok: matches partial specialization of eval eval<B<int, float>> eB; // ok: matches partial specialization of eval eval<C<17>> 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 eval<D<int, 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 eval<E<int, float>> eE; // error: E does not match TT in partial specialization // because E's third (default) parameter is a non-type
template<class T> class A { /* ... */ }; template<class T, class U = T> class B { /* ... */ }; template <class ...Types> class C { /* ... */ }; template<template<class> class P> class X { /* ... */ }; X<A> xa; // OK X<B> xb; // OK in C++14 after CWG 150 // Error earlier: not an exact match X<C> xc; // OK in C++14 after CWG 150 // Error earlier: not an exact match template<template<class ...> class Q> class Y { /* ... */ }; Y<A> ya; // OK Y<B> yb; // OK Y<C> yc; // OK template<auto n> class D { /* ... */ }; // note: C++17 template<template<int> class R> class Z { /* ... */ }; Z<D> zd; // OK template <int> struct SI { /* ... */ }; template <template <auto> class> void FA(); // note: C++17 FA<SI>(); // Error
Formally, a template template-parameter
If the rewrite produces an invalid type, then |
(since C++14) |
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.
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. In a function template, a parameter pack may be followed by more type parameters only if they have defaults or can be deduced from the function arguments.
Default parameters are not allowed
- in the out-of-class definition of a member template (they have to be provided in the declaration inside the class body)
- in friend class template declarations
|
(until C++11) |
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. |
(since C++11) |
Default template arguments that appear in the declarations and the definition are merged similarly to default function arguments:
template<typename T1, typename T2 = int> class A; template<typename T1 = int, typename T2> class A; // the above is the same as the following: template<typename T1 = int, typename T2 = int> class A;
But the same parameter cannot be given default arguments twice in the same scope
template<typename T = int> class X; template<typename T = int> class X {}; // error
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 template<typename T = float> struct B {}; // template template parameter T has a parameter list, which // consists of one type template parameter with a default template<template<typename = float> typename T> struct A { void f(); void g(); }; // out-of-body member function template definitions template<template<typename TT> class T> void A<T>::f() { T<> t; // error: TT has no default in scope } template<template<typename TT = char> class T> void A<T>::g() { T<> t; // ok: t is T<char> }
Member access for the names used in a default template parameter is checked at the declaration, not at the point of use:
class B {}; template<typename T> class C { protected: typedef T TT; }; template<typename U, typename V = typename U::TT> class D: public U {}; D<C<B>>* 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: template<typename T, typename U = int> struct S { }; S<bool>* p; // The default argument for U is instantiated at this point // the type of p is S<bool, int>* |
(since C++14) |
Examples
Non-type template parameters
#include <iostream> // simple non-type template parameter template<int N> struct S { int a[N]; }; template<const 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 (S<10>::*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<"fail"> s2; // error: string literal cannot be used char okay[] = "okay"; // static object with linkage S2< &okay[0] > s2; // error: array element has no linkage S2<okay> s2; // works int a[5]; int f(int n) { return n; } int main() { S<10> s; // s.a is an array of 10 int s.a[9] = 4; Complicated<'2', a, f, &S<10>::a> c; c.foo('0'); std::cout << s.a[9] << a[4] << '\n'; }
Output:
42
This section is incomplete Reason: more examples |
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 | C++14 | template-template arguments had to match parameter lists of template-template parameters exactly | more specialized also allowed |