Templates
Una plantilla es una entidad de C++ que define una de las siguientes:
- una familia de clases ( class template ), que pueden ser nested classes
- una familia de funciones ( function template ), que pueden ser member functions
|
(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) |
|
Esta sección está incompleta
Razón: sintaxis básica, parámetros de plantilla e instanciaciones, tomar contenido común entre class_template y function_template |
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) | |||||||
| 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.
|
(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
|
(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
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
|