2010-09-04 149 views
2

這是從The C++ Programming Language第17章複製的一些示例代碼,如下所示。當我用Visual Studio 2008進行編譯時,它一直給我這個錯誤: warning C4346: 'HashMap<Key,T,H,EQ,A>::mapped_type' : dependent name is not a type 1> prefix with 'typename' to indicate a type爲什麼不能編譯這個C++模板代碼?

有沒有人有任何想法呢? 在此先感謝!

#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

爲什麼downvotes?如果一本着名書籍的例子給出了知名編譯器的警告,這對學習者來說似乎是個好問題。 – ArtB 2012-03-12 16:09:38

+0

@ArtB:downvote鏈接說「這個問題沒有顯示任何研究工作」。至少對於這一點來說,因爲錯誤清楚地說明了如何解決它。如果OP想知道爲什麼需要這個,那麼downvote鏈接的部分說「不清楚」匹配。 – PlasmaHH 2012-03-12 16:30:27

+1

@PlasmaHH但是,如果你是初學者,它很難做研究。他們從「C++編程語言」中獲取代碼的事實已經表明他們正在進行研究。當問題是入門級或用戶是初學者時,很難做出有意義的研究。這與post〜300行代碼不同,並且說「這裏有些東西壞了,爲我修復」 – ArtB 2012-03-12 16:46:55

回答

3

變化

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

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

因爲您的錯誤已經提出。編譯器無法自行推斷mapped_type是類模板中的typedef

+0

Pieter,非常感謝您的回答!它在我添加'typename'後真的起作用。 但還有另一個錯誤: 錯誤C4519:只允許在類模板上使用默認模板參數 看起來函數定義不能使用像這樣的模板參數: template , \t \t \t \t類EQ = equal_to ,類A =分配器<對 >> 類型名稱的HashMap <鑰匙,T,H,EQ,A> :: mapped_type&HashMap中<鑰匙,T,H,EQ,A> :: operator [](const typename HashMap :: key_type&k) 您有任何解決方案嗎? 再次感謝您! – Sunnie 2010-09-04 16:23:47

+0

好的,我明白了。感謝提醒。 感謝Pieter,我已經完成了。 – Sunnie 2010-09-04 16:40:07