El El secreto reside en el hecho de que una plantilla puede ser especializada para algunos tipos. Esto significa que también puede definir la interfaz completamente diferente para varios tipos. Por ejemplo, puede escribir:
template<typename T>
struct test {
typedef T* ptr;
};
template<> // complete specialization
struct test<int> { // for the case T is int
T* ptr;
};
Uno puede preguntarse por qué es esto útil y de hecho: Eso realmente parece inútil. Pero tenga en cuenta que, por ejemplo, std::vector<bool>
, el tipo reference
tiene un aspecto completamente diferente al de otras T
s. Es cierto que no cambia el tipo de reference
de un tipo a algo diferente, pero sin embargo podría suceder.
Ahora qué sucede si escribe sus propias plantillas usando esta plantilla test
. Algo como esto
template<typename T>
void print(T& x) {
test<T>::ptr p = &x;
std::cout << *p << std::endl;
}
parece estar bien para usted porque espera quetest<T>::ptr
es un tipo. Pero el compilador no sabe y, de hecho, hasta el estándar le aconseja que espere lo contrario, test<T>::ptr
no es un tipo. Para decirle al compilador lo que espera, debe agregar un typename
antes. La plantilla correcta se parece a esto
template<typename T>
void print(T& x) {
typename test<T>::ptr p = &x;
std::cout << *p << std::endl;
}
En pocas palabras: Usted tiene que agregar typename
antes de cada vez que utilice un tipo anidado de una plantilla en sus plantillas. (Por supuesto, solo si se usa un parámetro de plantilla de su plantilla para esa plantilla interna)
http://stackoverflow.com/questions/1600464/ – sbi