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 }

Generated on Wed Mar 26 00:42:58 2008 for libstdc++ by  doxygen 1.5.1