2010-10-26 3 views
1

Может кто подскажет, почему это не компилируется? Наверное, мне здесь что-то не хватает. Компилятор g ++ 4.2.1 (в OS X), и ошибка «ожидается»; перед «it» на строке, где объявлен итератор.Нечетная ошибка с шаблоном класса C++

#include <vector> 

template <class T> 
class A { 
public: 
    struct SomeStruct { 
     T* ptr; 
     int i; 
    }; 

    typedef std::vector<SomeStruct> MyList; 

    void Func() 
    { 
     MyList::iterator it; 
    } 
}; 
+7

Да вы что-то не хватает: главный., Говоря нам, что ошибка компилятора. :) –

+2

@Steve: Нет, компилятор не имеет значения, кроме того, что g ++ неправильно принимает код. –

+0

Да, извините, что. Ред. –

ответ

6

Изменение:

MyList::iterator it; 

к:

typename MyList::iterator it; 

Я считаю, что это имеет отношение к компилятор не будучи уверенным в том, следует ли MyList::iterator быть значение некоторого вида (скажем, что iterator был статическим членом MyList) или типа. typename заставляет последний (правильный) вариант.

Я считаю, что соответствующий стандарт цитирует начинается здесь, второй 14,6:

имя, используемое в шаблоне предполагается не назвать тип, если это применимо именем поиск не находит имя типа или имя квалифицируется ключевое слово typename.

Таким образом, вы должны выяснить, что «применимо имя поиска» есть, но стандарт также следит за этим примером:

// no B declared here 

class X; 

template<class T> class Y { 
    class Z; // forward declaration of member class 

    void f() { 
     X* a1;  // declare pointer to X 
     T* a2;  // declare pointer to T 
     Y* a3;  // declare pointer to Y<T> 
     Z* a4;  // declare pointer to Z 
     typedef typename T::A TA; 
     TA* a5; // declare pointer to T’s A 
     typename T::A* a6; // declare pointer to T’s A 
     T::A* a7; // T::A is not a type name: 
        // multiply T::A by a7 
     B* a8;  // B is not a type name: 
        // multiply B by a8; ill-formed, 
        // no visible declaration of B 
     } 
}; 
+0

Нет, 'typename' ** не требуется ** здесь! –

+1

@Armen Tsirunyan: Я скомпилировал его код локально, прежде чем публиковать это: добавление 'typename' исправляет ошибку компилятора (" expected '; 'before' it '") – Thanatos

+0

@Thanatos, @Alf: По-видимому, я был неправ, но я все еще не понимаю, как SomeStruct является зависимым именем ... –

4

Вы не хватает на typename:

#include <vector> 

template <class T> 
class A { 
public: 
    struct SomeStruct { 
     T* ptr; 
     int i; 
    }; 

    typedef std::vector<SomeStruct> MyList; 

    void Func() 
    { 
     typename MyList::iterator it; 
    } 
}; 

int main() {} 

Этот код компилируется с g ++, msvc и Comeau Online.

Техническое описание SomeStruct является зависимым моментом., что означает, что то, что должно быть SomeStruct, зависит от параметра шаблона. С точки зрения компилятора std::vector может быть специализированным для некоторого A<T>::SomeStruct, где эта специализация не содержит iterator typedef. Итак, вы должны рассказать плохой компилятор. ;-)

Приветствия & НТН,

+0

Phew, имеет смысл. Раньше этого не было. Спасибо Альф. –

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