Looking for c++ Answers? Try Ask4KnowledgeBase
Looking for c++ Keywords? Try Ask4Keywords

C++Plantillas


Introducción

Las clases, funciones y (desde C ++ 14) las variables pueden tener plantillas. Una plantilla es un fragmento de código con algunos parámetros libres que se convertirán en una clase, función o variable concreta cuando se especifiquen todos los parámetros. Los parámetros pueden ser tipos, valores o plantillas. Una plantilla conocida es std::vector , que se convierte en un tipo de contenedor concreto cuando se especifica el tipo de elemento, por ejemplo, std::vector<int> .

Sintaxis

  • declaración de plantilla < plantilla-lista-parámetros >
  • exportar plantilla < lista de parámetros de plantilla > declaración / * hasta C ++ 11 * /
  • plantilla <> declaración
  • declaración de plantilla
  • Declaración de plantilla externa / * desde C ++ 11 * /
  • plantilla < plantilla-lista-parámetros > clase ... ( opt ) identificador ( opt )
  • plantilla < plantilla-lista-parámetros > identificador de clase ( opt ) = id-expresión
  • template < template-parameters-list > typename ... ( opt ) identifier ( opt ) / * desde C ++ 17 * /
  • plantilla < plantilla-lista-parámetros > identificador de nombre de tipo ( opt ) = id-expresión / * desde C ++ 17 * /
  • postfix-expresión . expresión- plantilla de la plantilla
  • postfix-expresión -> plantilla id-expresión
  • template especificador de nombre anidado simple-template-id ::

Observaciones

La palabra template es una palabra clave con cinco significados diferentes en el lenguaje C ++, dependiendo del contexto.

  1. Cuando sigue una lista de parámetros de plantilla incluida en <> , declara una plantilla como una plantilla de clase , una plantilla de función o una especialización parcial de una plantilla existente.

    template <class T>
    void increment(T& x) { ++x; }
    
  2. Cuando es seguido por un vacío <> , declara una especialización explícita (completa) .

    template <class T>
    void print(T x);
    
    template <> // <-- keyword used in this sense here
    void print(const char* s) {
        // output the content of the string
        printf("%s\n", s);
    }
    
  3. Cuando sigue una declaración sin <> , forma una declaración o definición de instanciación explícita .

    template <class T>
    std::set<T> make_singleton(T x) { return std::set<T>(x); }
    
    template std::set<int> make_singleton(int x); // <-- keyword used in this sense here
    
  4. Dentro de una lista de parámetros de plantilla, introduce un parámetro de plantilla de plantilla .

    template <class T, template <class U> class Alloc>
    //                 ^^^^^^^^ keyword used in this sense here
    class List {
        struct Node {
            T value;
            Node* next;
        };
        Alloc<Node> allocator;
        Node* allocate_node() {
            return allocator.allocate(sizeof(T));
        }
        // ...
    };
    
  5. Después del operador de resolución de alcance :: y los operadores de acceso de miembros de clase . y -> , especifica que el siguiente nombre es una plantilla.

    struct Allocator {
        template <class T>
        T* allocate();
    };
    
    template <class T, class Alloc>
    class List {
        struct Node {
            T value;
            Node* next;
        }
        Alloc allocator;
        Node* allocate_node() {
            // return allocator.allocate<Node>();       // error: < and > are interpreted as
                                                        // comparison operators
            return allocator.template allocate<Node>(); // ok; allocate is a template
            //               ^^^^^^^^ keyword used in this sense here
        }
    };
    

Antes de C ++ 11, se podría declarar una plantilla con la palabra clave de export , convirtiéndola en una plantilla exportada . La definición de una plantilla exportada no necesita estar presente en cada unidad de traducción en la que se crea una instancia de la plantilla. Por ejemplo, se suponía que funcionaba lo siguiente:

foo.h :

#ifndef FOO_H
#define FOO_H
export template <class T> T identity(T x);
#endif

foo.cpp :

#include "foo.h"
template <class T> T identity(T x) { return x; }

main.cpp :

#include "foo.h"
int main() {
    const int x = identity(42); // x is 42
}

Debido a la dificultad de implementación, la palabra clave de export no era compatible con la mayoría de los compiladores principales. Se eliminó en C ++ 11; ahora, es ilegal utilizar la palabra clave de export en absoluto. En su lugar, normalmente es necesario definir plantillas en los encabezados (a diferencia de las funciones que no son de plantilla, que generalmente no están definidas en los encabezados). Consulte ¿Por qué las plantillas solo se pueden implementar en el archivo de encabezado?

Plantillas Ejemplos relacionados