Templates

From cppreference.com
< cpplrm; | language

A template is a C++ entity that defines one of the following:

Templates are parametrized by one or more template parameters, of three kinds: type template parameters, non-type template parameters, and template template parameters.

When template arguments are provided, or, for function and class (since C++17) templates only, deduced, they are substituted for the template parameters to obtain a specialization of the template, that is, a specific type or a specific function lvalue. Specializations may also be provided explicitly: full specializations are allowed for both class and function templates, partial specializations are only allowed for class templates.

When a class template specialization is referenced in context that requires a complete object type, or when a function template specialization is referenced in context that requires a function definition to exist, the template is instantiated (the code for it is actually compiled), unless the template was already explicitly specialized or explicitly instantiated. Instantiation of a class template doesn't instantiate any of its member functions unless they are also used. At link time, identical instantiations generated by different translation units are merged.

The definition of a template must be visible at the point of implicit instantiation, which is why template libraries typically provide all template definitions in the headers (e.g. most boost libraries are header-only)

Syntax

template < parameter-list > requires-clause(C++20)(optional) declaration (1)
export template < parameter-list > declaration (2) (until C++11)
template < parameter-list > concept concept-name = constraint-expression ; (3) (since C++20)
declaration - declaration of a class (including struct and union), a member class or member enumeration type, a function or member function, a static data member at namespace scope, a variable or static data member at class scope, (since C++14) or an alias template (since C++11) It may also define a template specialization.
parameter-list - a non-empty comma-separated list of the template parameters, each of which is either non-type parameter, a type parameter, a template parameter, or a parameter pack of any of those.
concept-name
constraint-expression
- see constraints and concepts (since C++20)
export was an optional modifier which declared the template as exported (when used with a class template, it declared all of its members exported as well). Files that instantiated exported templates did not need to include their definitions: the declaration was sufficient. Implementations of export were rare and disagreed with each other on details. (until C++11)

The template parameter list may be followed by an optional requires-clause that specifies the constraints on the template arguments.

(since C++20)

template-id

template-name < parameter-list >
template-name - either an identifier that names a template (in which case this is called "simple-template-id") or a name of an overloaded operator template or user-defined literal template.

A simple-template-id that names a class template specialization names a class.

A template-id that names an alias template specialization names a type.

A template-id that names an function template specialization names a function.

A template-id is only valid if

  • there are at most as many arguments as there are parameters or a parameter is a template parameter pack,
  • there is an argument for each non-deducible non-pack parameter that does not have a default template-argument,
  • each template-argument matches the corresponding template-parameter,
  • substitution of each template argument into the following template parameters (if any) succeeds, and
  • (C++20) if the template-id is non-dependent, the associated constraints are satisfied as specified below.

An invalid simple-template-id is a compile-time error, unless it names a function template specialization (in which case SFINAE may apply).

template<class T, T::type n = 0> class X;
struct S {
  using type = int;
};
using T1 = X<S, int, int>; // error: too many arguments
using T2 = X<>;            // error: no default argument for first template parameter
using T3 = X<1>;           // error: value 1 does not match type-parameter
using T4 = X<int>;         // error: substitution failure for second template parameter
using T5 = X<S>;           // OK

When the template-name of a simple-template-id names a constrained non-function template or a constrained template template-parameter, but not a member template that is a member of an unknown specialization, and all template-arguments in the simple-template-id are non-dependent, the associated constraints of the constrained template must be satisfied:

template<typename T> concept C1 = sizeof(T) != sizeof(int);

template<C1 T> struct S1 { };
template<C1 T> using Ptr = T*;

S1<int>* p;                         // error: constraints not satisfied
Ptr<int> p;                         // error: constraints not satisfied

template<typename T>
struct S2 { Ptr<int> x; };          // error, no diagnostic required

template<typename T>
struct S3 { Ptr<T> x; };            // OK, satisfaction is not required

S3<int> x;                          // error: constraints not satisfied

template<template<C1 T> class X>
struct S4 {
  X<int> x;                         // error, no diagnostic required
};

template<typename T> concept C2 = sizeof(T) == 1;

template<C2 T> struct S { };

template struct S<char[2]>;         // error: constraints not satisfied
template<> struct S<char[2]> { };   // error: constraints not satisfied
(since C++20)

Templated entity

A templated entity (or, in some sources, "temploid") is any entity that is defined (or, for a lambda-expression, created) within a template definition. All of the following are templated entities:

  • a class/function/variable template
  • a member of a templated entity (such as a non-template member function of a class template)
  • an enumerator of an enumeration that is a templated entity
  • any entity defined or created within a templated entity: a local class, a local variable, a friend function, etc
  • the closure type of a lambda expression that appears in the declaration of a templated entity

For example, in:

template<typename T> struct A { void f() {} };

the function A::f is not a function template, but is still considered to be templated.