Namespaces
Variants

Class template

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Class template
Function template
Miscellaneous

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
1) Definición de instanciación explícita
2) Declaración de instanciación explícita

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