Class template
Una plantilla de clase define una familia de clases.
Contenidos |
Sintaxis
template
<
lista-de-parámetros
>
declaración-de-clase
|
(1) | ||||||||
template
<
lista-de-parámetros
>
requires
restricción
declaración-de-clase
|
(2) | (desde C++20) | |||||||
export
template
<
lista-de-parámetros
>
declaración-de-clase
|
(3) | (eliminado en C++11) | |||||||
Explicación
| class-declaration | - | una declaración de clase . El nombre de clase declarado se convierte en un nombre de plantilla. |
| parameter-list | - | una lista no vacía separada por comas de los parámetros de plantilla , cada uno de los cuales es un parámetro constante , un parámetro de tipo , un parámetro de plantilla , o un paquete de parámetros de cualquiera de esos. |
| constraint | - | una expresión de restricción que restringe los parámetros de plantilla aceptados por esta plantilla de clase |
export
era un modificador opcional que declaraba la plantilla como
exportada
(cuando se usaba con una plantilla de clase, declaraba todos sus miembros también como exportados). Los archivos que instanciaban plantillas exportadas no necesitaban incluir sus definiciones: la declaración era suficiente. Las implementaciones de
export
eran raras y discrepaban entre sí en los detalles.
|
(hasta C++11) |
Instanciación de plantilla de clase
Una plantilla de clase por sí misma no es un tipo, ni un objeto, ni ninguna otra entidad. No se genera código desde un archivo fuente que contiene solo definiciones de plantillas. Para que aparezca cualquier código, una plantilla debe ser instanciada: se deben proporcionar los argumentos de la plantilla para que el compilador pueda generar una clase real (o función, a partir de una plantilla de función).
Instanciación explícita
template
class-key
template-name
<
argument-list
>
;
|
(1) | ||||||||
extern
template
class-key
template-name
<
argument-list
>
;
|
(2) | (desde C++11) | |||||||
| class-key | - |
class
,
struct
o
union
|
Una definición de instanciación explícita fuerza la instanciación de la clase, struct o unión a la que se refiere. Puede aparecer en cualquier parte del programa después de la definición de la plantilla, y para una argument-list dada, solo se permite que aparezca una vez en todo el programa, sin requerirse diagnóstico.
|
Una declaración de instanciación explícita (una plantilla externa) omite el paso de instanciación implícita: el código que normalmente causaría una instanciación implícita en su lugar utiliza la definición de instanciación explícita proporcionada en otro lugar (resultando en errores de enlace si no existe dicha instanciación). Esto puede utilizarse para reducir los tiempos de compilación declarando explícitamente una instanciación de plantilla en todos los archivos fuente que la utilizan excepto uno, y definiéndola explícitamente en el archivo restante. |
(desde C++11) |
Las clases, funciones , variables (since C++14) , y especializaciones de plantillas miembro pueden ser instanciadas explícitamente desde sus plantillas. Las funciones miembro, clases miembro y miembros de datos estáticos de plantillas de clase pueden ser instanciados explícitamente desde sus definiciones de miembro.
La instanciación explícita solo puede aparecer en el espacio de nombres que contiene la plantilla, a menos que se utilice un identificador calificado:
namespace N { template<class T> class Y // definición de plantilla { void mf() {} }; } // template class Y<int>; // error: plantilla de clase Y no visible en el espacio de nombres global using N::Y; // template class Y<int>; // error: instanciación explícita fuera // del espacio de nombres de la plantilla template class N::Y<char*>; // OK: instanciación explícita template void N::Y<double>::mf(); // OK: instanciación explícita
La instanciación explícita no tiene efecto si una especialización explícita apareció antes para el mismo conjunto de argumentos de plantilla.
Solo la declaración debe ser visible al instanciar explícitamente una plantilla de función , una plantilla de variable (since C++14) , una función miembro o miembro de datos estático de una plantilla de clase, o una plantilla de función miembro. La definición completa debe aparecer antes de la instanciación explícita de una plantilla de clase, una clase miembro de una plantilla de clase, o una plantilla de clase miembro, a menos que una especialización explícita con los mismos argumentos de plantilla haya aparecido antes.
Si una plantilla de función , plantilla de variable (since C++14) , plantilla de función miembro, o función miembro o miembro de datos estático de una plantilla de clase se instancia explícitamente con una definición de instanciación explícita, la definición de la plantilla debe estar presente en la misma unidad de traducción.
Cuando una instanciación explícita nombra una especialización de plantilla de clase, sirve como una instanciación explícita del mismo tipo (declaración o definición) de cada uno de sus miembros no heredados no plantilla que no haya sido previamente especializado explícitamente en la unidad de traducción. Si esta instanciación explícita es una definición, también es una definición de instanciación explícita solo para los miembros que han sido definidos en este punto.
Las definiciones de instanciación explícita ignoran los especificadores de acceso de miembros: los tipos de parámetros y los tipos de retorno pueden ser privados.
Instanciación implícita
Cuando el código se refiere a una plantilla en un contexto que requiere un tipo completamente definido, o cuando la completitud del tipo afecta al código, y este tipo particular no ha sido instanciado explícitamente, ocurre una instanciación implícita. Por ejemplo, cuando se construye un objeto de este tipo, pero no cuando se construye un puntero a este tipo.
Esto se aplica a los miembros de la plantilla de clase: a menos que el miembro se utilice en el programa, no se instancia y no requiere una definición.
template<class T> struct Z // definición de plantilla { void f() {} void g(); // nunca definido }; template struct Z<double>; // instanciación explícita de Z<double> Z<int> a; // instanciación implícita de Z<int> Z<char>* p; // aquí no se instancia nada p->f(); // la instanciación implícita de Z<char> y Z<char>::f() ocurre aquí. // Z<char>::g() nunca se necesita y nunca se instancia: // no necesita estar definida
Si una plantilla de clase ha sido declarada, pero no definida, en el punto de instanciación, la instanciación produce un tipo de clase incompleto:
template<class T> class X; // declaración, no definición X<char> ch; // error: tipo incompleto X<char>
| Clases locales y cualquier plantilla utilizada en sus miembros se instancian como parte de la instanciación de la entidad dentro de la cual se declara la clase o enumeración local. | (desde C++17) |
Palabras clave
export (hasta C++11) extern (desde C++11)
Véase también
- parámetros y argumentos de plantilla permiten parametrizar plantillas
- declaración de plantilla de función declara una plantilla de función
- especialización de plantilla define una plantilla existente para un tipo específico
- paquetes de parámetros permiten el uso de listas de tipos en plantillas (desde C++11)