sep 14, 2009

Enviado por en C/C++, Programacion

Especialización de Plantillas

En este tema, trataré la especialización de plantillas de manera general.

Antes que todo, recordemos que una plantilla permite aplicar procedimientos comunes con distintos tipos de datos sin tener que reescribir el código. Podemos tener como ejemplo la clase de STL, std::vector<T>. Con la especialización de plantillas, en cambio, se permitir definir procedimientos o estructuras para casos particulares. Tal es el caso de std::vector<bool> en la librería STL que utiliza menos espacio que la clase genérica.

Otro ejemplo de la STL corresponde a std::char_traits<T>. Esta clase se encuentra indefinida [1], a diferencia de std::char_traits<char> y std::char_traits<wchar_t>. Algo así,

template <typename T>
struct char_traits;

template <>
struct char_traits<char> {
	size_t length(const char * str) {
		return strlen(str);
	}
};

template <>
struct char_traits<wchar_t> {
	size_t length(const wchar_t * str) {
		return wcslen(str);
	}
};

// ...

template <typename T>
size_t length(const T * str) {
	return char_traits<T>::length(str);
}

// ...

length("ABC");	// retorna 3.

int i;
length(&i);		// Produce un error de compilación, char_traits<T> no se
				// encuentra definida para T = int.

Adicionalmente, se permite casos más complejos. Como un ejemplo, definimos una estructura que maneje matrices. Existen distintas formas de manejar las matrices (modelos), entre ellas, llamemos de modelo estático cuando las dimensiones son predefinidas, de modelo dinámico cuando tales son definidos en tiempo de ejecución, y de modelo disperso como un caso particular del modelo dinámico donde solo se guardan los valores distintos de un cero. Podemos declarar las estructuras de este modo,

template <typename T, size_t Rows, size_t Columns>
class StaticMatrix;

template <typename T>
class DynamicMatrix;

template <typename T>
class SparseMatrix;

No obstante, podemos utilizar la especialización de plantillas y definir una estructura Matrix<T, Model> como,

namespace MatrixModels {
	template <size_t Rows, size_t Columns> class Static;
	class Dynamic;
	class Sparse;
}

template <typename T, typename Model>
class Matrix;

template <typename T, size_t Rows, size_t Columns>
class Matrix<T, MatrixModels::Static<Rows, Columns>>;

template <typename T>
class Matrix<T, MatrixModels::Dynamic>;

template <typename T>
class Matrix<T, MatrixModels::Sparse>;

Con lo cual se facilita ciertos casos como,

template <typename T, typename Model>
Model<T, Model> Power2(const Matrix<T, Model> & matrix) {
	return matrix * matrix;
}

Y no se requiere definir una función por cada modelo. Por cierto, se permite valores por defecto para las plantillas como,

template <typename T, typename Model = MatrixModels::Dynamic>
class Matrix;

No obstante, tales valores por defecto son inválidos en la declaración de una especialización de plantilla. El siguiente caso produce error de compilación.

template <typename T, size_t Rows, size_t Columns = 1>
class Matrix<T, MatrixModels::Static<Rows, Columns>>;

Aunque de este modo no hay problema:

template <size_t Rows, size_t Columns = 1> class Static;

Bien, hasta ahora hemos tratado la especialización para estructuras de datos no obstante también se puede aplicar a funciones:

template<typename T, typename Model>
pair<size_t, size_t> Size(const Matrix<T, Model> & matrix);

template<typename T>
pair<size_t, size_t> Size<T, MatrixModels::Dynamic>(
	const Matrix<T, MatrixModels::Dynamic> & matrix); 

template<typename T>
pair<size_t, size_t> Size(
	const Matrix<T, MatrixModels::Dynamic> & matrix
	); // El compilador se encarga de deducir Model.

Hay que tomar en cuenta que se requiere que cada especialización se encuentre definida al momento de traducirla, de otro modo, aquellos que no se encontraron definidas no serán tomados en cuenta, es decir,

template <typename T>
struct A {
	static const int i = 0;
};

int f() {
	return A<char>::i; // devuelve 0
}

template <>
struct A<char> {
	static const int i = 1;
};

int g() {
	return A<char>::i; // devuelve 1
}

[1] No es así en realidad pero se expresa de este modo para efectos didácticos.

    Posts Relacionados

    1. :o perfecto men!! por cierto, que tal te va en el ACM?

      Usando Google Chrome 4.0.206.1 Google Chrome 4.0.206.1 en Windows XP Windows XP
      • En realidad bien, creo que podremos llegar a hacer algo importante en la siguiente competencia. Vamos a ver.

        Saludos.

        Usando Opera 10.00 Opera 10.00 en Windows Vista Windows Vista

    Dejar una respuesta

    Debes ser Alojarse para enviar un comentario.