2012-06-30 14 views
32

Considere el siguiente archivo de cabecera:C++ iterador plantilla nombretipo

template <typename T> struct tNode 
{ 
    T Data;      //the data contained within this node 
    list<tNode<T>*> SubNodes;  //a list of tNodes pointers under this tNode 

    tNode(const T& theData) 
    //PRE: theData is initialized 
    //POST: this->data == theData and this->SubNodes have an initial capacity 
    //  equal to INIT_CAPACITY, it is set to the head of SubNodes 
    { 
     this->Data = theData; 
     SubNodes(INIT_CAPACITY); //INIT_CAPACITY is 10 
    } 

}; 

Consideremos ahora una línea de código de otro archivo:

list<tNode<T>*>::iterator it(); //iterate through the SubNodes 

El compilador me está dando este mensaje de error: Tree.h:38:17: error: need ‘typename’ before ‘std::list<tNode<T>*>::iterator’ because ‘std::list<tNode<T>*>’ is a dependent scope

No tengo idea de por qué el compilador me está gritando por esto.

Respuesta

54

en list<tNode<T>*>::iterator, tiene un nombre dependiente, es decir, un nombre que depende de un parámetro de plantilla.

Como tal, el compilador no puede inspeccionar list<tNode<T>*> (no tiene su definición en este momento) y por lo tanto no sabe si list<tNode<T>*>::iterator es un campo estático o un tipo.

En tal situación, el compilador asume que es un campo, por lo que en su caso produce un error de sintaxis. Para resolver el problema, simplemente decirle al compilador que es un tipo poniendo una por delante typename de la declaración:

typename list<tNode<T>*>::iterator it 
5

list<tNode<T>*>::iterator es un nombre dependiente, un tipo que depende de un parámetro de plantilla. Con el fin de declarar que la variable, es necesario utilizar la palabra clave typename:

typename list<tNode<T>*>::iterator it = ...; 
16

primer lugar, como otras respuestas ya se ha señalado, los nombres de tipos anidados en tipos dependientes deben ser precedidas por la typename palabra clave.

esa palabra clave no es necesario cuando la plantilla es completamente especializada, lo que significa que no necesita list<tnode<int>*>::iteratortypename, pero cuando la clase externa sigue dependiendo de parámetro de plantilla T, typename debe estar presente.

template <typename T> void foo() { 
    list<tnode<int>*>::iterator it1; // OK without typename 
    typename list<tnode<T>*>::iterator it2; // typename necessary 
} 

En segundo lugar, incluso con la declaración typename

typename list<tNode<T>*>::iterator it(); 

declarará una función, no un iterador. Retire el ().

1

Más apaisada en las respuestas anteriores se proporciona aquí

A Description of the C++ typename keyword

que tenía un problema diferente pero similar en que quería typedef un iterador de nodos secundarios con el:

typedef std::vector<NodeType*>::iterator ChildIterator; 

que me dio el mismo error de compilación. Con las sugerencias aquí y la ayuda del enlace de arriba, la solución a mi problema es usar

typedef typename std::vector<NodeType*>::iterator ChildIterator; 

en su lugar.