Espacios de nombres
Variantes
Acciones

Plantilla de clase

De cppreference.com
< cpp‎ | language

Una plantilla de clase define una familia de clases.

Contenido

[editar] Sintaxis

template < lista-de-parámetros > declaración-de-clase (1)
export template < lista-de-parámetros > declaración-de-clase (2) (eliminado en C++11)

[editar] Explicación

declaración-de-clase - Una declaración de clase. El nombre de clase declarado se vuelve un nombre de plantilla.
lista-de-parámetros - Una lista no vacía separada por comas de los parámetros de plantilla, cada uno de los cuales es o bien un parámetro de no-tipo, un parámetro de tipo, un parámetro de plantilla, o un paquete de parámetros de cualquiera de esos.
export era un modificador opcional que declaraba a la plantilla como exportada (cuando se usaba con una plantilla de clase, declaraba todos sus miembros también como exportados). Los archivos que instanciaban las plantillas exportadas no necesitaban incluir sus definiciones: su declaración era suficiente. Las implementaciones de export eran raras y estaban en desacuerdo entre sí en los detalles. (hasta C++11)

[editar] Instanciación de plantilla de clase

Una plantilla de clase no es un tipo en sí misma, un objeto, o cualquier otra entidad. No se genera ningún código de un archivo fuente que contiene solamente definiciones de plantillas. Para que cualquier código pueda aparecer, una plantilla debe ser instanciada: se deben proporcionar los argumentos de plantilla para que el compilador pueda generar una clase real (o función, de una plantilla de función).

[editar] Instanciación explícita

template clave-de-clase nombre-de-plantilla < lista-de-argumentos > ; (1)
extern template clave-de-clase nombre-de-plantilla < lista-de-argumentos > ; (2) (desde C++11)
clave-de-clase - 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, estructura o unión a la que se refieren. Puede aparecer en el programa en cualquier lugar después de la definición de la plantilla, y, para una lista-de-argumentos dada, solamente se permite que aparezca una vez en todo el programa, no se requiere diagnóstico.

Una declaración de instanciación explícita (una plantilla externa) se salta el paso de instanciación implícita: el código que, de otra forma, causaría una instanciación implícita, usa en su lugar la definición de instanciación explícita proporcionada en otro lado (lo que genera errores de enlace si no existe tal instanciación). Esto se puede usar para reducir los tiempos de compilación, al declarar explícitamente la instanciación de una plantilla en todos los archivos fuente, excepto uno, y al definirla explícitamente en este archivo restante.

(desde C++11)


Las clases, las funciones, las variables (desde C++14) y las especializaciones de plantilla de miembros se pueden instanciar explícitamente desde sus plantillas. Las funciones miembro, las clases miembro y los miembros de datos estáticos de las plantillas de clase se pueden instanciar explícitamente a partir de sus definiciones de miembro.

La instanciación explícita solamente puede aparecer en el espacio de nombres de la plantilla, a menos que use un id-calificado:

namespace N 
{
    template<class T> 
    class Y // definición de plantilla
    { 
        void mf() { } 
    }; 
}
 
// template class Y<int>;         // ERROR: la plantilla de clase Y no es 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*>;       // de acuerdo: instanciación explícita
template void N::Y<double>::mf(); // de acuerdo: 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 se requiere que la declaración esté visible cuando se crea una instancia explícita de una plantilla de función, una plantilla de variable, (desde C++14) una función miembro o datos miembro estáticos 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 antes apareciera una especialización explícita con los mismos argumentos de plantilla.

Si una plantilla de función, plantilla de variable, (desde C++14) plantilla de función miembro, o función miembro, o datos miembro estáticos de una plantilla de clase se instancia explícitamente con una definición de instanciación explícita, la definición de plantilla debe estar presente en la misma unidad de traducción.

Cuando una instanciación explícita denomina 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 se ha especializado previamente 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 se han definido en este punto.

Las definiciones de instanciación explícita ignoran los especificadores de acceso a miembros: los tipos de parámetros y tipos de retorno pueden ser privados (private).

[editar] 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 integridad del tipo afecta al código, y este tipo en particular no se ha 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 use en el programa, no se crea una 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();       // aquí ocurre una instanciación implícita de Z<char> y Z<char>::f().
              // Z<char>::g() nunca se necesita y nunca se instancia: no tiene que definirse

Si se ha declarado una plantilla de clase, pero no se ha definido, en el momento de la instanciación la instancia produce un tipo de clase incompleta:

template<class T> 
class X;      // declaración, no definición
 
X<char> ch;   // ERROR: tipo incompleto X<char>
Las clases locales y cualquier plantilla utilizada en sus miembros se instancia como parte de la instanciación de la entidad dentro de la cual se declara la clase o enumeración local. (desde C++17)

[editar] Véase también