Espacios de nombres
Variantes
Acciones

Plantillas

De cppreference.com
< cpp‎ | language

Una plantilla es una entidad de C++ que define uno de los siguientes:

Las plantillas están parametrizadas por uno o más parámetros de plantilla de tres tipos: parámetros de plantilla de tipo, parámetros de plantilla de no tipo, y parámetros de plantilla de plantilla.

Cuando se proporcionan argumentos de plantilla, o, solamente para plantillas de función y de clase (desde C++17), deducidos, se sustituyen por los parámetros de plantilla para obener una especialización de la plantilla, es decir, un tipo específico o un lvalue de función específico. Las especializaciones también pueden proporcionarse explícitamente: se permiten las especializaciones totales tanto para plantillas de clase como para plantillas de función, las especializaciones parciales solamente se permiten para plantillas de clase.

Cuando se hace referencia a una especialización de plantilla de clase en un contexto que requiere un tipo de objeto completo, o cuando se hace referencia a una especialización de plantilla de función que requiera que exista una definición de función, la plantilla es instanciada (de hecho se compila el código para ella), a menos que la plantilla ya haya sido especializada explícitamente o se haya instanciado explícitamente. La instanciación de una plantilla de clase no instancia ninguna de sus funciones miembro a menos que también se usen. En tiempo de enlace, las instanciaciones idénticas generadas por distintas unidades de traducción se fusionan.

La definición de una plantilla debe de ser visible en el punto de la instanciación implícita, que es la razón por la que las bibliotecas de plantilla proporcionan todas sus definiciones de plantilla en los archivos de encabezado (p.ej., la mayoría de las bibliotecas de Boost son de encabezado solamente).

[editar] Sintaxis

template < lista-de-parámetros > cláusula-requiere(C++20)(opcional) declaración (1)
export template < lista-de-parámetros > declaración (2) (hasta C++11)
template < lista-de-parámetros > concept nombre-de-concepto = expresión-restrictiva ; (3) (desde C++20)
declaración - Declaración de una clase (incluyendo estructura y unión), una clase miembro o tipo de enumeración miembro, una función o función miembro, un dato miembro estático en ámbito de espacio de nombres, una variable o dato miembro estático en ámbito de clase, (desde C++14) o una plantilla de alias (desde C++11). También puede definir una especialización de plantilla.
lista-de-parámetros - Una lista no vacía, separada por comas, de parámetros de plantilla, cada uno de los cuales es ya sea 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.
nombre-de-concepto
expresión-restrictiva
- Véase restricciones y conceptos (desde C++20)
export era un modificador opcional que declaraba la plantilla como exportada (cuando se usaba con una plantilla de clase, también declaraba que todos sus miembros se exportaban). Los archivos que instanciaban plantillas exportadas no necesitaban incluir sus definiciones: la declaración era suficiente. Las implementaciones de export fueron raras y no estuvieron de acuerdo entre sí en los detalles. (hasta C++11)

La lista de parámetros de plantilla puede ser seguida por una cláusula opcional cláusula-requiere que especifica las restricciones sobre los argumentos de plantilla.

(desde C++20)

[editar] id-de-plantilla

nombre-de-plantilla < lista-de-parámetros >
nombre-de-plantilla - ya sea un identificador que nombra a una plantilla (en cuyo caso esto se llama "id-de-plantilla-simple") o un nombre de un operador de plantilla sobrecargado o una plantilla de literal definida por el usuario.

Un id-de-plantilla-simple que nombra a una especialización de plantilla de clase nombra a una clase.

Un id-de-plantilla que nombra a una especialización de plantilla de alias nombra a un tipo.

Un id-de-plantilla que nombra a una especialización de plantilla de función nombra a una función.

Un id-de-plantilla es solamente valido si

  • hay como máximo tantos argumentos como parámetros o un parámetro es un paquete de parámetros de plantilla;
  • hay un argumento para cada parámetro que no es de paquete, no deducible, que no tiene un argumento de plantilla por defecto;
  • cada argumento de plantilla coincide con el parámetro de plantilla correspondiente;
  • la sustitución de cada argumento de plantilla en los siguientes parámetros de plantilla (si los hay) tiene éxito, y
  • (C++20) si el id-de-plantilla no es dependiente, las restricciones asociadas se satisfacen como se especifica a continuación.

Un id-de-plantilla-simple inválido es un error en tiempo de compilación, a menos de que nombre a una especialización de plantilla de función (en cuyo caso puede aplicarse SFINAE).

template<typename T, T::type n = 0> class X;
struct S {
  using type = int;
};
using T1 = X<S, int, int>; // ERROR: demasiados argumentos
using T2 = X<>;            // ERROR: no hay argumento por defecto para el primer parámetro de plantilla
using T3 = X<1>;           // ERROR: valor 1 no coincide con el parámetro de tipo
using T4 = X<int>;         // ERROR: falla en la sustitución para el segundo parámetro de plantilla
using T5 = X<S>;           // de acuerdo

Cuando el nombre de plantilla de un id-de-plantilla-simple nombra una plantilla restringida que no es plantilla de función, o un parámetro de plantilla de plantilla, pero no una plantilla miembro que es miembro de una especialización desconocida, y todos los argumentos de plantilla en el id-de-plantilla-simple no son dependientes, las restricciones asociadas con la plantilla restringida deben satisfacerse:

template<typename T> concept C1 = sizeof(T) != sizeof(int);
 
template<C1 T> struct S1 { };
template<C1 T> using Ptr = T*;
 
S1<int>* p;                         // ERROR: restricciones no se satisfacen
Ptr<int> p;                         // ERROR: restricciones no se satisfacen
 
template<typename T>
struct S2 { Ptr<int> x; };          // ERROR, no se requiere diagnóstico
 
template<typename T>
struct S3 { Ptr<T> x; };            // de acuerdo, no se requiere que se satisfagan
                                    // restricciones
 
S3<int> x;                          // ERROR: restricciones no se satisfacen
 
template<template<C1 T> class X>
struct S4 {
  X<int> x;                         // ERROR, no se requiere diagnóstico
};
 
template<typename T> concept C2 = sizeof(T) == 1;
 
template<C2 T> struct S { };
 
template struct S<char[2]>;         // ERROR: restricciones no se satisfacen
template<> struct S<char[2]> { };   // ERROR: restricciones no se satisfacen
(desde C++20)

[editar] Entidad emplantillada

Una entidad emplantillada (o, en algunas fuentes, temploid) es una entidad que está definida (o, para una expresión lambda, creada) dentro de una definición de plantilla. Todas las siguientes son entidades emplantilladas:

  • una plantilla de clase/función /variable (desde C++14);
  • un concepto; (desde C++20)
  • un miembro de una entidad emplantillada (tal como un función miembro que no es una plantilla, de una plantilla de clase);
  • un enumerador de una enumeración que es una entidad emplantillada;
  • una entidad definida o creada dentro de una entidad emplantillada: una clase local, una variable local, una función amiga (friend), etc.;
  • el tipo de cierre (closure) de una expresión lambda que aparece en la declaración de una entidad emplantillada.

Por ejemplo, en:

template<typename T> struct A { void f() {} };

la función A::f no es una plantilla de función, pero todavía se considera que es emplantillada.