Templates
suggest changeIntroduction
Classes, functions, and (since C++14) variables can be templated. A template is a piece of code with some free parameters that will become a concrete class, function, or variable when all parameters are specified. Parameters can be types, values, or themselves templates. A well-known template is std::vector
, which becomes a concrete container type when the element type is specified, e.g., std::vector<int>
.
Syntax
template <
template-parameter-list
>
declaration
export template <
template-parameter-list
>
declaration
/* until C++11 */template <>
declaration
template
declaration
extern template
declaration
template <
template-parameter-list
> class …(
opt
)
identifier
(
opt
)
template <
template-parameter-list
> class
identifier
(
opt
) =
id-expression
template <
template-parameter-list
> typename …(
opt
)
identifier
(
opt
)
/* since C++17 */template <
template-parameter-list
> typename
identifier
(
opt
) =
id-expression
/* since C++17 */postfix-expression
. template
id-expression
postfix-expression
-> template
id-expression
nested-name-specifier
template
simple-template-id
::
Remarks
The word template
is a keyword with five different meanings in the C++ language, depending on the context.
- When followed by a list of template parameters enclosed in
<>
, it declares a template such as a class template, a function template, or a partial specialization of an existing template.template <class T> void increment(T& x) { ++x; }
- When followed by an empty
<>
, it declares a an explicit (full) specialization.template <class T> void print(T x); template <> // <-- keyword used in this sense here void print(const char* s) { // output the content of the string printf("%s\n", s); }
- When followed by a declaration without
<>
, it forms an explicit instantiation declaration or definition.template <class T> std::set<T> make_singleton(T x) { return std::set<T>(x); } template std::set<int> make_singleton(int x); // <-- keyword used in this sense here
- Within a template parameter list, it introduces a template template parameter.
template <class T, template <class U> class Alloc> // ^^^^^^^^ keyword used in this sense here class List { struct Node { T value; Node* next; }; Alloc<Node> allocator; Node* allocate_node() { return allocator.allocate(sizeof(T)); } // ... };
- After the scope resolution operator
::
and the class member access operators.
and->
, it specifies that the following name is a template.struct Allocator { template <class T> T* allocate(); }; template <class T, class Alloc> class List { struct Node { T value; Node* next; } Alloc allocator; Node* allocate_node() { // return allocator.allocate<Node>(); // error: < and > are interpreted as // comparison operators return allocator.template allocate<Node>(); // ok; allocate is a template // ^^^^^^^^ keyword used in this sense here } };
Before C++11, a template could be declared with the
export
keyword, making it into an exported template. An exported template’s definition does not need to be present in every translation unit in which the template is instantiated. For example, the following was supposed to work:foo.h
:#ifndef FOO_H #define FOO_H export template <class T> T identity(T x); #endif
foo.cpp
:#include "foo.h" template <class T> T identity(T x) { return x; }
main.cpp
:#include "foo.h" int main() { const int x = identity(42); // x is 42 }
Due to difficulty of implementation, the
export
keyword was not supported by most major compilers. It was removed in C++11; now, it is illegal to use theexport
keyword at all. Instead, it is usually necessary to define templates in headers (in contrast to non-template functions, which are usually not defined in headers). See http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file