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 one of

  • non-type template parameter
  • type template parameter
  • 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)
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

type is one of the following types (optionally cv-qualified, the qualifiers are ignored)

  • integral type
  • enumeration
  • pointer to object or to function
  • lvalue reference to object or to function
  • pointer to member object or to member function
  • std::nullptr_t (since C++11)

Array and function types may be written in a template declaration, but they are automatically replaced by pointer to data 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.

[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<class T> class myarray {};
 
// two type template parameters and one template template parameter:
template<class K, class V, template<typename> class C = myarray>
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 or defaulted. For function templates, the arguments are explicitly provided, defaulted, or deduced from context.

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

[edit] Template type arguments

A template argument for a type template parameter must be a type-id, which may name an incomplete type:

template <class 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<class T> class A { // primary template
    int x;
};
template<class T> class A<T*> { // partial specialization
    long x;
};
 
// 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<class T> struct eval; // primary template 
 
template< template<class, class...> class TT, class T1, class... Rest>
struct eval<TT<T1, Rest...>> {}; // partial specialization of eval
 
template <class T1> struct A;
template <class T1, class T2> struct B;
template <int N> struct C;
template <class T1, int N> struct D;
template <class T1, class 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, 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

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 and the definition are merged similarly to default function arguments:

template<class T1, class T2 = int> class A;
template<class T1 = int, class T2> class A;
// the above is the same as the following:
template<class T1 = int, class T2 = int> class A;

But the same parameter cannot be given default arguments twice in the same scope

template<class T = int> class X;
template<class 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 <class T = float> struct B {};
 
// template template parameter T has a parameter list, which 
// consists of one type template parameter with a default
template <template <class = float> class T> struct A {
    void f();
    void g();
};
// out-of-body member function template definitions
template <template <class TT> class T>
void A<T>::f() {
    T<> t; // error - TT has no default in scope
}
template <template <class 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 <class T> class C {
 protected:
    typedef T TT;
};
 
template <class U, class V = typename U::TT>
class D : public U {};
 
D<C<B>>* d; // access error, C::TT is protected


[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