Las clases, funciones y (desde C ++ 14) las variables pueden tener plantillas. Una plantilla es un fragmento de código con algunos parámetros libres que se convertirán en una clase, función o variable concreta cuando se especifiquen todos los parámetros. Los parámetros pueden ser tipos, valores o plantillas. Una plantilla conocida es std::vector
, que se convierte en un tipo de contenedor concreto cuando se especifica el tipo de elemento, por ejemplo, std::vector<int>
.
template
especificador de nombre anidado simple-template-id ::
La palabra template
es una palabra clave con cinco significados diferentes en el lenguaje C ++, dependiendo del contexto.
Cuando sigue una lista de parámetros de plantilla incluida en <>
, declara una plantilla como una plantilla de clase , una plantilla de función o una especialización parcial de una plantilla existente.
template <class T>
void increment(T& x) { ++x; }
Cuando es seguido por un vacío <>
, declara una especialización explícita (completa) .
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);
}
Cuando sigue una declaración sin <>
, forma una declaración o definición de instanciación explícita .
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
Dentro de una lista de parámetros de plantilla, introduce un parámetro de plantilla de plantilla .
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));
}
// ...
};
Después del operador de resolución de alcance ::
y los operadores de acceso de miembros de clase .
y ->
, especifica que el siguiente nombre es una plantilla.
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
}
};
Antes de C ++ 11, se podría declarar una plantilla con la palabra clave de export
, convirtiéndola en una plantilla exportada . La definición de una plantilla exportada no necesita estar presente en cada unidad de traducción en la que se crea una instancia de la plantilla. Por ejemplo, se suponía que funcionaba lo siguiente:
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
}
Debido a la dificultad de implementación, la palabra clave de export
no era compatible con la mayoría de los compiladores principales. Se eliminó en C ++ 11; ahora, es ilegal utilizar la palabra clave de export
en absoluto. En su lugar, normalmente es necesario definir plantillas en los encabezados (a diferencia de las funciones que no son de plantilla, que generalmente no están definidas en los encabezados). Consulte ¿Por qué las plantillas solo se pueden implementar en el archivo de encabezado?