Namespaces
Variants

Templates

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
Miscellaneous

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

(desde C++11)
(desde C++14)
(desde C++20)

Las plantillas son parametrizadas por uno o más template parameters , de tres tipos: type template parameters, constant template parameters, y template template parameters.

Cuando se proporcionan argumentos de plantilla, o, para function and class (since C++17) templates only, deduced, se sustituyen por los parámetros de plantilla para obtener 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: full specializations están permitidas para class , variable (since C++14) y function templates, partial specializations están permitidas únicamente para class templates y variable templates (since C++14) .

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

La definición de una plantilla de clase debe ser visible en el punto de instanciación implícita, por lo que las bibliotecas de plantillas normalmente proporcionan todas las definiciones de plantillas en los encabezados (por ejemplo, la mayoría de las bibliotecas de boost son solo de encabezado ).

Contenidos

Sintaxis

template < lista-de-parámetros  > cláusula-requires  (opcional) declaración (1)
export template < lista-de-parámetros  > declaración (2) (hasta C++11)
template < lista-de-parámetros  > concept nombre-del-concepto = expresión-de-restricción  ; (3) (desde C++20)
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 estos (desde C++11) .
requires-clause - (desde C++20) una cláusula requires que especifica las restricciones sobre los argumentos de plantilla.
declaration - declaración de una clase (incluyendo struct y union) , una clase miembro o tipo de enumeración miembro , una función o función miembro , un miembro de datos estático en el ámbito del espacio de nombres , una variable o miembro de datos estático en el ámbito de clase (desde C++14) , o un alias de plantilla (desde C++11) . También puede definir una especialización de plantilla .
concept-name
constraint-expression
- ver restricciones y conceptos

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)

Identificadores de plantilla

Un identificador de plantilla tiene una de las siguientes sintaxis:

template-name  < template-argument-list  (opcional) > (1)
operator op  < template-argument-list  (opcional) > (2)
operator "" identifier < template-argument-list  (opcional) > (3) (desde C++11)
(obsoleto)
operator user-defined-string-literal < template-argument-list  (opcional) > (4) (desde C++11)
1) Un identificador de plantilla simple .
2) Un identificador de plantilla de función de operador.
3,4) Un identificador de plantilla de función de literal operator .
template-name - un identificador que nombra una plantilla
op - un operador sobrecargable
identifier - un identificador
user-defined-string-literal - "" seguido de un identificador


Un identificador de plantilla simple que nombra una especialización de plantilla de clase nombra una clase.

Un identificador de plantilla que nombra una especialización de plantilla de alias nombra un tipo.

Un identificador de plantilla que nombra una especialización de plantilla de función nombra una función.

Si se cumplen todas las siguientes condiciones, un identificador de plantilla es válido :

  • Hay como máximo tantos argumentos como parámetros o un parámetro es un parameter pack (since C++11) .
  • Hay un argumento para cada parámetro no deducible non-pack (since C++11) que no tiene un argumento de plantilla predeterminado.
  • 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.
  • Si el identificador de plantilla es no dependiente , las restricciones asociadas se satisfacen como se especifica a continuación.
(desde C++20)

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

template<class 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 predeterminado para el primer parámetro de plantilla
using T3 = X<1>;           // error: el valor 1 no coincide con el parámetro de tipo
using T4 = X<int>;         // error: fallo de sustitución para el segundo parámetro de plantilla
using T5 = X<S>;           // OK

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

template<typename T>
concept C1 = sizeof(T) != sizeof(int);
template<C1 T>
struct S1 {};
template<C1 T>
using Ptr = T*;
S1<int>* p;                      // error: constraints not satisfied
Ptr<int> p;                      // error: constraints not satisfied
template<typename T>
struct S2 { Ptr<int> x; };       // error, no diagnostic required
template<typename T>
struct S3 { Ptr<T> x; };         // OK, satisfaction is not required
S3<int> x;                       // error: constraints not satisfied
template<template<C1 T> class X>
struct S4
{
    X<int> x;                    // error, no diagnostic required
};
template<typename T>
concept C2 = sizeof(T) == 1;
template<C2 T> struct S {};
template struct S<char[2]>;      // error: constraints not satisfied
template<> struct S<char[2]> {}; // error: constraints not satisfied
(desde C++20)

Si se cumplen todas las siguientes condiciones, dos identificadores de plantilla son same :

  • Sus template-name s u operadores se refieren a la misma plantilla.
  • Sus argumentos de plantilla de tipo correspondientes son del mismo tipo.
  • Los valores de parámetros de plantilla determinados por sus argumentos de plantilla constantes correspondientes son template-argument-equivalent .
  • Sus argumentos de plantilla de plantilla correspondientes se refieren a la misma plantilla.

Dos identificadores de plantilla que son iguales se refieren a la misma variable, (since C++14) clase o función.

Entidad con plantilla

Una entidad plantillada (o, en algunas fuentes, "temploid") es cualquier entidad que se define (o, para una expresión lambda , se crea) (desde C++11) dentro de una definición de plantilla. Todas las siguientes son entidades plantilladas:

  • una clase/función /variable (desde C++14) plantilla
(desde C++20)
  • un miembro de una entidad con plantilla (como una función miembro no plantilla de una clase con plantilla)
  • un enumerador de una enumeración que es una entidad con plantilla
  • cualquier entidad definida o creada dentro de una entidad con plantilla: una clase local, una variable local, una función amiga, etc
  • el tipo de clausura de una expresión lambda que aparece en la declaración de una entidad templada
(since C++11)

Por ejemplo, en

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

la función A::f no es una plantilla de función, pero aún se considera que está parametrizada.


Una función con plantilla es una plantilla de función o una función que tiene plantilla.

Una clase con plantilla es una plantilla de clase o una clase que tiene plantilla.

Una variable con plantilla es una variable de plantilla o una variable que tiene plantilla.

(since C++14)

Palabras clave

template , export

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
CWG 2293 C++98 no se proporcionaron las reglas para determinar si un
identificador de plantilla es válido
proporcionado
CWG 2682 C++98
C++14
faltaban las definiciones de función plantilla/clase plantilla
(C++98)/variable plantilla (C++14)
añadido
P2308R1 C++98 dos identificadores de plantilla eran diferentes si sus
argumentos de plantilla constantes correspondientes
no son equivalentes-como-argumento-de-plantilla
son diferentes si sus valores de parámetro
de plantilla constante correspondientes
no son equivalentes-como-argumento-de-plantilla

Véase también

Documentación de C para Generic selection