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.
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
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 ()
.
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 = ...;
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.