web-dev-qa-db-fra.com

Itérateur de nom de type de modèle C ++

Considérez le fichier d'en-tête suivant:

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
    }

};

Considérons maintenant une ligne de code d'un autre fichier:

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

Le compilateur me donne ce message d'erreur: Tree.h:38:17: error: need ‘typename’ before ‘std::list<tNode<T>*>::iterator’ because ‘std::list<tNode<T>*>’ is a dependent scope

Je n'ai aucune idée pourquoi le compilateur me crie dessus.

38
CodeKingPlusPlus

Dans list<tNode<T>*>::iterator, vous avez un nom dépendant, c'est-à-dire un nom qui dépend d'un paramètre de modèle.

En tant que tel, le compilateur ne peut pas inspecter list<tNode<T>*> (il n'a pas sa définition à ce stade) et donc il ne sait pas si list<tNode<T>*>::iterator est soit un champ statique soit un type.

Dans une telle situation, le compilateur suppose qu'il s'agit d'un champ, donc dans votre cas, il génère une erreur de syntaxe. Pour résoudre le problème, dites simplement au compilateur qu'il s'agit d'un type en mettant un typename avant la déclaration:

typename list<tNode<T>*>::iterator it
65
akappa

Premièrement, comme d'autres réponses l'ont déjà fait remarquer, les noms de types imbriqués dans des types dépendants doivent être précédés du mot clé typename.

Ce mot clé n'est pas nécessaire lorsque le modèle est entièrement spécialisé, ce qui signifie que list<tnode<int>*>::iterator n'a pas besoin de typename, mais lorsque la classe externe dépend toujours du paramètre de modèle T, typename doit être présent.

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

Deuxièmement, même avec typename le

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

declaration déclarera une fonction, pas un itérateur. Retirer le ().

21
AnT

list<tNode<T>*>::iterator est un nom dépendant, un type qui dépend d'un paramètre de modèle. Pour déclarer cette variable, vous devez utiliser le mot clé typename:

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

Plus d'informations sur les réponses ci-dessus sont fournies ici

ne description du mot-clé du nom de type C++

J'ai eu un problème différent mais similaire en ce que je voulais dactylographier un itérateur pour les nœuds enfants avec:

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

ce qui m'a donné la même erreur de compilation. Avec les suggestions ici et l'aide du lien ci-dessus, la solution à mon problème est d'utiliser

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

au lieu.

1
trueter