Emil Kirichev
Emil Kirichev

Reputation: 189

Odd error with C++ class template

can anyone suggest why this does not compile? I guess I'm missing something major here. The compiler is g++ 4.2.1 (on OS X) and error is "expected `;' before ‘it’" on the line where the iterator is declared.

#include <vector>

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

    typedef std::vector<SomeStruct> MyList;

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

Upvotes: 1

Views: 209

Answers (2)

Thanatos
Thanatos

Reputation: 44344

Change:

MyList::iterator it;

to:

typename MyList::iterator it;

I believe this has to do with the compiler not being sure as to whether MyList::iterator should be a value of some sort (say that iterator was a static member of MyList) or a type. typename forces the latter (correct) option.

I believe the relevant standard quoting starts here, second 14.6:

A name used in a template is assumed not to name a type unless the applicable name lookup finds a type name or the name is qualified by the keyword typename.

So, you'd have to figure out what the "applicable name lookup" is, but the standard also follows up with this example:

// 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
        }
};

Upvotes: 6

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145429

You're lacking a 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() {}

This code compiles with g++, msvc and Comeau Online.

Technically SomeStruct is a dependent name, meaning that what SomeStruct stands for depends on the template parameter. From the compiler's point of view std::vector might be specialized for some A<T>::SomeStruct, where that specialization doesn't have an iterator typedef. So you have to tell the poor compiler. ;-)

Cheers & hth.,

Upvotes: 4

Related Questions