Plantillas C ++
Las plantillas son la base de la programación genérica, que implica escribir código de una manera que es independiente de cualquier tipo en particular.
Una plantilla es un plan o fórmula para crear una clase o función genérica. Los contenedores de biblioteca como iteradores y algoritmos son ejemplos de programación genérica y se han desarrollado utilizando el concepto de plantilla.
Hay una única definición de cada contenedor, como vector, pero podemos definir muchos tipos diferentes de vectores, por ejemplo, vector <int> o vector <string>.
Puede usar plantillas para definir funciones y clases, veamos cómo funcionan.
Plantilla de función
La forma general de una definición de función de plantilla se muestra aquí:
template <class type> ret-type func-name(parameter list) {
// body of function
}
Aquí, el tipo es un nombre de marcador de posición para un tipo de datos utilizado por la función. Este nombre se puede utilizar dentro de la definición de función.
El siguiente es el ejemplo de una plantilla de función que devuelve el máximo de dos valores:
#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;
}
Si compilamos y ejecutamos el código anterior, esto produciría el siguiente resultado:
Max(i, j): 39
Max(f1, f2): 20.7
Max(s1, s2): World
Plantilla de clase
Así como podemos definir plantillas de funciones, también podemos definir plantillas de clases. La forma general de una declaración de clase genérica se muestra aquí:
template <class type> class class-name {
.
.
.
}
Aquí, typees el nombre del tipo de marcador de posición, que se especificará cuando se cree una instancia de una clase. Puede definir más de un tipo de datos genérico utilizando una lista separada por comas.
A continuación se muestra el ejemplo para definir la clase Stack <> e implementar métodos genéricos para empujar y extraer los elementos de la pila:
#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <stdexcept>
using namespace std;
template <class T>
class Stack {
private:
vector<T> elems; // elements
public:
void push(T const&); // push element
void pop(); // pop element
T top() const; // return top element
bool empty() const { // return true if empty.
return elems.empty();
}
};
template <class T>
void Stack<T>::push (T const& elem) {
// append copy of passed element
elems.push_back(elem);
}
template <class T>
void Stack<T>::pop () {
if (elems.empty()) {
throw out_of_range("Stack<>::pop(): empty stack");
}
// remove last element
elems.pop_back();
}
template <class T>
T Stack<T>::top () const {
if (elems.empty()) {
throw out_of_range("Stack<>::top(): empty stack");
}
// return copy of last element
return elems.back();
}
int main() {
try {
Stack<int> intStack; // stack of ints
Stack<string> stringStack; // stack of strings
// manipulate int stack
intStack.push(7);
cout << intStack.top() <<endl;
// manipulate string stack
stringStack.push("hello");
cout << stringStack.top() << std::endl;
stringStack.pop();
stringStack.pop();
} catch (exception const& ex) {
cerr << "Exception: " << ex.what() <<endl;
return -1;
}
}
Si compilamos y ejecutamos el código anterior, esto produciría el siguiente resultado:
7
hello
Exception: Stack<>::pop(): empty stack