Подтвердить что ты не робот

Иерархический идентификатор типа С++

Рассмотрим следующий заголовочный файл:

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
    }

};

Теперь рассмотрим строку кода из другого файла:

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

Компилятор сообщает мне это сообщение об ошибке: Tree.h:38:17: error: need ‘typename’ before ‘std::list<tNode<T>*>::iterator’ because ‘std::list<tNode<T>*>’ is a dependent scope

Я понятия не имею, почему компилятор кричит на меня за это.

4b9b3361

Ответ 1

В list<tNode<T>*>::iterator у вас есть зависимое имя, то есть имя, которое зависит от параметра шаблона.

Таким образом, компилятор не может проверить list<tNode<T>*> (он не имеет определения в этой точке), и поэтому он не знает, является ли list<tNode<T>*>::iterator либо статическим полем, либо типом.

В такой ситуации компилятор предполагает, что это поле, поэтому в вашем случае он дает синтаксическую ошибку. Чтобы решить проблему, просто сообщите компилятору, что это тип, поставив typename перед объявлением:

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

Ответ 2

Во-первых, как уже отмечалось в других ответах, имена типов, вложенные в зависимые типы, должны быть добавлены с ключевым словом typename.

Это ключевое слово не требуется, когда шаблон полностью специализирован, что означает, что list<tnode<int>*>::iterator не нуждается в typename, но когда внешний класс все еще зависит от параметра шаблона T, должен присутствовать typename.

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

Во-вторых, даже с typename

typename list<tNode<T>*>::iterator it();
Объявление

объявит функцию, а не итератор. Удалите ().

Ответ 3

list<tNode<T>*>::iterator - зависимое имя, тип которого зависит от параметра шаблона. Чтобы объявить эту переменную, вам нужно использовать ключевое слово typename:

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

Ответ 4

Более подробное описание ответов приведено здесь

Описание ключевого слова typename для С++

У меня была другая, но схожая проблема в том, что я хотел набрать итератор для дочерних узлов с помощью:

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

который дал мне ту же ошибку компилятора. С предложениями здесь и с помощью приведенной выше ссылки решение моей проблемы заключается в использовании

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

вместо.