tags:

views:

112

answers:

2

Hey Everyone,

I'm having this problem while writing my own HashTable. It all works, but when I try to templatize the thing, it gave me errors. I recreated the problem as follows:

THIS CODE WORKS:

typedef double Item;

class A
{
public:
    A()
    {
        v.push_back(pair<string, Item>("hey", 5.0));
    }

    void iterate()
    {
        for(Iterator iter = v.begin(); iter != v.end(); ++iter)
            cout << iter->first << ", " << iter->second << endl;
    }

private:
    vector<pair<string, double> > v;
    typedef vector< pair<string, double> >::iterator Iterator;
};

THIS CODE DOES NOT:

template<typename ValueType>
class B
{
public:
    B(){}

    void iterate()
    {
        for(Iterator iter = v.begin(); iter != v.end(); ++iter)
            cout << iter->first << ", " << iter->second << endl;
    }

private:
    vector<pair<string, ValueType> > v;
    typedef vector< pair<string, ValueType> >::iterator Iterator;
};

the error messages: g++ -O0 -g3 -Wall -c -fmessage-length=0 -omain.o ..\main.cpp

..\main.cpp:50: error: type std::vector<std::pair<std::string, ValueType>, std::allocator<std::pair<std::string, ValueType> > >' is not derived from typeB'

..\main.cpp:50: error: ISO C++ forbids declaration of `iterator' with no type

..\main.cpp:50: error: expected `;' before "Iterator"

..\main.cpp: In member function `void B::iterate()':

..\main.cpp:44: error: `Iterator' was not declared in this scope

..\main.cpp:44: error: expected `;' before "iter"

..\main.cpp:44: error: `iter' was not declared in this scope

Does anybody know why this is happening? Thanks!

+5  A: 

This is called "dependent names" in C++. In your second code snippet, you say:

typedef vector< pair<string, ValueType> >::iterator Iterator;

whereas you should say:

typedef typename vector< pair<string, ValueType> >::iterator Iterator;

Whenever you see an error saying "is not derived...", typename is to the rescue. In general, the idea is that the compiler doesn't know if iterator is a type or a variable, because it doesn't know what

vector< pair <string, ValueType> >

is, as it depends on ValueType.

(Afraid I'm not using the right terms here, but the idea is correct)

Semen Semenych
Shouldn't it be:typedef typename vector< typename pair<string, ValueType> >::iterator Iterator; ?
Tomek
@Tomek: `pair<string, ValueType>` can only be a type since `pair` is a class template. So the compiler knowns that it is a type and there is no need to disambiguate it with `typename`.
sth
Tomek: it builds fine without it, so I guess it's fine. You don't say e.g pair<string, ValueType>::first_typehere, so you don't need that typename.
Semen Semenych
A: 

thanks it works and all makes sense now!

And i don't want to use a typedef, I can also use typename like this:

for( typename list<pair<string, ValueType> >::const_iterator itr = v.begin(); itr != v.end() ; ++itr){
{
//code
}
toefel
You'd better typedef it, because it's the right way to do things in general, and you could fall into the habit of not typedef'ing things, which would be not so nice)
Semen Semenych