views:

74

answers:

1

This is a code sample copied from chapter 17 as bellow. When I compile it with Visual Studio 2008, it keeps this error: warning C4346: 'HashMap::mapped_type' : dependent name is not a type 1> prefix with 'typename' to indicate a type

Does anyone has any idea about this? Thanks in advance!

#include <vector>
#include <map>
using std::vector;
using std::pair;
using std::iterator;

template<class Key, class T, class H= Hash<Key>, class EQ = equal_to<Key>, class A = allocator<pair<const Key, T>>>
class HashMap{
public:
    typedef Key key_type;
    typedef T mapped_type;
    typedef pair<const Key, T> value_type;
    typedef typename A::size_type size_type;
    typedef H Hasher;
    typedef EQ key_equal;

    HashMap(const T& dv=T(), size_type n = 101, const H& hf = H(), const EQ& = EQ()):
            :default_value(dv), b(n), no_of_erased(0), hash(hf), eq(e){
        set_load();
        v.reserve(max_load*b.size());
    }
    template<class In> HashMap(In first, In last,
        const T& dv=T(), size_type n=101, const H& hf=H(), const EQ& = EQ());

    void set_load(float m=0.7, float g=1.6){
        max_load = m;
        grow = g;
    }
    mapped_type& operator[](const key_type& k);

    void resize(size_type n);
    void erase(iterator position);
    size_type size() const { return v.size() - no_of_erased;}
    size_type bucket_count() const { return b.size();}
    Hasher hash_fun() const { return hash;}
    key_equal key_eq() const { return eq;}

private:
    struct Entry{
        key_type key;
        mapped_type val;
        bool erased;
        Entry* next;
        Entry(key_type k, mapped_type v, Entry* n):
            key(k),val(v),erased(false),next(n) {}
    };

    vector<Entry> v;
    vector<Entry*> b;

    float max_load;
    float grow;
    size_type no_of_erased;
    Hasher hash;
    key_equal eq;

    const T default_value;

};


template<class Key, class T, class H=Hash<Key>, class EQ=equal_to<Key>, class A=allocator<pair<const Key,T>>> 
HashMap<Key,T,H,EQ,A>::mapped_type & HashMap<Key,T,H,EQ,A>::operator [](const HashMap<Key,T,H,EQ,A>::key_type& k){
    size_type i = hash(k)%b.size();

    for(Entry* p=b[i]; p; p=p->next){
        if(eq(k, p->key)){
            if(p->erased){
                p->erased = false;
                no_of_erased--;
                return p->val=default_value;
            }
            return p->val;
        }
    }

    if(size_type(b.size()*max_load) <= v.size()){
        resize(b.size()*grow);
        return operator[](k);
    }

    v.push_back(Entry(k,default_value,b[i]));
    b[i] = &v.back();

    return b[i]->val;
}

template<class Key, class T, class H=Hash<Key>, class EQ=equal_to<Key>, class A=allocator<pair<const Key,T>>> 
void HashMap<Key,T,H,EQ,A>::resize(size_type s){
    size_type i = v.size();
    while(no_of_erased){
        if(v[--i].erased){
            v.erase(&v[i]);
            --no_of_erased;
        }
    }

    if(s<=b.size())
        return;
    b.resize(s);
    fill(b.begin(),b.end(),0);
    v.reserve(s*max_load);

    for(size_type i=0;i<v.size(); i++){
        size_type ii = hash(v[i].key)%b.size();
        v[i].next = b[ii];
        b[ii] = &v[i];
    }
}

template<class Key, class T, class H=Hash<Key>, class EQ=equal_to<Key>, class A=allocator<pair<const Key,T>>>
void HashMap<Key,T,H,EQ,A>::erase(iterator p){
        if(p->erased == false) no_of_erased++;
        p->erased = true;
}


int main(){
    return 0;
}
+1  A: 

Change

HashMap<Key,T,H,EQ,A>::mapped_type & HashMap<Key,T,H,EQ,A>::operator []

to

typename HashMap<Key,T,H,EQ,A>::mapped_type & HashMap<Key,T,H,EQ,A>::operator []

as your error already suggests. The compiler cannot deduce on it's own that mapped_type is a typedef inside a class template.

Pieter
Sunnie
OK, I got it. Thanks for reminder.And thanks to Pieter, I've worked it out.
Sunnie