Template Inheritance and Instantiation -- A Simpler Hashtable Iterator

Chad Gatesman chadg@redrose.net
Fri Sep 4 06:42:00 GMT 1998


I am trying to develop a simpler hashtable iterator.  By simpler, I mean
one that will dereference to just the Value instead of pair<Key,Value>.

At first I tryed to write a wrapper around the template iterator, but
ran into some problems.  I am now implementing it by inheriting
__hashtable_const_iterator defined in stl_hashtable.h.

I was able to implement it, and it compiled fine with egcs-1.0.3.  Here
is my implementation:

#include <hash_map>

// CSimpleHashIterator
//     Acts just like a hashtable iterator,
//     but only dereferences the value
//     instead of pair<Key,Value>

template <class Value, class Key, class HashFcn = hash<Key>,
          class ExtractKey = select1st<pair<const Key, Value> >,
          class EqualKey = equal_to<Key>, class Alloc = alloc>
struct CSimpleHashIterator
   : public __hashtable_iterator<pair<const Key, Value>, Key, HashFcn,
                                 ExtractKey, EqualKey, Alloc>
{
   CSimpleHashIterator(void)
      : __hashtable_iterator<pair<const Key, Value>, Key, HashFcn,
                             ExtractKey, EqualKey, Alloc>() {}

   CSimpleHashIterator(node* n, hashtable* tab)
      : __hashtable_iterator<pair<const Key, Value>, Key, HashFcn,
                             ExtractKey, EqualKey, Alloc>(n, tab) {}

   CSimpleHashIterator(const __hashtable_iterator<pair<const Key,Value>,

                                Key, HashFcn, ExtractKey,
                                EqualKey, Alloc> &i)
      : __hashtable_iterator<pair<const Key,Value>, Key, HashFcn,
                             ExtractKey, EqualKey, Alloc>(i) {}

   Value &operator*(void) const { return cur->val.second; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
   Value *operator->(void) const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
};


template <class Value, class Key, class HashFcn = hash<Key>,
          class ExtractKey = select1st<pair<const Key, Value> >,
          class EqualKey = equal_to<Key>, class Alloc = alloc>
struct CSimpleConstHashIterator
   : public __hashtable_const_iterator<pair<const Key, Value>, Key,
                                       HashFcn, ExtractKey, EqualKey,
                                       Alloc>
{
   typedef CSimpleHashIterator<Value, Key, HashFcn, ExtractKey,
                               EqualKey, Alloc> iterator;
   typedef CSimpleConstHashIterator<Value, Key, HashFcn, ExtractKey,
                                    EqualKey, Alloc> const_iterator;

   CSimpleConstHashIterator(void)
      : __hashtable_const_iterator<pair<const Key, Value>, Key, HashFcn,

                                   ExtractKey, EqualKey, Alloc>() {}

   CSimpleConstHashIterator(const iterator& i)
   {
      cur = i.cur;
      ht  = i.ht;
   }

   CSimpleConstHashIterator(node* n, hashtable* tab)
      : __hashtable_const_iterator<pair<const Key, Value>, Key, HashFcn,

                                   ExtractKey, EqualKey,
                                   Alloc>(n, tab) {}

   CSimpleConstHashIterator(const
      __hashtable_const_iterator<pair<const Key,Value>,
                                 Key, HashFcn, ExtractKey,
                                 EqualKey, Alloc> &i)
      : __hashtable_const_iterator<pair<const Key,Value>,
                                   Key, HashFcn, ExtractKey,
                           EqualKey, Alloc>(i) {}

   const Value &operator*(void) const { return cur->val.second; }
#ifndef __SGI_STL_NO_ARROW_OPERATOR
   const Value *operator->(void) const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */
};



Just recently I upgraded to egcs-1.1a and now the above implementation
causes link errors from collect2 when using the -frepo option of egcs.
This was not a problem with egcs-1.0.3 -frepo.  The code will compile if
I do not use the -frepo option (I would rather use the -frepo, because I
am dealing with a very large code base that uses templates
extensively).  Have I found a regression in egcs, or is there something
that isn't quite to the C++ Standard that is causing the newer compiler
to choke?

It seems like templates aren't getting instantiated in the right order,
which I thought was one of the things -frepo was suppose to take care
of.  This would be a problem as I have read in the C++ Draft 14.6.1.3:

"The use of a _template-parameter_ as a base class implies that a class
used as a _template-argument_ must be defined and not just declared when
the class template is instantiated."

If there is something wrong with the way I am implementing this, does
anyone know how I can fix this?  Is there something I have to do to
force instantiations to occur in the right order and in the right
place?  I wouldn't think I would have to do explicit instantiations.
This could get very sloppy and tedious with the amount of instances I
would have to deal with.  If it is a regression in egcs (God forbit),
does anyone know of a work-around for this until it is fixed?

I can email an attachment of the link errors if that would help you help
me ;)

Thanks in advance for everything.

--
  Chad Gatesman
  Software Engineer






More information about the Gcc mailing list