title: Why can't this C++ template code be compiled?
body: <p>This is some sample code copied from <a href="http://en.wikipedia.org/wiki/The_C%2B%2B_Programming_Language" rel="nofollow noreferrer">The C++ Programming Language</a> chapter 17 as below. When I compile it with Visual Studio 2008, it keeps giving me this error:
  <code>warning C4346: 'HashMap&lt;Key,T,H,EQ,A&gt;::mapped_type' : dependent name is not a type
  1&gt;        prefix with 'typename' to indicate a type</code></p>
  
  <p>Does anyone have any idea about this? 
  Thanks in advance!</p>
  
  <pre><code>#include &lt;vector&gt;
  #include &lt;map&gt;
  using std::vector;
  using std::pair;
  using std::iterator;
  
  template&lt;class Key, class T, class H= Hash&lt;Key&gt;, class EQ = equal_to&lt;Key&gt;, class A = allocator&lt;pair&lt;const Key, T&gt;&gt;&gt;
  class HashMap{
  public:
      typedef Key key_type;
      typedef T mapped_type;
      typedef pair&lt;const Key, T&gt; value_type;
      typedef typename A::size_type size_type;
      typedef H Hasher;
      typedef EQ key_equal;
  
      HashMap(const T&amp; dv=T(), size_type n = 101, const H&amp; hf = H(), const EQ&amp; = EQ()):
              :default_value(dv), b(n), no_of_erased(0), hash(hf), eq(e){
          set_load();
          v.reserve(max_load*b.size());
      }
      template&lt;class In&gt; HashMap(In first, In last,
          const T&amp; dv=T(), size_type n=101, const H&amp; hf=H(), const EQ&amp; = EQ());
  
      void set_load(float m=0.7, float g=1.6){
          max_load = m;
          grow = g;
      }
      mapped_type&amp; operator[](const key_type&amp; 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&lt;Entry&gt; v;
      vector&lt;Entry*&gt; b;
  
      float max_load;
      float grow;
      size_type no_of_erased;
      Hasher hash;
      key_equal eq;
  
      const T default_value;
  
  };
  
  
  template&lt;class Key, class T, class H=Hash&lt;Key&gt;, class EQ=equal_to&lt;Key&gt;, class A=allocator&lt;pair&lt;const Key,T&gt;&gt;&gt; 
  HashMap&lt;Key,T,H,EQ,A&gt;::mapped_type &amp; HashMap&lt;Key,T,H,EQ,A&gt;::operator [](const HashMap&lt;Key,T,H,EQ,A&gt;::key_type&amp; k){
      size_type i = hash(k)%b.size();
  
      for(Entry* p=b[i]; p; p=p-&gt;next){
          if(eq(k, p-&gt;key)){
              if(p-&gt;erased){
                  p-&gt;erased = false;
                  no_of_erased--;
                  return p-&gt;val=default_value;
              }
              return p-&gt;val;
          }
      }
  
      if(size_type(b.size()*max_load) &lt;= v.size()){
          resize(b.size()*grow);
          return operator[](k);
      }
  
      v.push_back(Entry(k,default_value,b[i]));
      b[i] = &amp;v.back();
  
      return b[i]-&gt;val;
  }
  
  template&lt;class Key, class T, class H=Hash&lt;Key&gt;, class EQ=equal_to&lt;Key&gt;, class A=allocator&lt;pair&lt;const Key,T&gt;&gt;&gt; 
  void HashMap&lt;Key,T,H,EQ,A&gt;::resize(size_type s){
      size_type i = v.size();
      while(no_of_erased){
          if(v[--i].erased){
              v.erase(&amp;v[i]);
              --no_of_erased;
          }
      }
  
      if(s&lt;=b.size())
          return;
      b.resize(s);
      fill(b.begin(),b.end(),0);
      v.reserve(s*max_load);
  
      for(size_type i=0;i&lt;v.size(); i++){
          size_type ii = hash(v[i].key)%b.size();
          v[i].next = b[ii];
          b[ii] = &amp;v[i];
      }
  }
  
  template&lt;class Key, class T, class H=Hash&lt;Key&gt;, class EQ=equal_to&lt;Key&gt;, class A=allocator&lt;pair&lt;const Key,T&gt;&gt;&gt;
  void HashMap&lt;Key,T,H,EQ,A&gt;::erase(iterator p){
          if(p-&gt;erased == false) no_of_erased++;
          p-&gt;erased = true;
  }
  
  
  int main(){
      return 0;
  }
  </code></pre>