Los argumentos de los templates no restrigen su uso a tipos
class; se pueden también usar tipos empotrados. Los valores de
estos argumentos se convierten en constantes en tiempo de
compilación para una instanciación en particular de la
plantilla. Se pueden usar incluso valores por defecto para
esos argumentos. El siguiente ejemplo nos permite indicar el
tamaño de la clase Array
durante la
instanciación, pero también proporciona un valor por defecto:
//: C16:Array3.cpp // Built-in types as template arguments #include "../require.h" #include <iostream> using namespace std; template<class T, int size = 100> class Array { T array[size]; public: T& operator[](int index) { require(index >= 0 && index < size, "Index out of range"); return array[index]; } int length() const { return size; } }; class Number { float f; public: Number(float ff = 0.0f) : f(ff) {} Number& operator=(const Number& n) { f = n.f; return *this; } operator float() const { return f; } friend ostream& operator<<(ostream& os, const Number& x) { return os << x.f; } }; template<class T, int size = 20> class Holder { Array<T, size>* np; public: Holder() : np(0) {} T& operator[](int i) { require(0 <= i && i < size); if(!np) np = new Array<T, size>; return np->operator[](i); } int length() const { return size; } ~Holder() { delete np; } }; int main() { Holder<Number> h; for(int i = 0; i < 20; i++) h[i] = i; for(int j = 0; j < 20; j++) cout << h[j] << endl; } ///:~
Listado 16.8. C16/Array3.cpp
Como antes, Array
es un array de
objetos que previene de rebasar los límites. La clase
Holder
es muy parecida a
Array
excepto que tiene un puntero a
Array
en vez de un tener incrustrado
un objeto del tipo Array
. Este puntero
no se inicializa en el constructor; la inicialización es
retrasada hasta el primer acceso. Esto se conoce como
inicialización perezosa; se puede usar
una técnica como esta si se están creando un montón de
objetos, pero no se está accediendo a todos ellos y se quiere
ahorrar almacenamiento.
Hay que resaltar que nunca se almacena internamente el valor
de size
en la clase, pero se usa como si
fuera un dato interno dentro de las funciones miembro.