2012-06-30 4 views
32

Рассмотрим следующий файл заголовка:C++ шаблон имяТипа итератора

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

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

ответ

54

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

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

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

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

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

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

Во-первых, как и другие ответы уже отмечалось, имена типов вложенных в зависимые типы должны предваряться с 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(); 

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

1

Более фон на ответы выше, представлен здесь

A Description of the C++ typename keyword

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

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

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

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

вместо этого.

Смежные вопросы