Why can't this C++ template code be compiled?
This is some sample code copied from The C++ Programming Language chapter 17 as below. When I compile it with Visual Studio 2008, it keeps giving me this error:
warning C4346: 'HashMap<Key,T,H,EQ,A>::mapped_type' : dependent name is not a type
1> prefix with 'typename' to indicate a type
Does anyone have 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, clas开发者_JS百科s 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;
}
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.
精彩评论