Información general de plantillas
Las plantillas, que a veces se denominan tipos parametrizados, son mecanismos para generar funciones y clases sobre la base de parámetros de tipo. Mediante plantillas, puede diseñar una clase o una función única que opera en datos de muchos tipos, en lugar de tener que crear una clase independiente para cada tipo.
Comentarios
Por ejemplo, para crear una función con seguridad de tipos que devuelva el menor de dos parámetros sin utilizar plantillas, escribiría un conjunto de funciones sobrecargadas como esta:
// what_are_templates1.cpp
// compile with: /c
// min for ints
int min( int a, int b ) {
return ( a < b ) ? a : b;
}
// min for longs
long min( long a, long b ) {
return ( a < b ) ? a : b;
}
// min for chars
char min( char a, char b ) {
return ( a < b ) ? a : b;
}
Mediante plantillas, puede reducir esta duplicación a una única plantilla de función:
// what_are_templates2.cpp
// compile with: /c
template <class T> T min( T a, T b ) {
return ( a < b ) ? a : b;
}
Las plantillas pueden reducir significativamente el tamaño del código fuente y aumentar la flexibilidad del código sin reducir la seguridad de tipos.
Hay dos tipos principales de plantillas: plantillas de función y plantillas de clase. En el ejemplo anterior, min es una plantilla de función. Una plantilla de clase es una clase con un parámetro, tal como:
// what_are_templates3.cpp
template <class T> class A {
T m_t;
public:
A(T t): m_t(t) {}
void f(T t);
};
int main() {
A<int> a(10);
}
Las plantillas se declaran y se definen de manera similar a otras funciones y clases, con algunas diferencias importantes. Una declaración de plantilla no define totalmente una función o clase; define solo un esquema sintáctico para una clase o función. Una clase o función real se crea a partir de una plantilla mediante un proceso llamado creación de instancias. Las clases o funciones individuales creadas se conocen como instancias. Por ejemplo, una plantilla de clase:
template <class T> struct A { . . . };
se puede usar para crear instancias de clases para A<int>, A<char>, A<int*>, A<MyClass*> y etc.
La creación de clases o funciones se puede hacer de forma explícita o implícita. La creación explícita de instancias es una manera de indicar en el código qué versiones de la plantilla deben generarse. La creación implícita permite crear instancias de plantillas cuando es necesario en el punto donde se utilizan por primera vez.
Las plantillas también se pueden parametrizar mediante un parámetro de valor, en cuyo caso el parámetro de plantilla se declara como el parámetro para una función. Los tipos de punto flotante y los tipos de clase no se permiten como parámetros de valor.
// what_are_templates4.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
template <int i> class A {
int array[i];
public:
A() { memset(array, 0, i*sizeof(int)); }
};
int main() {
A<10> a;
}
Un problema común con las plantillas es que puede ser una solución única, lo que significa que el mismo código se aplica a todos los tipos. Si necesita personalizar el comportamiento de la plantilla para un tipo determinado, puede utilizar la especialización. Mediante la especialización explícita, se puede especializar una plantilla para un tipo real determinado, no un tipo genérico. Una plantilla de clase también se puede especializar parcialmente, lo que es útil si se tiene una plantilla con varios parámetros de tipo y solo se desea personalizar el comportamiento respecto a algunos parámetros, pero no todos. Una especialización parcial continúa siendo genérica y necesita argumentos de plantilla reales para producir una clase con instancias real.