Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A template template parameter is a template parameter that acts as a placeholder expecting an uninstantiated class template or alias template as its argument. It allows a host template to receive a template rather than a fully instantiated type, granting the host template the authority to instantiate the provided template internally using types, non-type parameters, or other templates of its own choosing.

Syntax

The declaration of a template template parameter requires its own nested template parameter list. This nested list defines the exact signature (arity and parameter kinds) of the templates that can be passed as arguments.
// 'TemplateParam' is a template template parameter expecting a template with exactly one type parameter.
template <template <typename U> class TemplateParam>
class HostTemplate {
    // Instantiating the template parameter internally
    TemplateParam<int> int_instance;
    TemplateParam<double> double_instance;
};
Note: Prior to C++17, the keyword class was strictly required to declare a template template parameter. Since C++17, typename is also permitted and functionally identical in this context:
// C++17 syntax
template <template <typename U> typename TemplateParam>
class HostTemplate;

Parameter Matching Rules

When passing a template argument to a template template parameter, the compiler enforces matching rules between the nested parameter list and the provided template. Pre-C++17 (Strict Matching): The parameter list of the argument template must exactly match the parameter list of the template template parameter. Default template arguments in the argument template are ignored during this evaluation.
#include <memory>

template <template <typename> class T> 
struct Host {};

template <typename U, typename Alloc = std::allocator<U>> 
struct Container {};

// ERROR in C++14: Container has two parameters (even though one has a default), 
// but Host expects a template with exactly one parameter.
Host<Container> h1; 
C++17 and Later (Relaxed Matching): The matching rules were relaxed (P0522R0). A template argument A is considered a valid match for a template template parameter P if P is at least as specialized as A. Because the parameter template <typename> class is more specialized than the argument template <typename, typename> class, and the extra parameters in the argument have default values, the match succeeds.
// VALID in C++17: The compiler recognizes that Container can be 
// instantiated with a single type argument due to the default allocator.
Host<Container> h2; 

Variadic Template Template Parameters

Template template parameters can be variadic. A variadic template template parameter specifically expects a variadic template as its argument (a template that takes zero or more parameters). It will strictly reject fixed-arity templates, even if the fixed arity falls within the “zero or more” conceptual range.
// Accepts only variadic templates
template <template <typename...> class VariadicTemplateParam>
class HostTemplate {
    VariadicTemplateParam<int> single_arg;
    VariadicTemplateParam<int, float, char> multi_arg;
};

template <typename... Types> struct VariadicContainer {};
template <typename T> struct SingleContainer {};

HostTemplate<VariadicContainer> valid_host; // OK
// HostTemplate<SingleContainer> invalid_host; // ERROR: SingleContainer is not variadic

Mixing Parameter Kinds

The nested parameter list of a template template parameter can include type parameters, non-type template parameters (NTTPs), and even other template template parameters, dictating a highly specific signature.
#include <cstddef>

// Expects a template that takes a type and a non-type parameter of type std::size_t
template <template <typename T, std::size_t N> class ArrayLike>
class HostTemplate {
    ArrayLike<int, 10> buffer;
};

Restrictions

  1. Class and Alias Templates Only: Only class templates and alias templates can be passed as arguments to a template template parameter. Function templates and variable templates are strictly prohibited.
  2. Nested Parameter Names: The names of the parameters within the nested template parameter list (e.g., U in template <typename U> class) cannot be referenced within the body of the host template. While they are often omitted for simple type parameters, they are strictly required if a subsequent parameter in the nested list depends on a previous one.
// 'T' is strictly required here because the non-type parameter 'Value' depends on it.
template <template <typename T, T Value> class DependentParam>
class HostTemplate;
Master C++ with Deep Grasping Methodology!Learn More