C++ Plantillas

Las plantillas son la base de la programación genérica, es decir, escribir código de manera independiente de cualquier tipo específico.

Las plantillas son el modelo o la fórmula para crear clases o funciones genéricas. Los contenedores de bibliotecas, como los iteradores y los algoritmos, son ejemplos de programación genérica y todos utilizan el concepto de plantillas.

Cada contenedor tiene una definición única, comovector, podemos definir vectores de muchos tipos diferentes, comovector <int>ovector <string>。

Puede usar plantillas para definir funciones y clases. A continuación, veamos cómo se usan.

Plantillas de funciones

La forma general de definición de una plantilla de función es la siguiente:

template <typename type> ret-type func-name(parameter list) { // cuerpo de la función }

Aquí, type es el nombre del marcador de posición del tipo de datos que utiliza la función. Este nombre se puede usar en la definición de la función.

El siguiente es un ejemplo de plantilla de función que devuelve el máximo de dos números:

Ejemplo

#include <iostream> #include <string> using namespace std; template <typename T> inline T const& Max (T const& a, T const& b) { return a < b ? b:a; } int main () { int i = 39; int j = 20; cout << "Max(i, j): " << Max(i, j) << endl; double f1 = 13.5; double f2 = 20.7; cout << "Max(f1, f2): " << Max(f1, f2) << endl; string s1 = "Hello"; string s2 = "World"; cout << "Max(s1, s2): " << Max(s1, s2) << endl; return 0; }

Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:

Max(i, j): 39
Max(f1, f2): 20.7
Max(s1, s2): World

Plantillas de clases

Así como definimos plantillas de funciones, también podemos definir plantillas de clases. La forma general de declaración de una clase genérica es la siguiente:

template <class type> class class-name {
.
.
.
}

Aquí,typees el nombre del tipo de marcador de posición, que se puede especificar cuando se instancia la clase. Puede usar una lista separada por comas para definir múltiples tipos de datos genéricos.

El siguiente ejemplo define la clase Stack<> e implementa métodos genéricos para realizar operaciones de push y pop de elementos:

Ejemplo

#include <iostream> #include <vector> #include <cstdlib> #include <string> #include <stdexcept> using namespace std; template <class T> class Stack { private: vector<T> elems; // elemento public: void push(T const&); // push (apilar) void pop(); // pop (desapilar) T top() const; // devuelve el elemento superior de la pila bool empty() const{ // devuelve verdadero si está vacía. return elems.empty(); } }; template <class T> void Stack<T>::push (T const& elem) { // añade una copia del elemento pasado elems.push_back(elem); } template <class T> void Stack<T>::pop () { if (elems.empty()) { throw out_of_range("Stack<>::pop(): empty stack"); } // elimina el último elemento elems.pop_back(); } template <class T> T Stack<T>::top () const { if (elems.empty()) { throw out_of_range("Stack<>::top(): empty stack"); } // devuelve una copia del último elemento return elems.back(); } int main() { try { Stack<int> intStack; // pila de tipo int Stack<string> stringStack; // pila de tipo string // operar la pila de tipo int intStack.push(7); cout << intStack.top() <<endl; // operar la pila de tipo string stringStack.push("hello"); cout << stringStack.top() << std::endl; stringStack.pop(); stringStack.pop(); } catch (exception const& ex) { cerr << "Exception: " << ex.what() <<endl; return -1; } }

Cuando el código anterior se compila y ejecuta, produce el siguiente resultado:

7
hello
Exception: Stack<>::pop(): empty stack
Otras extensiones