# hashtable_policy.h

Go to the documentation of this file.

    00001 // Internal policy header for TR1 unordered_set and unordered_map -*- C++ -*-
    00002
    00003 // Copyright (C) 2007 Free Software Foundation, Inc.
    00004 //
    00005 // This file is part of the GNU ISO C++ Library.  This library is free
    00006 // software; you can redistribute it and/or modify it under the
    00007 // terms of the GNU General Public License as published by the
    00008 // Free Software Foundation; either version 2, or (at your option)
    00009 // any later version.
    00010
    00011 // This library is distributed in the hope that it will be useful,
    00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00014 // GNU General Public License for more details.
    00015
    00016 // You should have received a copy of the GNU General Public License along
    00017 // with this library; see the file COPYING.  If not, write to the Free
    00018 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
    00019 // USA.
    00020
    00021 // As a special exception, you may use this file as part of a free software
    00022 // library without restriction.  Specifically, if other files instantiate
    00023 // templates or use macros or inline functions from this file, or you compile
    00024 // this file and link it with other files to produce an executable, this
    00025 // file does not by itself cause the resulting executable to be covered by
    00026 // the GNU General Public License.  This exception does not however
    00027 // invalidate any other reasons why the executable file might be covered by
    00028 // the GNU General Public License.
    00029
    00030 /** @file tr1_impl/hashtable_policy.h
    00031  *  This is an internal header file, included by other library headers.
    00032  *  You should not attempt to use it directly.
    00033  */
    00034
    00035 namespace std
    00036 {
    00037 _GLIBCXX_BEGIN_NAMESPACE_TR1
    00038
    00039 namespace __detail
    00040 {
    00041   // Helper function: return distance(first, last) for forward
    00042   // iterators, or 0 for input iterators.
    00043   template<class _Iterator>
    00044     inline typename std::iterator_traits<_Iterator>::difference_type
    00045     __distance_fw(_Iterator __first, _Iterator __last,
    00046           std::input_iterator_tag)
    00047     { return 0; }
    00048
    00049   template<class _Iterator>
    00050     inline typename std::iterator_traits<_Iterator>::difference_type
    00051     __distance_fw(_Iterator __first, _Iterator __last,
    00052           std::forward_iterator_tag)
    00053     { return std::distance(__first, __last); }
    00054
    00055   template<class _Iterator>
    00056     inline typename std::iterator_traits<_Iterator>::difference_type
    00057     __distance_fw(_Iterator __first, _Iterator __last)
    00058     {
    00059       typedef typename std::iterator_traits<_Iterator>::iterator_category _Tag;
    00060       return __distance_fw(__first, __last, _Tag());
    00061     }
    00062
    00063   template<typename _RAIter, typename _Tp>
    00064     _RAIter
    00065     __lower_bound(_RAIter __first, _RAIter __last, const _Tp& __val)
    00066     {
    00067       typedef typename std::iterator_traits<_RAIter>::difference_type _DType;
    00068
    00069       _DType __len = __last - __first;
    00070       while (__len > 0)
    00071     {
    00072       _DType __half = __len >> 1;
    00073       _RAIter __middle = __first + __half;
    00074       if (*__middle < __val)
    00075         {
    00076           __first = __middle;
    00077           ++__first;
    00078           __len = __len - __half - 1;
    00079         }
    00080       else
    00081         __len = __half;
    00082     }
    00083       return __first;
    00084     }
    00085
    00086   // Auxiliary types used for all instantiations of _Hashtable: nodes
    00087   // and iterators.
    00088
    00089   // Nodes, used to wrap elements stored in the hash table.  A policy
    00090   // template parameter of class template _Hashtable controls whether
    00091   // nodes also store a hash code. In some cases (e.g. strings) this
    00092   // may be a performance win.
    00093   template<typename _Value, bool __cache_hash_code>
    00094     struct _Hash_node;
    00095
    00096   template<typename _Value>
    00097     struct _Hash_node<_Value, true>
    00098     {
    00099       _Value       _M_v;
    00100       std::size_t  _M_hash_code;
    00101       _Hash_node*  _M_next;
    00102     };
    00103
    00104   template<typename _Value>
    00105     struct _Hash_node<_Value, false>
    00106     {
    00107       _Value       _M_v;
    00108       _Hash_node*  _M_next;
    00109     };
    00110
    00111   // Local iterators, used to iterate within a bucket but not between
    00112   // buckets.
    00113   template<typename _Value, bool __cache>
    00114     struct _Node_iterator_base
    00115     {
    00116       _Node_iterator_base(_Hash_node<_Value, __cache>* __p)
    00117       : _M_cur(__p) { }
    00118
    00119       void
    00120       _M_incr()
    00121       { _M_cur = _M_cur->_M_next; }
    00122
    00123       _Hash_node<_Value, __cache>*  _M_cur;
    00124     };
    00125
    00126   template<typename _Value, bool __cache>
    00127     inline bool
    00128     operator==(const _Node_iterator_base<_Value, __cache>& __x,
    00129            const _Node_iterator_base<_Value, __cache>& __y)
    00130     { return __x._M_cur == __y._M_cur; }
    00131
    00132   template<typename _Value, bool __cache>
    00133     inline bool
    00134     operator!=(const _Node_iterator_base<_Value, __cache>& __x,
    00135            const _Node_iterator_base<_Value, __cache>& __y)
    00136     { return __x._M_cur != __y._M_cur; }
    00137
    00138   template<typename _Value, bool __constant_iterators, bool __cache>
    00139     struct _Node_iterator
    00140     : public _Node_iterator_base<_Value, __cache>
    00141     {
    00142       typedef _Value                                   value_type;
    00143       typedef typename
    00144       __gnu_cxx::__conditional_type<__constant_iterators,
    00145                     const _Value*, _Value*>::__type
    00146                                                        pointer;
    00147       typedef typename
    00148       __gnu_cxx::__conditional_type<__constant_iterators,
    00149                     const _Value&, _Value&>::__type
    00150                                                        reference;
    00151       typedef std::ptrdiff_t                           difference_type;
    00152       typedef std::forward_iterator_tag                iterator_category;
    00153
    00154       _Node_iterator()
    00155       : _Node_iterator_base<_Value, __cache>(0) { }
    00156
    00157       explicit
    00158       _Node_iterator(_Hash_node<_Value, __cache>* __p)
    00159       : _Node_iterator_base<_Value, __cache>(__p) { }
    00160
    00161       reference
    00162       operator*() const
    00163       { return this->_M_cur->_M_v; }
    00164
    00165       pointer
    00166       operator->() const
    00167       { return &this->_M_cur->_M_v; }
    00168
    00169       _Node_iterator&
    00170       operator++()
    00171       {
    00172     this->_M_incr();
    00173     return *this;
    00174       }
    00175
    00176       _Node_iterator
    00177       operator++(int)
    00178       {
    00179     _Node_iterator __tmp(*this);
    00180     this->_M_incr();
    00181     return __tmp;
    00182       }
    00183     };
    00184
    00185   template<typename _Value, bool __constant_iterators, bool __cache>
    00186     struct _Node_const_iterator
    00187     : public _Node_iterator_base<_Value, __cache>
    00188     {
    00189       typedef _Value                                   value_type;
    00190       typedef const _Value*                            pointer;
    00191       typedef const _Value&                            reference;
    00192       typedef std::ptrdiff_t                           difference_type;
    00193       typedef std::forward_iterator_tag                iterator_category;
    00194
    00195       _Node_const_iterator()
    00196       : _Node_iterator_base<_Value, __cache>(0) { }
    00197
    00198       explicit
    00199       _Node_const_iterator(_Hash_node<_Value, __cache>* __p)
    00200       : _Node_iterator_base<_Value, __cache>(__p) { }
    00201
    00202       _Node_const_iterator(const _Node_iterator<_Value, __constant_iterators,
    00203                __cache>& __x)
    00204       : _Node_iterator_base<_Value, __cache>(__x._M_cur) { }
    00205
    00206       reference
    00207       operator*() const
    00208       { return this->_M_cur->_M_v; }
    00209
    00210       pointer
    00211       operator->() const
    00212       { return &this->_M_cur->_M_v; }
    00213
    00214       _Node_const_iterator&
    00215       operator++()
    00216       {
    00217     this->_M_incr();
    00218     return *this;
    00219       }
    00220
    00221       _Node_const_iterator
    00222       operator++(int)
    00223       {
    00224     _Node_const_iterator __tmp(*this);
    00225     this->_M_incr();
    00226     return __tmp;
    00227       }
    00228     };
    00229
    00230   template<typename _Value, bool __cache>
    00231     struct _Hashtable_iterator_base
    00232     {
    00233       _Hashtable_iterator_base(_Hash_node<_Value, __cache>* __node,
    00234                    _Hash_node<_Value, __cache>** __bucket)
    00235       : _M_cur_node(__node), _M_cur_bucket(__bucket) { }
    00236
    00237       void
    00238       _M_incr()
    00239       {
    00240     _M_cur_node = _M_cur_node->_M_next;
    00241     if (!_M_cur_node)
    00242       _M_incr_bucket();
    00243       }
    00244
    00245       void
    00246       _M_incr_bucket();
    00247
    00248       _Hash_node<_Value, __cache>*   _M_cur_node;
    00249       _Hash_node<_Value, __cache>**  _M_cur_bucket;
    00250     };
    00251
    00252   // Global iterators, used for arbitrary iteration within a hash
    00253   // table.  Larger and more expensive than local iterators.
    00254   template<typename _Value, bool __cache>
    00255     void
    00256     _Hashtable_iterator_base<_Value, __cache>::
    00257     _M_incr_bucket()
    00258     {
    00259       ++_M_cur_bucket;
    00260
    00261       // This loop requires the bucket array to have a non-null sentinel.
    00262       while (!*_M_cur_bucket)
    00263     ++_M_cur_bucket;
    00264       _M_cur_node = *_M_cur_bucket;
    00265     }
    00266
    00267   template<typename _Value, bool __cache>
    00268     inline bool
    00269     operator==(const _Hashtable_iterator_base<_Value, __cache>& __x,
    00270            const _Hashtable_iterator_base<_Value, __cache>& __y)
    00271     { return __x._M_cur_node == __y._M_cur_node; }
    00272
    00273   template<typename _Value, bool __cache>
    00274     inline bool
    00275     operator!=(const _Hashtable_iterator_base<_Value, __cache>& __x,
    00276            const _Hashtable_iterator_base<_Value, __cache>& __y)
    00277     { return __x._M_cur_node != __y._M_cur_node; }
    00278
    00279   template<typename _Value, bool __constant_iterators, bool __cache>
    00280     struct _Hashtable_iterator
    00281     : public _Hashtable_iterator_base<_Value, __cache>
    00282     {
    00283       typedef _Value                                   value_type;
    00284       typedef typename
    00285       __gnu_cxx::__conditional_type<__constant_iterators,
    00286                     const _Value*, _Value*>::__type
    00287                                                        pointer;
    00288       typedef typename
    00289       __gnu_cxx::__conditional_type<__constant_iterators,
    00290                     const _Value&, _Value&>::__type
    00291                                                        reference;
    00292       typedef std::ptrdiff_t                           difference_type;
    00293       typedef std::forward_iterator_tag                iterator_category;
    00294
    00295       _Hashtable_iterator()
    00296       : _Hashtable_iterator_base<_Value, __cache>(0, 0) { }
    00297
    00298       _Hashtable_iterator(_Hash_node<_Value, __cache>* __p,
    00299               _Hash_node<_Value, __cache>** __b)
    00300       : _Hashtable_iterator_base<_Value, __cache>(__p, __b) { }
    00301
    00302       explicit
    00303       _Hashtable_iterator(_Hash_node<_Value, __cache>** __b)
    00304       : _Hashtable_iterator_base<_Value, __cache>(*__b, __b) { }
    00305
    00306       reference
    00307       operator*() const
    00308       { return this->_M_cur_node->_M_v; }
    00309
    00310       pointer
    00311       operator->() const
    00312       { return &this->_M_cur_node->_M_v; }
    00313
    00314       _Hashtable_iterator&
    00315       operator++()
    00316       {
    00317     this->_M_incr();
    00318     return *this;
    00319       }
    00320
    00321       _Hashtable_iterator
    00322       operator++(int)
    00323       {
    00324     _Hashtable_iterator __tmp(*this);
    00325     this->_M_incr();
    00326     return __tmp;
    00327       }
    00328     };
    00329
    00330   template<typename _Value, bool __constant_iterators, bool __cache>
    00331     struct _Hashtable_const_iterator
    00332     : public _Hashtable_iterator_base<_Value, __cache>
    00333     {
    00334       typedef _Value                                   value_type;
    00335       typedef const _Value*                            pointer;
    00336       typedef const _Value&                            reference;
    00337       typedef std::ptrdiff_t                           difference_type;
    00338       typedef std::forward_iterator_tag                iterator_category;
    00339
    00340       _Hashtable_const_iterator()
    00341       : _Hashtable_iterator_base<_Value, __cache>(0, 0) { }
    00342
    00343       _Hashtable_const_iterator(_Hash_node<_Value, __cache>* __p,
    00344                 _Hash_node<_Value, __cache>** __b)
    00345       : _Hashtable_iterator_base<_Value, __cache>(__p, __b) { }
    00346
    00347       explicit
    00348       _Hashtable_const_iterator(_Hash_node<_Value, __cache>** __b)
    00349       : _Hashtable_iterator_base<_Value, __cache>(*__b, __b) { }
    00350
    00351       _Hashtable_const_iterator(const _Hashtable_iterator<_Value,
    00352                 __constant_iterators, __cache>& __x)
    00353       : _Hashtable_iterator_base<_Value, __cache>(__x._M_cur_node,
    00354                           __x._M_cur_bucket) { }
    00355
    00356       reference
    00357       operator*() const
    00358       { return this->_M_cur_node->_M_v; }
    00359
    00360       pointer
    00361       operator->() const
    00362       { return &this->_M_cur_node->_M_v; }
    00363
    00364       _Hashtable_const_iterator&
    00365       operator++()
    00366       {
    00367     this->_M_incr();
    00368     return *this;
    00369       }
    00370
    00371       _Hashtable_const_iterator
    00372       operator++(int)
    00373       {
    00374     _Hashtable_const_iterator __tmp(*this);
    00375     this->_M_incr();
    00376     return __tmp;
    00377       }
    00378     };
    00379
    00380
    00381   // Many of class template _Hashtable's template parameters are policy
    00382   // classes.  These are defaults for the policies.
    00383
    00384   // Default range hashing function: use division to fold a large number
    00385   // into the range [0, N).
    00386   struct _Mod_range_hashing
    00387   {
    00388     typedef std::size_t first_argument_type;
    00389     typedef std::size_t second_argument_type;
    00390     typedef std::size_t result_type;
    00391
    00392     result_type
    00393     operator()(first_argument_type __num, second_argument_type __den) const
    00394     { return __num % __den; }
    00395   };
    00396
    00397   // Default ranged hash function H.  In principle it should be a
    00398   // function object composed from objects of type H1 and H2 such that
    00399   // h(k, N) = h2(h1(k), N), but that would mean making extra copies of
    00400   // h1 and h2.  So instead we'll just use a tag to tell class template
    00401   // hashtable to do that composition.
    00402   struct _Default_ranged_hash { };
    00403
    00404   // Default value for rehash policy.  Bucket size is (usually) the
    00405   // smallest prime that keeps the load factor small enough.
    00406   struct _Prime_rehash_policy
    00407   {
    00408     _Prime_rehash_policy(float __z = 1.0)
    00409     : _M_max_load_factor(__z), _M_growth_factor(2.f), _M_next_resize(0) { }
    00410
    00411     float
    00412     max_load_factor() const
    00413     { return _M_max_load_factor; }
    00414
    00415     // Return a bucket size no smaller than n.
    00416     std::size_t
    00417     _M_next_bkt(std::size_t __n) const;
    00418
    00419     // Return a bucket count appropriate for n elements
    00420     std::size_t
    00421     _M_bkt_for_elements(std::size_t __n) const;
    00422
    00423     // __n_bkt is current bucket count, __n_elt is current element count,
    00424     // and __n_ins is number of elements to be inserted.  Do we need to
    00425     // increase bucket count?  If so, return make_pair(true, n), where n
    00426     // is the new bucket count.  If not, return make_pair(false, 0).
    00427     std::pair<bool, std::size_t>
    00428     _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt,
    00429            std::size_t __n_ins) const;
    00430
    00431     enum { _S_n_primes = sizeof(unsigned long) != 8 ? 256 : 256 + 48 };
    00432
    00433     float                _M_max_load_factor;
    00434     float                _M_growth_factor;
    00435     mutable std::size_t  _M_next_resize;
    00436   };
    00437
    00438   extern const unsigned long __prime_list[];
    00439
    00440   // XXX This is a hack.  There's no good reason for any of
    00441   // _Prime_rehash_policy's member functions to be inline.
    00442
    00443   // Return a prime no smaller than n.
    00444   inline std::size_t
    00445   _Prime_rehash_policy::
    00446   _M_next_bkt(std::size_t __n) const
    00447   {
    00448     const unsigned long* __p = __lower_bound(__prime_list, __prime_list
    00449                          + _S_n_primes, __n);
    00450     _M_next_resize =
    00451       static_cast<std::size_t>(__builtin_ceil(*__p * _M_max_load_factor));
    00452     return *__p;
    00453   }
    00454
    00455   // Return the smallest prime p such that alpha p >= n, where alpha
    00456   // is the load factor.
    00457   inline std::size_t
    00458   _Prime_rehash_policy::
    00459   _M_bkt_for_elements(std::size_t __n) const
    00460   {
    00461     const float __min_bkts = __n / _M_max_load_factor;
    00462     const unsigned long* __p = __lower_bound(__prime_list, __prime_list
    00463                          + _S_n_primes, __min_bkts);
    00464     _M_next_resize =
    00465       static_cast<std::size_t>(__builtin_ceil(*__p * _M_max_load_factor));
    00466     return *__p;
    00467   }
    00468
    00469   // Finds the smallest prime p such that alpha p > __n_elt + __n_ins.
    00470   // If p > __n_bkt, return make_pair(true, p); otherwise return
    00471   // make_pair(false, 0).  In principle this isn't very different from
    00472   // _M_bkt_for_elements.
    00473
    00474   // The only tricky part is that we're caching the element count at
    00475   // which we need to rehash, so we don't have to do a floating-point
    00476   // multiply for every insertion.
    00477
    00478   inline std::pair<bool, std::size_t>
    00479   _Prime_rehash_policy::
    00480   _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt,
    00481          std::size_t __n_ins) const
    00482   {
    00483     if (__n_elt + __n_ins > _M_next_resize)
    00484       {
    00485     float __min_bkts = ((float(__n_ins) + float(__n_elt))
    00486                 / _M_max_load_factor);
    00487     if (__min_bkts > __n_bkt)
    00488       {
    00489         __min_bkts = std::max(__min_bkts, _M_growth_factor * __n_bkt);
    00490         const unsigned long* __p =
    00491           __lower_bound(__prime_list, __prime_list + _S_n_primes,
    00492                 __min_bkts);
    00493         _M_next_resize = static_cast<std::size_t>
    00494           (__builtin_ceil(*__p * _M_max_load_factor));
    00495         return std::make_pair(true, *__p);
    00496       }
    00497     else
    00498       {
    00499         _M_next_resize = static_cast<std::size_t>
    00500           (__builtin_ceil(__n_bkt * _M_max_load_factor));
    00501         return std::make_pair(false, 0);
    00502       }
    00503       }
    00504     else
    00505       return std::make_pair(false, 0);
    00506   }
    00507
    00508   // Base classes for std::tr1::_Hashtable.  We define these base
    00509   // classes because in some cases we want to do different things
    00510   // depending on the value of a policy class.  In some cases the
    00511   // policy class affects which member functions and nested typedefs
    00512   // are defined; we handle that by specializing base class templates.
    00513   // Several of the base class templates need to access other members
    00514   // of class template _Hashtable, so we use the "curiously recurring
    00515   // template pattern" for them.
    00516
    00517   // class template _Map_base.  If the hashtable has a value type of the
    00518   // form pair<T1, T2> and a key extraction policy that returns the
    00519   // first part of the pair, the hashtable gets a mapped_type typedef.
    00520   // If it satisfies those criteria and also has unique keys, then it
    00521   // also gets an operator[].
    00522   template<typename _Key, typename _Value, typename _Ex, bool __unique,
    00523        typename _Hashtable>
    00524     struct _Map_base { };
    00525
    00526   template<typename _Key, typename _Pair, typename _Hashtable>
    00527     struct _Map_base<_Key, _Pair, std::_Select1st<_Pair>, false, _Hashtable>
    00528     {
    00529       typedef typename _Pair::second_type mapped_type;
    00530     };
    00531
    00532   template<typename _Key, typename _Pair, typename _Hashtable>
    00533   struct _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>
    00534     {
    00535       typedef typename _Pair::second_type mapped_type;
    00536
    00537       mapped_type&
    00538       operator[](const _Key& __k);
    00539     };
    00540
    00541   template<typename _Key, typename _Pair, typename _Hashtable>
    00542     typename _Map_base<_Key, _Pair, std::_Select1st<_Pair>,
    00543                true, _Hashtable>::mapped_type&
    00544     _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::
    00545     operator[](const _Key& __k)
    00546     {
    00547       _Hashtable* __h = static_cast<_Hashtable*>(this);
    00548       typename _Hashtable::_Hash_code_type __code = __h->_M_hash_code(__k);
    00549       std::size_t __n = __h->_M_bucket_index(__k, __code,
    00550                          __h->_M_bucket_count);
    00551
    00552       typename _Hashtable::_Node* __p =
    00553     __h->_M_find_node(__h->_M_buckets[__n], __k, __code);
    00554       if (!__p)
    00555     return __h->_M_insert_bucket(std::make_pair(__k, mapped_type()),
    00556                      __n, __code)->second;
    00557       return (__p->_M_v).second;
    00558     }
    00559
    00560   // class template _Rehash_base.  Give hashtable the max_load_factor
    00561   // functions iff the rehash policy is _Prime_rehash_policy.
    00562   template<typename _RehashPolicy, typename _Hashtable>
    00563     struct _Rehash_base { };
    00564
    00565   template<typename _Hashtable>
    00566     struct _Rehash_base<_Prime_rehash_policy, _Hashtable>
    00567     {
    00568       float
    00569       max_load_factor() const
    00570       {
    00571     const _Hashtable* __this = static_cast<const _Hashtable*>(this);
    00572     return __this->__rehash_policy().max_load_factor();
    00573       }
    00574
    00575       void
    00576       max_load_factor(float __z)
    00577       {
    00578     _Hashtable* __this = static_cast<_Hashtable*>(this);
    00579     __this->__rehash_policy(_Prime_rehash_policy(__z));
    00580       }
    00581     };
    00582
    00583   // Class template _Hash_code_base.  Encapsulates two policy issues that
    00584   // aren't quite orthogonal.
    00585   //   (1) the difference between using a ranged hash function and using
    00586   //       the combination of a hash function and a range-hashing function.
    00587   //       In the former case we don't have such things as hash codes, so
    00588   //       we have a dummy type as placeholder.
    00589   //   (2) Whether or not we cache hash codes.  Caching hash codes is
    00590   //       meaningless if we have a ranged hash function.
    00591   // We also put the key extraction and equality comparison function
    00592   // objects here, for convenience.
    00593
    00594   // Primary template: unused except as a hook for specializations.
    00595   template<typename _Key, typename _Value,
    00596        typename _ExtractKey, typename _Equal,
    00597        typename _H1, typename _H2, typename _Hash,
    00598        bool __cache_hash_code>
    00599     struct _Hash_code_base;
    00600
    00601   // Specialization: ranged hash function, no caching hash codes.  H1
    00602   // and H2 are provided but ignored.  We define a dummy hash code type.
    00603   template<typename _Key, typename _Value,
    00604        typename _ExtractKey, typename _Equal,
    00605        typename _H1, typename _H2, typename _Hash>
    00606     struct _Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2,
    00607                _Hash, false>
    00608     {
    00609     protected:
    00610       _Hash_code_base(const _ExtractKey& __ex, const _Equal& __eq,
    00611               const _H1&, const _H2&, const _Hash& __h)
    00612       : _M_extract(__ex), _M_eq(__eq), _M_ranged_hash(__h) { }
    00613
    00614       typedef void* _Hash_code_type;
    00615
    00616       _Hash_code_type
    00617       _M_hash_code(const _Key& __key) const
    00618       { return 0; }
    00619
    00620       std::size_t
    00621       _M_bucket_index(const _Key& __k, _Hash_code_type,
    00622               std::size_t __n) const
    00623       { return _M_ranged_hash(__k, __n); }
    00624
    00625       std::size_t
    00626       _M_bucket_index(const _Hash_node<_Value, false>* __p,
    00627               std::size_t __n) const
    00628       { return _M_ranged_hash(_M_extract(__p->_M_v), __n); }
    00629
    00630       bool
    00631       _M_compare(const _Key& __k, _Hash_code_type,
    00632          _Hash_node<_Value, false>* __n) const
    00633       { return _M_eq(__k, _M_extract(__n->_M_v)); }
    00634
    00635       void
    00636       _M_store_code(_Hash_node<_Value, false>*, _Hash_code_type) const
    00637       { }
    00638
    00639       void
    00640       _M_copy_code(_Hash_node<_Value, false>*,
    00641            const _Hash_node<_Value, false>*) const
    00642       { }
    00643
    00644       void
    00645       _M_swap(_Hash_code_base& __x)
    00646       {
    00647     std::swap(_M_extract, __x._M_extract);
    00648     std::swap(_M_eq, __x._M_eq);
    00649     std::swap(_M_ranged_hash, __x._M_ranged_hash);
    00650       }
    00651
    00652     protected:
    00653       _ExtractKey  _M_extract;
    00654       _Equal       _M_eq;
    00655       _Hash        _M_ranged_hash;
    00656     };
    00657
    00658
    00659   // No specialization for ranged hash function while caching hash codes.
    00660   // That combination is meaningless, and trying to do it is an error.
    00661
    00662
    00663   // Specialization: ranged hash function, cache hash codes.  This
    00664   // combination is meaningless, so we provide only a declaration
    00665   // and no definition.
    00666   template<typename _Key, typename _Value,
    00667        typename _ExtractKey, typename _Equal,
    00668        typename _H1, typename _H2, typename _Hash>
    00669     struct _Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2,
    00670                _Hash, true>;
    00671
    00672   // Specialization: hash function and range-hashing function, no
    00673   // caching of hash codes.  H is provided but ignored.  Provides
    00674   // typedef and accessor required by TR1.
    00675   template<typename _Key, typename _Value,
    00676        typename _ExtractKey, typename _Equal,
    00677        typename _H1, typename _H2>
    00678     struct _Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2,
    00679                _Default_ranged_hash, false>
    00680     {
    00681       typedef _H1 hasher;
    00682
    00683       hasher
    00684       hash_function() const
    00685       { return _M_h1; }
    00686
    00687     protected:
    00688       _Hash_code_base(const _ExtractKey& __ex, const _Equal& __eq,
    00689               const _H1& __h1, const _H2& __h2,
    00690               const _Default_ranged_hash&)
    00691       : _M_extract(__ex), _M_eq(__eq), _M_h1(__h1), _M_h2(__h2) { }
    00692
    00693       typedef std::size_t _Hash_code_type;
    00694
    00695       _Hash_code_type
    00696       _M_hash_code(const _Key& __k) const
    00697       { return _M_h1(__k); }
    00698
    00699       std::size_t
    00700       _M_bucket_index(const _Key&, _Hash_code_type __c,
    00701               std::size_t __n) const
    00702       { return _M_h2(__c, __n); }
    00703
    00704       std::size_t
    00705       _M_bucket_index(const _Hash_node<_Value, false>* __p,
    00706               std::size_t __n) const
    00707       { return _M_h2(_M_h1(_M_extract(__p->_M_v)), __n); }
    00708
    00709       bool
    00710       _M_compare(const _Key& __k, _Hash_code_type,
    00711          _Hash_node<_Value, false>* __n) const
    00712       { return _M_eq(__k, _M_extract(__n->_M_v)); }
    00713
    00714       void
    00715       _M_store_code(_Hash_node<_Value, false>*, _Hash_code_type) const
    00716       { }
    00717
    00718       void
    00719       _M_copy_code(_Hash_node<_Value, false>*,
    00720            const _Hash_node<_Value, false>*) const
    00721       { }
    00722
    00723       void
    00724       _M_swap(_Hash_code_base& __x)
    00725       {
    00726     std::swap(_M_extract, __x._M_extract);
    00727     std::swap(_M_eq, __x._M_eq);
    00728     std::swap(_M_h1, __x._M_h1);
    00729     std::swap(_M_h2, __x._M_h2);
    00730       }
    00731
    00732     protected:
    00733       _ExtractKey  _M_extract;
    00734       _Equal       _M_eq;
    00735       _H1          _M_h1;
    00736       _H2          _M_h2;
    00737     };
    00738
    00739   // Specialization: hash function and range-hashing function,
    00740   // caching hash codes.  H is provided but ignored.  Provides
    00741   // typedef and accessor required by TR1.
    00742   template<typename _Key, typename _Value,
    00743        typename _ExtractKey, typename _Equal,
    00744        typename _H1, typename _H2>
    00745     struct _Hash_code_base<_Key, _Value, _ExtractKey, _Equal, _H1, _H2,
    00746                _Default_ranged_hash, true>
    00747     {
    00748       typedef _H1 hasher;
    00749
    00750       hasher
    00751       hash_function() const
    00752       { return _M_h1; }
    00753
    00754     protected:
    00755       _Hash_code_base(const _ExtractKey& __ex, const _Equal& __eq,
    00756               const _H1& __h1, const _H2& __h2,
    00757               const _Default_ranged_hash&)
    00758       : _M_extract(__ex), _M_eq(__eq), _M_h1(__h1), _M_h2(__h2) { }
    00759
    00760       typedef std::size_t _Hash_code_type;
    00761
    00762       _Hash_code_type
    00763       _M_hash_code(const _Key& __k) const
    00764       { return _M_h1(__k); }
    00765
    00766       std::size_t
    00767       _M_bucket_index(const _Key&, _Hash_code_type __c,
    00768               std::size_t __n) const
    00769       { return _M_h2(__c, __n); }
    00770
    00771       std::size_t
    00772       _M_bucket_index(const _Hash_node<_Value, true>* __p,
    00773               std::size_t __n) const
    00774       { return _M_h2(__p->_M_hash_code, __n); }
    00775
    00776       bool
    00777       _M_compare(const _Key& __k, _Hash_code_type __c,
    00778          _Hash_node<_Value, true>* __n) const
    00779       { return __c == __n->_M_hash_code && _M_eq(__k, _M_extract(__n->_M_v)); }
    00780
    00781       void
    00782       _M_store_code(_Hash_node<_Value, true>* __n, _Hash_code_type __c) const
    00783       { __n->_M_hash_code = __c; }
    00784
    00785       void
    00786       _M_copy_code(_Hash_node<_Value, true>* __to,
    00787            const _Hash_node<_Value, true>* __from) const
    00788       { __to->_M_hash_code = __from->_M_hash_code; }
    00789
    00790       void
    00791       _M_swap(_Hash_code_base& __x)
    00792       {
    00793     std::swap(_M_extract, __x._M_extract);
    00794     std::swap(_M_eq, __x._M_eq);
    00795     std::swap(_M_h1, __x._M_h1);
    00796     std::swap(_M_h2, __x._M_h2);
    00797       }
    00798
    00799     protected:
    00800       _ExtractKey  _M_extract;
    00801       _Equal       _M_eq;
    00802       _H1          _M_h1;
    00803       _H2          _M_h2;
    00804     };
    00805 } // namespace __detail
    00806
    00807 _GLIBCXX_END_NAMESPACE_TR1
    00808 }