2010-09-04 148 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