Namespaces
Variants
Views
Actions

Template parameters and template arguments

From cppreference.com
< cpp‎ | language

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.

Contents

[edit] 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)
1) A non-type template parameter with an optional name.
2) A non-type template parameter with an optional name and a default value.
3) A non-type template parameter pack with an optional name.
4) A non-type template parameter with a deduced type (note, it may also be auto ** or any other type that includes the placeholder auto )

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.

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 auto:

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)

[edit] 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)
1) A type template parameter with an optional name.
2) Exactly the same as 1).
3) A type template parameter with an optional name and a default.
4) A type template parameter pack with an optional name.

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.

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

Unlike type template parameter declaration, template template parameter declaration can only use the keyword class and not typename.

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

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

[edit] Template non-type arguments

The following limitations apply when instantiating templates that have non-type template parameters:

  • For integral and arithmetic types, the template argument provided during instantiation must be a converted constant expression of the template parameter's type (so certain implicit conversion applies).
  • For pointers to objects, the template arguments have to designate the address of an object with static storage duration and a linkage (either internal or external), or a constant expression that evaluates to the appropriate null pointer or std::nullptr_t value.
  • For pointers to functions, the valid arguments are pointers to functions with linkage (or constant expressions that evaluate to null pointer values).
  • For lvalue reference parameters, the argument provided at instantiation cannot be a temporary, an unnamed lvalue, or a named lvalue with no linkage (in other words, the argument must have linkage).
  • For pointers to members, the argument has to be a pointer to member expressed as &Class::Member or a constant expression that evaluates to null pointer or std::nullptr_t value.

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

  • a subobject (including non-static class member, base subobject, or array element);
  • a temporary object (including one created during reference initialization);
  • a string literal;
  • the result of typeid;
  • or the predefined variable __func__.
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)

[edit] 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
}

[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.

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. 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

[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.

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

(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)

[edit] Examples

[edit] 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