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>
.
template
simple-template-id ::
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 the export
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 Why can templates only be implemented in the header file?