2012-06-30 29 views
32

Si consideri il seguente file di intestazione:C++ template typename iteratore

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 
    } 

}; 

Ora consideriamo una riga di codice da un altro file:

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

Il compilatore mi sta dando questo messaggio di errore: Tree.h:38:17: error: need ‘typename’ before ‘std::list<tNode<T>*>::iterator’ because ‘std::list<tNode<T>*>’ is a dependent scope

Non ho idea del perché il compilatore mi stia urlando per questo.

risposta

54

In list<tNode<T>*>::iterator, hai un nome dipendente, vale a dire, un nome che dipende da un parametro di template.

Come tale, il compilatore non può controllare list<tNode<T>*> (non ha la sua definizione a questo punto) e quindi non sa se list<tNode<T>*>::iterator è un campo statico o un tipo.

In una situazione del genere, il compilatore presuppone che si tratti di un campo, quindi nel tuo caso genera un errore di sintassi. Per risolvere il problema, basta dire al compilatore che si tratta di un tipo mettendo una typename avanti della dichiarazione:

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

list<tNode<T>*>::iterator è un nome dipendente, un tipo che dipende da un parametro di modello. Per dichiarare tale variabile, è necessario utilizzare la parola chiave typename:

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

In primo luogo, come altre risposte già notato, i nomi dei tipi annidati in tipi dipendenti devono essere anteporre con il typename parola chiave.

la parola chiave non è necessario quando il modello è completamente specializzata, il che significa che non ha bisogno list<tnode<int>*>::iteratortypename, ma quando la classe esterna dipende ancora dal parametro modello T, typename deve essere presente.

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

secondo luogo, anche con typename dichiarazione

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

dichiarerà una funzione, non un iteratore. Rimuovere lo ().

1

Maggiori backround sulle risposte di cui sopra è qui fornito

A Description of the C++ typename keyword

Ho avuto un problema diverso, ma simile in che volevo typedef un iteratore per i nodi figlio con la:

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

che mi ha dato lo stesso errore del compilatore. Con i suggerimenti qui e l'aiuto del collegamento sopra, la soluzione al mio problema è utilizzare

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

invece.