hashtable

Go to the documentation of this file.
00001 // Internal header for TR1 unordered_set and unordered_map -*- C++ -*-
00002 
00003 // Copyright (C) 2005 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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 
00031  *  This is a TR1 C++ Library header. 
00032  */
00033 
00034 // This header file defines std::tr1::hashtable, which is used to
00035 // implement std::tr1::unordered_set, std::tr1::unordered_map, 
00036 // std::tr1::unordered_multiset, and std::tr1::unordered_multimap.
00037 // hashtable has many template parameters, partly to accommodate
00038 // the differences between those four classes and partly to 
00039 // accommodate policy choices that go beyond what TR1 calls for.
00040 
00041 // ??? Arguably this should be Internal::hashtable, not std::tr1::hashtable.
00042 
00043 // Class template hashtable attempts to encapsulate all reasonable
00044 // variation among hash tables that use chaining.  It does not handle
00045 // open addressing.
00046 
00047 // References: 
00048 // M. Austern, "A Proposal to Add Hash Tables to the Standard
00049 //    Library (revision 4)," WG21 Document N1456=03-0039, 2003.
00050 // D. E. Knuth, The Art of Computer Programming, v. 3, Sorting and Searching.
00051 // A. Tavori and V. Dreizin, "Generic Associative Containers", 2004.
00052 //    ??? Full citation?
00053 
00054 #ifndef GNU_LIBSTDCXX_TR1_HASHTABLE_
00055 #define GNU_LIBSTDCXX_TR1_HASHTABLE_
00056 
00057 #include <utility>      // For std::pair
00058 #include <iterator>
00059 #include <cstddef>
00060 #include <cstdlib>
00061 #include <cmath>
00062 #include <tr1/type_traits>  // For true_type and false_type
00063 
00064 //----------------------------------------------------------------------
00065 // General utilities
00066 
00067 namespace Internal {
00068 template <bool Flag, typename IfTrue, typename IfFalse> struct IF;
00069 
00070 template <typename IfTrue, typename IfFalse>
00071 struct IF <true, IfTrue, IfFalse> { typedef IfTrue type; };
00072  
00073 template <typename IfTrue, typename IfFalse>
00074 struct IF <false, IfTrue, IfFalse> { typedef IfFalse type; };
00075 
00076 // Helper function: return distance(first, last) for forward
00077 // iterators, or 0 for input iterators.
00078 
00079 template <class Iterator>
00080 inline typename std::iterator_traits<Iterator>::difference_type
00081 distance_fw (Iterator first, Iterator last, std::input_iterator_tag)
00082 {
00083   return 0;
00084 }
00085 
00086 template <class Iterator>
00087 inline typename std::iterator_traits<Iterator>::difference_type
00088 distance_fw (Iterator first, Iterator last, std::forward_iterator_tag)
00089 {
00090   return std::distance(first, last);
00091 }
00092 
00093 template <class Iterator>
00094 inline typename std::iterator_traits<Iterator>::difference_type
00095 distance_fw (Iterator first, Iterator last)
00096 {
00097   typedef typename std::iterator_traits<Iterator>::iterator_category tag;
00098   return distance_fw(first, last, tag());
00099 }
00100 
00101 } // namespace Internal
00102 
00103 //----------------------------------------------------------------------
00104 // Auxiliary types used for all instantiations of hashtable: nodes
00105 // and iterators.
00106 
00107 // Nodes, used to wrap elements stored in the hash table.  A policy
00108 // template parameter of class template hashtable controls whether
00109 // nodes also store a hash code. In some cases (e.g. strings) this may
00110 // be a performance win.
00111 
00112 namespace Internal {
00113 
00114 template <typename Value, bool cache_hash_code> struct hash_node;
00115 
00116 template <typename Value>
00117 struct hash_node<Value, true> {
00118   Value m_v;
00119   std::size_t hash_code;
00120   hash_node* m_next;
00121 };
00122 
00123 template <typename Value>
00124 struct hash_node<Value, false> {
00125   Value m_v;
00126   hash_node* m_next;
00127 };
00128 
00129 // Local iterators, used to iterate within a bucket but not between
00130 // buckets.
00131 
00132 template <typename Value, bool cache>
00133 struct node_iterator_base {
00134   node_iterator_base(hash_node<Value, cache>* p) : m_cur(p) { }
00135   void incr() { m_cur = m_cur->m_next; }
00136 
00137   hash_node<Value, cache>* m_cur;
00138 };
00139 
00140 template <typename Value, bool cache>
00141 inline bool operator== (const node_iterator_base<Value, cache>& x,
00142             const node_iterator_base<Value, cache>& y)
00143 {
00144   return x.m_cur == y.m_cur;
00145 }
00146 
00147 template <typename Value, bool cache>
00148 inline bool operator!= (const node_iterator_base<Value, cache>& x,
00149             const node_iterator_base<Value, cache>& y)
00150 {
00151   return x.m_cur != y.m_cur;
00152 }
00153 
00154 template <typename Value, bool is_const, bool cache>
00155 struct node_iterator : public node_iterator_base<Value, cache> {
00156   typedef Value                                             value_type;
00157   typedef typename IF<is_const, const Value*, Value*>::type pointer;
00158   typedef typename IF<is_const, const Value&, Value&>::type reference;
00159   typedef std::ptrdiff_t                                    difference_type;
00160   typedef std::forward_iterator_tag                         iterator_category;
00161 
00162   explicit node_iterator (hash_node<Value, cache>* p = 0)
00163     : node_iterator_base<Value, cache>(p) { }
00164   node_iterator (const node_iterator<Value, true, cache>& x)
00165     : node_iterator_base<Value, cache>(x.m_cur) { }
00166 
00167   reference operator*() const { return this->m_cur->m_v; }
00168   pointer operator->() const { return &this->m_cur->m_v; }
00169 
00170   node_iterator& operator++() { this->incr(); return *this; }
00171   node_iterator operator++(int)
00172   { node_iterator tmp(*this); this->incr(); return tmp; }
00173 };
00174 
00175 template <typename Value, bool cache>
00176 struct hashtable_iterator_base {
00177   hashtable_iterator_base(hash_node<Value, cache>* node,
00178               hash_node<Value, cache>** bucket)
00179     : m_cur_node (node), m_cur_bucket (bucket)
00180   { }
00181 
00182   void incr() {
00183     m_cur_node = m_cur_node->m_next;
00184     if (!m_cur_node)
00185       m_incr_bucket();
00186   }
00187 
00188   void m_incr_bucket();
00189 
00190   hash_node<Value, cache>* m_cur_node;
00191   hash_node<Value, cache>** m_cur_bucket;
00192 };
00193 
00194 
00195 // Global iterators, used for arbitrary iteration within a hash
00196 // table.  Larger and more expensive than local iterators.
00197 
00198 template <typename Value, bool cache>
00199 void hashtable_iterator_base<Value, cache>::m_incr_bucket()
00200 {
00201   ++m_cur_bucket;
00202 
00203   // This loop requires the bucket array to have a non-null sentinel
00204   while (!*m_cur_bucket)
00205     ++m_cur_bucket;
00206   m_cur_node = *m_cur_bucket;
00207 }
00208 
00209 template <typename Value, bool cache>
00210 inline bool operator== (const hashtable_iterator_base<Value, cache>& x,
00211             const hashtable_iterator_base<Value, cache>& y)
00212 {
00213   return x.m_cur_node == y.m_cur_node;
00214 }
00215 
00216 template <typename Value, bool cache>
00217 inline bool operator!= (const hashtable_iterator_base<Value, cache>& x,
00218             const hashtable_iterator_base<Value, cache>& y)
00219 {
00220   return x.m_cur_node != y.m_cur_node;
00221 }
00222 
00223 template <typename Value, bool is_const, bool cache>
00224 struct hashtable_iterator : public hashtable_iterator_base<Value, cache>
00225 {
00226   typedef Value                                             value_type;
00227   typedef typename IF<is_const, const Value*, Value*>::type pointer;
00228   typedef typename IF<is_const, const Value&, Value&>::type reference;
00229   typedef std::ptrdiff_t                                    difference_type;
00230   typedef std::forward_iterator_tag                         iterator_category;
00231 
00232   hashtable_iterator (hash_node<Value, cache>* p, hash_node<Value, cache>** b)
00233     : hashtable_iterator_base<Value, cache>(p, b) { }
00234   hashtable_iterator (hash_node<Value, cache>** b)
00235     : hashtable_iterator_base<Value, cache>(*b, b) { }
00236   hashtable_iterator (const hashtable_iterator<Value, true, cache>& x)
00237     : hashtable_iterator_base<Value, cache>(x.m_cur_node, x.m_cur_bucket) { }
00238 
00239   reference operator*() const { return this->m_cur_node->m_v; }
00240   pointer operator->() const { return &this->m_cur_node->m_v; }
00241 
00242   hashtable_iterator& operator++() { this->incr(); return *this; }
00243   hashtable_iterator operator++(int)
00244   { hashtable_iterator tmp(*this); this->incr(); return tmp; }
00245 };
00246 
00247 } // namespace Internal
00248 
00249 // ----------------------------------------------------------------------
00250 // Many of class template hashtable's template parameters are policy
00251 // classes.  These are defaults for the policies.
00252 
00253 namespace Internal {
00254 
00255 // The two key extraction policies used by the *set and *map variants.
00256 template <typename T>
00257 struct identity {
00258   T operator()(const T& t) const { return t; }
00259 };
00260 
00261 template <typename Pair>
00262 struct extract1st {
00263   typename Pair::first_type operator()(const Pair& p) const { return p.first; }
00264 };
00265 
00266 // Default range hashing function: use division to fold a large number
00267 // into the range [0, N).
00268 struct mod_range_hashing
00269 {
00270   typedef std::size_t first_argument_type;
00271   typedef std::size_t second_argument_type;
00272   typedef std::size_t result_type;
00273 
00274   result_type operator() (first_argument_type r, second_argument_type N) const
00275     { return r % N; }
00276 };
00277 
00278 // Default ranged hash function H.  In principle it should be a
00279 // function object composed from objects of type H1 and H2 such that
00280 // h(k, N) = h2(h1(k), N), but that would mean making extra copies of
00281 // h1 and h2.  So instead we'll just use a tag to tell class template
00282 // hashtable to do that composition.
00283 struct default_ranged_hash { };
00284 
00285 // Default value for rehash policy.  Bucket size is (usually) the
00286 // smallest prime that keeps the load factor small enough.
00287 
00288 struct prime_rehash_policy
00289 {
00290   prime_rehash_policy (float z = 1.0);
00291 
00292   float max_load_factor() const;
00293 
00294   // Return a bucket size no smaller than n.
00295   std::size_t next_bkt (std::size_t n) const;
00296 
00297   // Return a bucket count appropriate for n elements
00298   std::size_t bkt_for_elements (std::size_t n) const;
00299 
00300   // n_bkt is current bucket count, n_elt is current element count,
00301   // and n_ins is number of elements to be inserted.  Do we need to
00302   // increase bucket count?  If so, return make_pair(true, n), where n
00303   // is the new bucket count.  If not, return make_pair(false, 0).
00304   std::pair<bool, std::size_t>
00305   need_rehash (std::size_t n_bkt, std::size_t n_elt, std::size_t n_ins) const;
00306 
00307   float m_max_load_factor;
00308   float m_growth_factor;
00309   mutable std::size_t m_next_resize;
00310 };
00311 
00312 // XXX This is a hack.  prime_rehash_policy's member functions, and
00313 // certainly the list of primes, should be defined in a .cc file.
00314 // We're temporarily putting them in a header because we don't have a
00315 // place to put TR1 .cc files yet.  There's no good reason for any of
00316 // prime_rehash_policy's member functions to be inline, and there's
00317 // certainly no good reason for X<> to exist at all.
00318 
00319 struct lt {
00320   template <typename X, typename Y> bool operator()(X x, Y y) { return x < y; }
00321 };
00322 
00323 template <int dummy>
00324 struct X {
00325   static const int n_primes = 256;
00326   static const unsigned long primes[n_primes + 1];
00327 };
00328 
00329 template <int dummy>
00330 const int X<dummy>::n_primes;
00331 
00332 template <int dummy>
00333 const unsigned long X<dummy>::primes[n_primes + 1] =
00334   {
00335     2ul, 3ul, 5ul, 7ul, 11ul, 13ul, 17ul, 19ul, 23ul, 29ul, 31ul,
00336     37ul, 41ul, 43ul, 47ul, 53ul, 59ul, 61ul, 67ul, 71ul, 73ul, 79ul,
00337     83ul, 89ul, 97ul, 103ul, 109ul, 113ul, 127ul, 137ul, 139ul, 149ul,
00338     157ul, 167ul, 179ul, 193ul, 199ul, 211ul, 227ul, 241ul, 257ul,
00339     277ul, 293ul, 313ul, 337ul, 359ul, 383ul, 409ul, 439ul, 467ul,
00340     503ul, 541ul, 577ul, 619ul, 661ul, 709ul, 761ul, 823ul, 887ul,
00341     953ul, 1031ul, 1109ul, 1193ul, 1289ul, 1381ul, 1493ul, 1613ul,
00342     1741ul, 1879ul, 2029ul, 2179ul, 2357ul, 2549ul, 2753ul, 2971ul,
00343     3209ul, 3469ul, 3739ul, 4027ul, 4349ul, 4703ul, 5087ul, 5503ul,
00344     5953ul, 6427ul, 6949ul, 7517ul, 8123ul, 8783ul, 9497ul, 10273ul,
00345     11113ul, 12011ul, 12983ul, 14033ul, 15173ul, 16411ul, 17749ul,
00346     19183ul, 20753ul, 22447ul, 24281ul, 26267ul, 28411ul, 30727ul,
00347     33223ul, 35933ul, 38873ul, 42043ul, 45481ul, 49201ul, 53201ul,
00348     57557ul, 62233ul, 67307ul, 72817ul, 78779ul, 85229ul, 92203ul,
00349     99733ul, 107897ul, 116731ul, 126271ul, 136607ul, 147793ul,
00350     159871ul, 172933ul, 187091ul, 202409ul, 218971ul, 236897ul,
00351     256279ul, 277261ul, 299951ul, 324503ul, 351061ul, 379787ul,
00352     410857ul, 444487ul, 480881ul, 520241ul, 562841ul, 608903ul,
00353     658753ul, 712697ul, 771049ul, 834181ul, 902483ul, 976369ul,
00354     1056323ul, 1142821ul, 1236397ul, 1337629ul, 1447153ul, 1565659ul,
00355     1693859ul, 1832561ul, 1982627ul, 2144977ul, 2320627ul, 2510653ul,
00356     2716249ul, 2938679ul, 3179303ul, 3439651ul, 3721303ul, 4026031ul,
00357     4355707ul, 4712381ul, 5098259ul, 5515729ul, 5967347ul, 6456007ul,
00358     6984629ul, 7556579ul, 8175383ul, 8844859ul, 9569143ul, 10352717ul,
00359     11200489ul, 12117689ul, 13109983ul, 14183539ul, 15345007ul,
00360     16601593ul, 17961079ul, 19431899ul, 21023161ul, 22744717ul,
00361     24607243ul, 26622317ul, 28802401ul, 31160981ul, 33712729ul,
00362     36473443ul, 39460231ul, 42691603ul, 46187573ul, 49969847ul,
00363     54061849ul, 58488943ul, 63278561ul, 68460391ul, 74066549ul,
00364     80131819ul, 86693767ul, 93793069ul, 101473717ul, 109783337ul,
00365     118773397ul, 128499677ul, 139022417ul, 150406843ul, 162723577ul,
00366     176048909ul, 190465427ul, 206062531ul, 222936881ul, 241193053ul,
00367     260944219ul, 282312799ul, 305431229ul, 330442829ul, 357502601ul,
00368     386778277ul, 418451333ul, 452718089ul, 489790921ul, 529899637ul,
00369     573292817ul, 620239453ul, 671030513ul, 725980837ul, 785430967ul,
00370     849749479ul, 919334987ul, 994618837ul, 1076067617ul, 1164186217ul,
00371     1259520799ul, 1362662261ul, 1474249943ul, 1594975441ul,
00372     1725587117ul, 1866894511ul, 2019773507ul, 2185171673ul,
00373     2364114217ul, 2557710269ul, 2767159799ul, 2993761039ul,
00374     3238918481ul, 3504151727ul, 3791104843ul, 4101556399ul,
00375     4294967291ul,
00376     4294967291ul // sentinel so we don't have to test result of lower_bound
00377   };
00378 
00379 inline prime_rehash_policy::prime_rehash_policy (float z)
00380   : m_max_load_factor(z),
00381     m_growth_factor (2.f),
00382     m_next_resize (0)
00383 { }
00384 
00385 inline float prime_rehash_policy::max_load_factor() const
00386 {
00387   return m_max_load_factor;
00388 }
00389 
00390 // Return a prime no smaller than n.
00391 inline std::size_t prime_rehash_policy::next_bkt (std::size_t n) const
00392 {
00393   const unsigned long* const last = X<0>::primes + X<0>::n_primes;
00394   const unsigned long* p = std::lower_bound (X<0>::primes, last, n);
00395   m_next_resize = static_cast<std::size_t>(std::ceil(*p * m_max_load_factor));
00396   return *p;
00397 }
00398 
00399 // Return the smallest prime p such that alpha p >= n, where alpha
00400 // is the load factor.
00401 inline std::size_t prime_rehash_policy::bkt_for_elements (std::size_t n) const
00402 {
00403   const unsigned long* const last = X<0>::primes + X<0>::n_primes;
00404   const float min_bkts = n / m_max_load_factor;
00405   const unsigned long* p = std::lower_bound (X<0>::primes, last, min_bkts, lt());
00406   m_next_resize = static_cast<std::size_t>(std::ceil(*p * m_max_load_factor));
00407   return *p;
00408 }
00409 
00410 // Finds the smallest prime p such that alpha p > n_elt + n_ins.
00411 // If p > n_bkt, return make_pair(true, p); otherwise return
00412 // make_pair(false, 0).  In principle this isn't very different from 
00413 // bkt_for_elements.
00414 
00415 // The only tricky part is that we're caching the element count at
00416 // which we need to rehash, so we don't have to do a floating-point
00417 // multiply for every insertion.
00418 
00419 inline std::pair<bool, std::size_t>
00420 prime_rehash_policy
00421 ::need_rehash (std::size_t n_bkt, std::size_t n_elt, std::size_t n_ins) const
00422 {
00423   if (n_elt + n_ins > m_next_resize) {
00424     float min_bkts = (float(n_ins) + float(n_elt)) / m_max_load_factor;
00425     if (min_bkts > n_bkt) {
00426       min_bkts = std::max (min_bkts, m_growth_factor * n_bkt);
00427       const unsigned long* const last = X<0>::primes + X<0>::n_primes;
00428       const unsigned long* p = std::lower_bound (X<0>::primes, last, min_bkts, lt());
00429       m_next_resize = static_cast<std::size_t>(std::ceil(*p * m_max_load_factor));
00430       return std::make_pair(true, *p);
00431     }
00432     else {
00433       m_next_resize = static_cast<std::size_t>(std::ceil(n_bkt * m_max_load_factor));
00434       return std::make_pair(false, 0);
00435     }
00436   }
00437   else
00438     return std::make_pair(false, 0);
00439 }
00440 
00441 } // namespace Internal
00442 
00443 //----------------------------------------------------------------------
00444 // Base classes for std::tr1::hashtable.  We define these base classes
00445 // because in some cases we want to do different things depending on
00446 // the value of a policy class.  In some cases the policy class affects
00447 // which member functions and nested typedefs are defined; we handle that
00448 // by specializing base class templates.  Several of the base class templates
00449 // need to access other members of class template hashtable, so we use
00450 // the "curiously recurring template pattern" for them.
00451 
00452 namespace Internal {
00453 
00454 // class template map_base.  If the hashtable has a value type of the
00455 // form pair<T1, T2> and a key extraction policy that returns the
00456 // first part of the pair, the hashtable gets a mapped_type typedef.
00457 // If it satisfies those criteria and also has unique keys, then it
00458 // also gets an operator[].
00459 
00460 template <typename K, typename V, typename Ex, bool unique, typename Hashtable>
00461 struct map_base { };
00462       
00463 template <typename K, typename Pair, typename Hashtable>
00464 struct map_base<K, Pair, extract1st<Pair>, false, Hashtable>
00465 {
00466   typedef typename Pair::second_type mapped_type;
00467 };
00468 
00469 template <typename K, typename Pair, typename Hashtable>
00470 struct map_base<K, Pair, extract1st<Pair>, true, Hashtable>
00471 {
00472   typedef typename Pair::second_type mapped_type;
00473   mapped_type& operator[](const K& k) {
00474     Hashtable* h = static_cast<Hashtable*>(this);
00475     typename Hashtable::iterator it = h->insert(std::make_pair(k, mapped_type())).first;
00476     return it->second;
00477   }
00478 };
00479 
00480 // class template rehash_base.  Give hashtable the max_load_factor
00481 // functions iff the rehash policy is prime_rehash_policy.
00482 template <typename RehashPolicy, typename Hashtable>
00483 struct rehash_base { };
00484 
00485 template <typename Hashtable>
00486 struct rehash_base<prime_rehash_policy, Hashtable>
00487 {
00488   float max_load_factor() const {
00489     const Hashtable* This = static_cast<const Hashtable*>(this);
00490     return This->rehash_policy()->max_load_factor();
00491   }
00492 
00493   void max_load_factor(float z) {
00494     Hashtable* This = static_cast<Hashtable*>(this);
00495     This->rehash_policy(prime_rehash_policy(z));    
00496   }
00497 };
00498 
00499 // Class template hash_code_base.  Encapsulates two policy issues that
00500 // aren't quite orthogonal.
00501 //   (1) the difference between using a ranged hash function and using
00502 //       the combination of a hash function and a range-hashing function.
00503 //       In the former case we don't have such things as hash codes, so
00504 //       we have a dummy type as placeholder.
00505 //   (2) Whether or not we cache hash codes.  Caching hash codes is
00506 //       meaningless if we have a ranged hash function.
00507 // We also put the key extraction and equality comparison function 
00508 // objects here, for convenience.
00509 
00510 // Primary template: unused except as a hook for specializations.
00511 
00512 template <typename Key, typename Value,
00513       typename ExtractKey, typename Equal,
00514       typename H1, typename H2, typename H,
00515       bool cache_hash_code>
00516 struct hash_code_base;
00517 
00518 // Specialization: ranged hash function, no caching hash codes.  H1
00519 // and H2 are provided but ignored.  We define a dummy hash code type.
00520 template <typename Key, typename Value,
00521       typename ExtractKey, typename Equal,
00522       typename H1, typename H2, typename H>
00523 struct hash_code_base <Key, Value, ExtractKey, Equal, H1, H2, H, false>
00524 {
00525 protected:
00526   hash_code_base (const ExtractKey& ex, const Equal& eq,
00527             const H1&, const H2&, const H& h)
00528     : m_extract(ex), m_eq(eq), m_ranged_hash(h) { }
00529 
00530   typedef void* hash_code_t;
00531   hash_code_t m_hash_code (const Key& k) const { return 0; }
00532   std::size_t bucket_index (const Key& k, hash_code_t, std::size_t N) const
00533     { return m_ranged_hash (k, N); }
00534   std::size_t bucket_index (const hash_node<Value, false>* p, std::size_t N) const {
00535     return m_ranged_hash (m_extract (p->m_v), N); 
00536   }
00537   
00538   bool compare (const Key& k, hash_code_t, hash_node<Value, false>* n) const
00539     { return m_eq (k, m_extract(n->m_v)); }
00540 
00541   void copy_code (hash_node<Value, false>*, const hash_node<Value, false>*) const { }
00542 
00543   void m_swap(hash_code_base& x) {
00544     m_extract.m_swap(x);
00545     m_eq.m_swap(x);
00546     m_ranged_hash.m_swap(x);
00547   }
00548 
00549 protected:
00550   ExtractKey m_extract;
00551   Equal m_eq;
00552   H m_ranged_hash;
00553 };
00554 
00555 
00556 // No specialization for ranged hash function while caching hash codes.
00557 // That combination is meaningless, and trying to do it is an error.
00558 
00559 
00560 // Specialization: ranged hash function, cache hash codes.  This
00561 // combination is meaningless, so we provide only a declaration
00562 // and no definition.
00563 
00564 template <typename Key, typename Value,
00565       typename ExtractKey, typename Equal,
00566       typename H1, typename H2, typename H>
00567 struct hash_code_base <Key, Value, ExtractKey, Equal, H1, H2, H, true>;
00568 
00569 
00570 // Specialization: hash function and range-hashing function, no
00571 // caching of hash codes.  H is provided but ignored.  Provides
00572 // typedef and accessor required by TR1.
00573 
00574 template <typename Key, typename Value,
00575       typename ExtractKey, typename Equal,
00576       typename H1, typename H2>
00577 struct hash_code_base <Key, Value, ExtractKey, Equal, H1, H2, default_ranged_hash, false>
00578 {
00579   typedef H1 hasher;
00580   hasher hash_function() const { return m_h1; }
00581 
00582 protected:
00583   hash_code_base (const ExtractKey& ex, const Equal& eq,
00584           const H1& h1, const H2& h2, const default_ranged_hash&)
00585     : m_extract(ex), m_eq(eq), m_h1(h1), m_h2(h2) { }
00586 
00587   typedef std::size_t hash_code_t;
00588   hash_code_t m_hash_code (const Key& k) const { return m_h1(k); }
00589   std::size_t bucket_index (const Key&, hash_code_t c, std::size_t N) const
00590     { return m_h2 (c, N); }
00591   std::size_t bucket_index (const hash_node<Value, false>* p, std::size_t N) const {
00592     return m_h2 (m_h1 (m_extract (p->m_v)), N);
00593   }
00594 
00595   bool compare (const Key& k, hash_code_t,  hash_node<Value, false>* n) const
00596     { return m_eq (k, m_extract(n->m_v)); }
00597 
00598   void copy_code (hash_node<Value, false>*, const hash_node<Value, false>*) const { }
00599 
00600   void m_swap(hash_code_base& x) {
00601     m_extract.m_swap(x);
00602     m_eq.m_swap(x);
00603     m_h1.m_swap(x);
00604     m_h2.m_swap(x);
00605   }
00606 
00607 protected:
00608   ExtractKey m_extract;
00609   Equal m_eq;
00610   H1 m_h1;
00611   H2 m_h2;
00612 };
00613 
00614 // Specialization: hash function and range-hashing function, 
00615 // caching hash codes.  H is provided but ignored.  Provides
00616 // typedef and accessor required by TR1.
00617 template <typename Key, typename Value,
00618       typename ExtractKey, typename Equal,
00619       typename H1, typename H2>
00620 struct hash_code_base <Key, Value, ExtractKey, Equal, H1, H2, default_ranged_hash, true>
00621 {
00622   typedef H1 hasher;
00623   hasher hash_function() const { return m_h1; }
00624 
00625 protected:
00626   hash_code_base (const ExtractKey& ex, const Equal& eq,
00627             const H1& h1, const H2& h2, const default_ranged_hash&)
00628     : m_extract(ex), m_eq(eq), m_h1(h1), m_h2(h2) { }
00629 
00630   typedef std::size_t hash_code_t;
00631   hash_code_t m_hash_code (const Key& k) const { return m_h1(k); }
00632   std::size_t bucket_index (const Key&, hash_code_t c, std::size_t N) const
00633     { return m_h2 (c, N); }
00634 
00635   std::size_t bucket_index (const hash_node<Value, true>* p, std::size_t N) const {
00636     return m_h2 (p->hash_code, N);
00637   }
00638 
00639   bool compare (const Key& k, hash_code_t c,  hash_node<Value, true>* n) const
00640     { return c == n->hash_code && m_eq (k, m_extract(n->m_v)); }
00641 
00642   void copy_code (hash_node<Value, true>* to, const hash_node<Value, true>* from) const
00643     { to->hash_code = from->hash_code; }
00644 
00645   void m_swap(hash_code_base& x) {
00646     m_extract.m_swap(x);
00647     m_eq.m_swap(x);
00648     m_h1.m_swap(x);
00649     m_h2.m_swap(x);
00650   }
00651 
00652 protected:
00653   ExtractKey m_extract;
00654   Equal m_eq;
00655   H1 m_h1;
00656   H2 m_h2;
00657 };
00658 
00659 } // namespace internal
00660 
00661 namespace std { namespace tr1 {
00662 
00663 //----------------------------------------------------------------------
00664 // Class template hashtable, class definition.
00665 
00666 // Meaning of class template hashtable's template parameters
00667 
00668 // Key and Value: arbitrary CopyConstructible types.
00669 
00670 // Allocator: an allocator type ([lib.allocator.requirements]) whose
00671 // value type is Value.
00672 
00673 // ExtractKey: function object that takes a object of type Value
00674 // and returns a value of type Key.
00675 
00676 // Equal: function object that takes two objects of type k and returns
00677 // a bool-like value that is true if the two objects are considered equal.
00678 
00679 // H1: the hash function.  A unary function object with argument type
00680 // Key and result type size_t.  Return values should be distributed
00681 // over the entire range [0, numeric_limits<size_t>:::max()].
00682 
00683 // H2: the range-hashing function (in the terminology of Tavori and
00684 // Dreizin).  A binary function object whose argument types and result
00685 // type are all size_t.  Given arguments r and N, the return value is
00686 // in the range [0, N).
00687 
00688 // H: the ranged hash function (Tavori and Dreizin). A binary function
00689 // whose argument types are Key and size_t and whose result type is
00690 // size_t.  Given arguments k and N, the return value is in the range
00691 // [0, N).  Default: h(k, N) = h2(h1(k), N).  If H is anything other
00692 // than the default, H1 and H2 are ignored.
00693 
00694 // RehashPolicy: Policy class with three members, all of which govern
00695 // the bucket count. n_bkt(n) returns a bucket count no smaller
00696 // than n.  bkt_for_elements(n) returns a bucket count appropriate
00697 // for an element count of n.  need_rehash(n_bkt, n_elt, n_ins)
00698 // determines whether, if the current bucket count is n_bkt and the
00699 // current element count is n_elt, we need to increase the bucket
00700 // count.  If so, returns make_pair(true, n), where n is the new
00701 // bucket count.  If not, returns make_pair(false, <anything>).
00702 
00703 // ??? Right now it is hard-wired that the number of buckets never
00704 // shrinks.  Should we allow RehashPolicy to change that?
00705 
00706 // cache_hash_code: bool.  true if we store the value of the hash
00707 // function along with the value.  This is a time-space tradeoff.
00708 // Storing it may improve lookup speed by reducing the number of times
00709 // we need to call the Equal function.
00710 
00711 // mutable_iterators: bool.  true if hashtable::iterator is a mutable
00712 // iterator, false if iterator and const_iterator are both const 
00713 // iterators.  This is true for unordered_map and unordered_multimap,
00714 // false for unordered_set and unordered_multiset.
00715 
00716 // unique_keys: bool.  true if the return value of hashtable::count(k)
00717 // is always at most one, false if it may be an arbitrary number.  This
00718 // true for unordered_set and unordered_map, false for unordered_multiset
00719 // and unordered_multimap.
00720 
00721 template <typename Key, typename Value, 
00722       typename Allocator,
00723       typename ExtractKey, typename Equal,
00724       typename H1, typename H2,
00725       typename H, typename RehashPolicy,
00726       bool cache_hash_code,
00727       bool mutable_iterators,
00728       bool unique_keys>
00729 class hashtable
00730   : public Internal::rehash_base<RehashPolicy, hashtable<Key, Value, Allocator, ExtractKey, Equal, H1, H2, H, RehashPolicy, cache_hash_code, mutable_iterators, unique_keys> >,
00731     public Internal::hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H, cache_hash_code>,
00732     public Internal::map_base<Key, Value, ExtractKey, unique_keys, hashtable<Key, Value, Allocator, ExtractKey, Equal, H1, H2, H, RehashPolicy, cache_hash_code, mutable_iterators, unique_keys> >
00733 {
00734 public:
00735   typedef Allocator                           allocator_type;
00736   typedef Value                               value_type;
00737   typedef Key                                 key_type;
00738   typedef Equal                               key_equal;
00739   // mapped_type, if present, comes from map_base.
00740   // hasher, if present, comes from hash_code_base.
00741   typedef typename Allocator::difference_type difference_type;
00742   typedef typename Allocator::size_type       size_type;
00743   typedef typename Allocator::reference       reference;
00744   typedef typename Allocator::const_reference const_reference;
00745 
00746   typedef Internal::node_iterator<value_type, !mutable_iterators, cache_hash_code>
00747           local_iterator;
00748   typedef Internal::node_iterator<value_type, false,              cache_hash_code>
00749           const_local_iterator;
00750 
00751   typedef Internal::hashtable_iterator<value_type, !mutable_iterators, cache_hash_code>
00752           iterator;
00753   typedef Internal::hashtable_iterator<value_type, false,              cache_hash_code>
00754           const_iterator;
00755 
00756 private:
00757   typedef Internal::hash_node<Value, cache_hash_code>                 node;
00758   typedef typename Allocator::template rebind<node>::other  node_allocator_t;
00759   typedef typename Allocator::template rebind<node*>::other bucket_allocator_t;
00760 
00761 private:
00762   node_allocator_t m_node_allocator;
00763   node** m_buckets;
00764   size_type m_bucket_count;
00765   size_type m_element_count;
00766   RehashPolicy m_rehash_policy;
00767 
00768   node* m_allocate_node (const value_type& v);
00769   void m_deallocate_node (node* n);
00770   void m_deallocate_nodes (node**, size_type);
00771 
00772   node** m_allocate_buckets (size_type n);
00773   void m_deallocate_buckets (node**, size_type n);
00774 
00775 public:             // Constructor, destructor, assignment, swap
00776   hashtable(size_type bucket_hint,
00777         const H1&, const H2&, const H&,
00778         const Equal&, const ExtractKey&,
00779         const allocator_type&);
00780   
00781   template <typename InIter>
00782   hashtable(InIter first, InIter last,
00783         size_type bucket_hint,
00784         const H1&, const H2&, const H&,
00785         const Equal&, const ExtractKey&,
00786         const allocator_type&);
00787   
00788   hashtable(const hashtable&);
00789   hashtable& operator=(const hashtable&);
00790   ~hashtable();
00791 
00792   void swap(hashtable&);
00793 
00794 public:             // Basic container operations
00795   iterator       begin() {
00796     iterator i(m_buckets);
00797     if (!i.m_cur_node)
00798       i.m_incr_bucket();
00799     return i;
00800   }
00801 
00802   const_iterator begin() const {
00803     const_iterator i(m_buckets);
00804     if (!i.m_cur_node)
00805       i.m_incr_bucket();
00806     return i;
00807   }
00808 
00809   iterator       end()
00810     { return iterator(m_buckets + m_bucket_count); }
00811   const_iterator end() const
00812     { return const_iterator(m_buckets + m_bucket_count); }
00813 
00814   size_type size() const { return m_element_count; }
00815   bool empty() const { return size() == 0; }
00816 
00817   allocator_type get_allocator() const { return m_node_allocator; }
00818   size_type max_size() const { return m_node_allocator.max_size(); }
00819 
00820 public:             // Bucket operations
00821   size_type bucket_count() const
00822     { return m_bucket_count; }
00823   size_type max_bucket_count() const
00824     { return max_size(); }
00825   size_type bucket_size (size_type n) const
00826     { return std::distance(begin(n), end(n)); }
00827   size_type bucket (const key_type& k) const
00828     { return this->bucket_index (k, this->m_hash_code, this->m_bucket_count); }
00829 
00830   local_iterator begin(size_type n)
00831     { return local_iterator(m_buckets[n]); }
00832   local_iterator end(size_type n)
00833     { return local_iterator(0); }
00834   const_local_iterator begin(size_type n) const
00835     { return const_local_iterator(m_buckets[n]); }
00836   const_local_iterator end(size_type n) const
00837     { return const_local_iterator(0); }
00838 
00839   float load_factor() const
00840     { return static_cast<float>(size()) / static_cast<float>(bucket_count()); }
00841   // max_load_factor, if present, comes from rehash_base.
00842 
00843   // Generalization of max_load_factor.  Extension, not found in TR1.  Only
00844   // useful if RehashPolicy is something other than the default.
00845   const RehashPolicy& rehash_policy() const { return m_rehash_policy; }
00846   void rehash_policy (const RehashPolicy&);
00847 
00848 public:             // lookup
00849   iterator       find(const key_type&);
00850   const_iterator find(const key_type& k) const;
00851   size_type count(const key_type& k) const;
00852   std::pair<iterator, iterator> equal_range(const key_type& k);
00853   std::pair<const_iterator, const_iterator> equal_range(const key_type& k) const;
00854 
00855 private:            // Insert and erase helper functions
00856   // ??? This dispatching is a workaround for the fact that we don't
00857   // have partial specialization of member templates; it would be
00858   // better to just specialize insert on unique_keys.  There may be a
00859   // cleaner workaround.
00860   typedef typename Internal::IF<unique_keys, std::pair<iterator, bool>, iterator>::type
00861           Insert_Return_Type;
00862 
00863   node* find_node (node* p, const key_type& k, typename hashtable::hash_code_t c);
00864 
00865   std::pair<iterator, bool> insert (const value_type&, std::tr1::true_type);
00866   iterator insert (const value_type&, std::tr1::false_type);
00867 
00868 public:             // Insert and erase
00869   Insert_Return_Type insert (const value_type& v) 
00870   { return this->insert (v, std::tr1::integral_constant<bool, unique_keys>()); }
00871   Insert_Return_Type insert (const_iterator, const value_type& v)
00872     { return this->insert(v); }
00873 
00874   template <typename InIter> void insert(InIter first, InIter last);
00875 
00876   void erase(const_iterator);
00877   size_type erase(const key_type&);
00878   void erase(const_iterator, const_iterator);
00879   void clear();
00880 
00881 public:
00882   // Set number of buckets to be apropriate for container of n element.
00883   void rehash (size_type n);
00884 
00885 private:
00886   // Unconditionally change size of bucket array to n.
00887   void m_rehash (size_type n);
00888 };
00889 
00890 //----------------------------------------------------------------------
00891 // Definitions of class template hashtable's out-of-line member functions.
00892 
00893 template <typename K, typename V, 
00894       typename A, typename Ex, typename Eq,
00895       typename H1, typename H2, typename H, typename RP,
00896       bool c, bool m, bool u>
00897 typename hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::node*
00898 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::m_allocate_node (const value_type& v)
00899 {
00900   node* n = m_node_allocator.allocate(1);
00901   try {
00902     get_allocator().construct(&n->m_v, v);
00903     n->m_next = 0;
00904     return n;
00905   }
00906   catch(...) {
00907     m_node_allocator.deallocate(n, 1);
00908     throw;
00909   }
00910 }
00911 
00912 template <typename K, typename V, 
00913       typename A, typename Ex, typename Eq,
00914       typename H1, typename H2, typename H, typename RP,
00915       bool c, bool m, bool u>
00916 void
00917 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::m_deallocate_node (node* n)
00918 {
00919   get_allocator().destroy(&n->m_v);
00920   m_node_allocator.deallocate(n, 1);
00921 }
00922 
00923 template <typename K, typename V, 
00924       typename A, typename Ex, typename Eq,
00925       typename H1, typename H2, typename H, typename RP,
00926       bool c, bool m, bool u>
00927 void
00928 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>
00929 ::m_deallocate_nodes (node** array, size_type n)
00930 {
00931   for (size_type i = 0; i < n; ++i) {
00932     node* p = array[i];
00933     while (p) {
00934       node* tmp = p;
00935       p = p->m_next;
00936       m_deallocate_node (tmp);
00937     }
00938     array[i] = 0;
00939   }
00940 }
00941 
00942 template <typename K, typename V, 
00943       typename A, typename Ex, typename Eq,
00944       typename H1, typename H2, typename H, typename RP,
00945       bool c, bool m, bool u>
00946 typename hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::node**
00947 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::m_allocate_buckets (size_type n)
00948 {
00949   bucket_allocator_t alloc(m_node_allocator);
00950 
00951   // We allocate one extra bucket to hold a sentinel, an arbitrary
00952   // non-null pointer.  Iterator increment relies on this.
00953   node** p = alloc.allocate(n+1);
00954   std::fill(p, p+n, (node*) 0);
00955   p[n] = reinterpret_cast<node*>(0x1000);
00956   return p;
00957 }
00958 
00959 template <typename K, typename V, 
00960       typename A, typename Ex, typename Eq,
00961       typename H1, typename H2, typename H, typename RP,
00962       bool c, bool m, bool u>
00963 void
00964 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>
00965 ::m_deallocate_buckets (node** p, size_type n)
00966 {
00967   bucket_allocator_t alloc(m_node_allocator);
00968   alloc.deallocate(p, n+1);
00969 }
00970 
00971 template <typename K, typename V, 
00972       typename A, typename Ex, typename Eq,
00973       typename H1, typename H2, typename H, typename RP,
00974       bool c, bool m, bool u>
00975 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>
00976 ::hashtable(size_type bucket_hint,
00977         const H1& h1, const H2& h2, const H& h,
00978         const Eq& eq, const Ex& exk,
00979         const allocator_type& a)
00980   : Internal::rehash_base<RP,hashtable> (),
00981     Internal::hash_code_base<K,V,Ex,Eq,H1,H2,H,c> (exk, eq, h1, h2, h),
00982     Internal::map_base<K,V,Ex,u,hashtable> (),
00983     m_node_allocator(a),
00984     m_bucket_count (0),
00985     m_element_count (0),
00986     m_rehash_policy ()
00987 {
00988   m_bucket_count = m_rehash_policy.next_bkt(bucket_hint);
00989   m_buckets = m_allocate_buckets (m_bucket_count);
00990 }
00991 
00992 template <typename K, typename V, 
00993       typename A, typename Ex, typename Eq,
00994       typename H1, typename H2, typename H, typename RP,
00995       bool c, bool m, bool u>
00996 template <typename InIter>
00997 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>
00998 ::hashtable(InIter f, InIter l,
00999         size_type bucket_hint,
01000         const H1& h1, const H2& h2, const H& h,
01001         const Eq& eq, const Ex& exk,
01002         const allocator_type& a)
01003   : Internal::rehash_base<RP,hashtable> (),
01004     Internal::hash_code_base<K,V,Ex,Eq,H1,H2,H,c> (exk, eq, h1, h2, h),
01005     Internal::map_base<K,V,Ex,u,hashtable> (),
01006     m_node_allocator(a),
01007     m_bucket_count (0),
01008     m_element_count (0),
01009     m_rehash_policy ()
01010 {
01011   m_bucket_count = std::max(m_rehash_policy.next_bkt(bucket_hint),
01012                 m_rehash_policy.bkt_for_elements(Internal::distance_fw(f, l)));
01013   m_buckets = m_allocate_buckets (m_bucket_count);
01014   try {
01015     for  (; f != l; ++f)
01016       this->insert (*f);
01017   }
01018   catch(...) {
01019     clear();
01020     m_deallocate_buckets (m_buckets, m_bucket_count);
01021     throw;
01022   }
01023 }
01024 
01025 template <typename K, typename V, 
01026       typename A, typename Ex, typename Eq,
01027       typename H1, typename H2, typename H, typename RP,
01028       bool c, bool m, bool u>
01029 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>
01030 ::hashtable(const hashtable& ht)
01031   : Internal::rehash_base<RP,hashtable> (ht),
01032     Internal::hash_code_base<K,V,Ex,Eq,H1,H2,H,c> (ht),
01033     Internal::map_base<K,V,Ex,u,hashtable> (ht),
01034     m_node_allocator(ht.get_allocator()),
01035     m_bucket_count (ht.m_bucket_count),
01036     m_element_count (ht.m_element_count),
01037     m_rehash_policy (ht.m_rehash_policy)
01038 {
01039   m_buckets = m_allocate_buckets (m_bucket_count);
01040   try {
01041     for (size_t i = 0; i < ht.m_bucket_count; ++i) {
01042       node* n = ht.m_buckets[i];
01043       node** tail = m_buckets + i;
01044       while (n) {
01045     *tail = m_allocate_node (n);
01046     (*tail).copy_code_from (n);
01047     tail = &((*tail)->m_next);
01048     n = n->m_next;
01049       }
01050     }
01051   }
01052   catch (...) {
01053     clear();
01054     m_deallocate_buckets (m_buckets, m_bucket_count);
01055     throw;
01056   }
01057 }
01058 
01059 template <typename K, typename V, 
01060       typename A, typename Ex, typename Eq,
01061       typename H1, typename H2, typename H, typename RP,
01062       bool c, bool m, bool u>
01063 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>&
01064 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::operator= (const hashtable& ht)
01065 {
01066   hashtable tmp(ht);
01067   this->swap(tmp);
01068   return *this;
01069 }
01070 
01071 template <typename K, typename V, 
01072       typename A, typename Ex, typename Eq,
01073       typename H1, typename H2, typename H, typename RP,
01074       bool c, bool m, bool u>
01075 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::~hashtable()
01076 {
01077   clear();
01078   m_deallocate_buckets(m_buckets, m_bucket_count);
01079 }
01080 
01081 template <typename K, typename V, 
01082       typename A, typename Ex, typename Eq,
01083       typename H1, typename H2, typename H, typename RP,
01084       bool c, bool m, bool u>
01085 void hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::swap (hashtable& x)
01086 {
01087   // The only base class with member variables is hash_code_base.  We
01088   // define hash_code_base::m_swap because different specializations
01089   // have different members.
01090   Internal::hash_code_base<K, V, Ex, Eq, H1, H2, H, c>::m_swap(x);
01091 
01092   // open LWG issue 431
01093   // std::swap(m_node_allocator, x.m_node_allocator);
01094   std::swap (m_rehash_policy, x.m_rehash_policy);
01095   std::swap (m_buckets, x.m_buckets);
01096   std::swap (m_bucket_count, x.m_bucket_count);
01097   std::swap (m_element_count, x.m_element_count);
01098 }
01099 
01100 template <typename K, typename V, 
01101       typename A, typename Ex, typename Eq,
01102       typename H1, typename H2, typename H, typename RP,
01103       bool c, bool m, bool u>
01104 void
01105 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::rehash_policy (const RP& pol)
01106 {
01107   m_rehash_policy = pol;
01108   size_type n_bkt = pol.bkt_for_elements(m_element_count);
01109   if (n_bkt > m_bucket_count)
01110     m_rehash (n_bkt);
01111 }
01112 
01113 template <typename K, typename V, 
01114       typename A, typename Ex, typename Eq,
01115       typename H1, typename H2, typename H, typename RP,
01116       bool c, bool m, bool u>
01117 typename hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::iterator
01118 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::find (const key_type& k)
01119 {
01120   typename hashtable::hash_code_t code = this->m_hash_code (k);
01121   std::size_t n = this->bucket_index (k, code, this->bucket_count());
01122   node* p = find_node (m_buckets[n], k, code);
01123   return p ? iterator(p, m_buckets + n) : this->end();
01124 }
01125 
01126 template <typename K, typename V, 
01127       typename A, typename Ex, typename Eq,
01128       typename H1, typename H2, typename H, typename RP,
01129       bool c, bool m, bool u>
01130 typename hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::const_iterator
01131 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::find (const key_type& k) const
01132 {
01133   typename hashtable::hash_code_t code = this->m_hash_code (k);
01134   std::size_t n = this->bucket_index (k, code, this->bucket_count());
01135   node* p = find_node (m_buckets[n], k, code);
01136   return p ? const_iterator(p, m_buckets + n) : this->end();
01137 }
01138 
01139 template <typename K, typename V, 
01140       typename A, typename Ex, typename Eq,
01141       typename H1, typename H2, typename H, typename RP,
01142       bool c, bool m, bool u>
01143 typename hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::size_type
01144 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::count (const key_type& k) const
01145 {
01146   typename hashtable::hash_code_t code = this->m_hash_code (k);
01147   std::size_t n = this->bucket_index (k, code, this->bucket_count());
01148   size_t result = 0;
01149   for (node* p = m_buckets[n]; p ; p = p->m_next)
01150     if (this->compare (k, code, p))
01151       ++result;
01152   return result;
01153 }
01154 
01155 template <typename K, typename V, 
01156       typename A, typename Ex, typename Eq,
01157       typename H1, typename H2, typename H, typename RP,
01158       bool c, bool m, bool u>
01159 std::pair<typename hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::iterator,
01160       typename hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::iterator>
01161 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::equal_range (const key_type& k)
01162 {
01163   typename hashtable::hash_code_t code = this->m_hash_code (k);
01164   std::size_t n = this->bucket_index (k, code, this->bucket_count());
01165   node** head = m_buckets + n;
01166   node* p = find_node (*head, k, code);
01167 
01168   if (p) {
01169     node* p1 = p->m_next;
01170     for (; p1 ; p1 = p1->m_next)
01171       if (!this->compare (k, code, p1))
01172     break;
01173     iterator first(p, head);
01174     iterator last(p1, head);
01175     if (!p1)
01176       last.m_incr_bucket();
01177     return std::make_pair(first, last);
01178   }
01179   else
01180     return std::make_pair (this->end(), this->end());
01181 }
01182 
01183 template <typename K, typename V, 
01184       typename A, typename Ex, typename Eq,
01185       typename H1, typename H2, typename H, typename RP,
01186       bool c, bool m, bool u>
01187 std::pair<typename hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::const_iterator,
01188       typename hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::const_iterator>
01189 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::equal_range (const key_type& k) const
01190 {
01191   typename hashtable::hash_code_t code = this->m_hash_code (k);
01192   std::size_t n = this->bucket_index (k, code, this->bucket_count());
01193   node** head = m_buckets + n;
01194   node* p = find_node (*head, k, code);
01195 
01196   if (p) {
01197     node* p1 = p->m_next;
01198     for (; p1 ; p1 = p1->m_next)
01199       if (!this->compare (k, code, p1))
01200     break;
01201     const_iterator first(p, head);
01202     const_iterator last(p1, head);
01203     if (!p1)
01204       last.m_incr_bucket();
01205     return std::make_pair(first, last);
01206   }
01207   else
01208     return std::make_pair (this->end(), this->end());
01209 }
01210 
01211 // Find the node whose key compares equal to k, beginning the search
01212 // at p (usually the head of a bucket).  Return nil if no node is found.
01213 template <typename K, typename V, 
01214       typename A, typename Ex, typename Eq,
01215       typename H1, typename H2, typename H, typename RP,
01216       bool c, bool m, bool u>
01217 typename hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::node* 
01218 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>
01219 ::find_node (node* p, const key_type& k, typename hashtable::hash_code_t code)
01220 {
01221   for ( ; p ; p = p->m_next)
01222     if (this->compare (k, code, p))
01223       return p;
01224   return false;
01225 }
01226 
01227 // Insert v if no element with its key is already present.
01228 template <typename K, typename V, 
01229       typename A, typename Ex, typename Eq,
01230       typename H1, typename H2, typename H, typename RP,
01231       bool c, bool m, bool u>
01232 std::pair<typename hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::iterator, bool>
01233 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>
01234 ::insert (const value_type& v, std::tr1::true_type)
01235 {
01236   const key_type& k = this->m_extract(v);
01237   typename hashtable::hash_code_t code = this->m_hash_code (k);
01238   size_type n = this->bucket_index (k, code, m_bucket_count);
01239 
01240   if (node* p = find_node (m_buckets[n], k, code))
01241     return std::make_pair(iterator(p, m_buckets + n), false);
01242 
01243   std::pair<bool, size_t> do_rehash
01244     = m_rehash_policy.need_rehash(m_bucket_count, m_element_count, 1);
01245 
01246   // Allocate the new node before doing the rehash so that we don't
01247   // do a rehash if the allocation throws.
01248   node* new_node = m_allocate_node (v);
01249 
01250   try {
01251     if (do_rehash.first) {
01252       n = this->bucket_index (k, code, do_rehash.second);
01253       m_rehash(do_rehash.second);
01254     }
01255 
01256     new_node->m_next = m_buckets[n];
01257     m_buckets[n] = new_node;
01258     ++m_element_count;
01259     return std::make_pair(iterator (new_node, m_buckets + n), true);
01260   }
01261   catch (...) {
01262     m_deallocate_node (new_node);
01263     throw;
01264   }
01265 }
01266 
01267 // Insert v unconditionally.
01268 template <typename K, typename V, 
01269       typename A, typename Ex, typename Eq,
01270       typename H1, typename H2, typename H, typename RP,
01271       bool c, bool m, bool u>
01272 typename hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::iterator
01273 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>
01274 ::insert (const value_type& v, std::tr1::false_type)
01275 {
01276   std::pair<bool, std::size_t> do_rehash
01277     = m_rehash_policy.need_rehash(m_bucket_count, m_element_count, 1);
01278   if (do_rehash.first)
01279     m_rehash(do_rehash.second);
01280 
01281   const key_type& k = this->m_extract(v);
01282   typename hashtable::hash_code_t code = this->m_hash_code (k);
01283   size_type n = this->bucket_index (k, code, m_bucket_count);
01284 
01285   node* new_node = m_allocate_node (v);
01286   node* prev = find_node (m_buckets[n], k, code);
01287   if (prev) {
01288     new_node->m_next = prev->m_next;
01289     prev->m_next = new_node;
01290   }
01291   else {
01292     new_node->m_next = m_buckets[n];
01293     m_buckets[n] = new_node;
01294   }
01295 
01296   ++m_element_count;
01297   return iterator (new_node, m_buckets + n);
01298 }
01299 
01300 template <typename K, typename V, 
01301       typename A, typename Ex, typename Eq,
01302       typename H1, typename H2, typename H, typename RP,
01303       bool c, bool m, bool u>
01304 template <typename InIter>
01305 void 
01306 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::insert(InIter first, InIter last)
01307 {
01308   size_type n_elt = Internal::distance_fw (first, last);
01309   std::pair<bool, std::size_t> do_rehash
01310     = m_rehash_policy.need_rehash(m_bucket_count, m_element_count, n_elt);
01311   if (do_rehash.first)
01312     m_rehash(do_rehash.second);
01313 
01314   for (; first != last; ++first)
01315     this->insert (*first);
01316 }
01317 
01318 // XXX We're following the TR in giving this a return type of void,
01319 // but that ought to change.  The return type should be const_iterator,
01320 // and it should return the iterator following the one we've erased.
01321 // That would simplify range erase.
01322 template <typename K, typename V, 
01323       typename A, typename Ex, typename Eq,
01324       typename H1, typename H2, typename H, typename RP,
01325       bool c, bool m, bool u>
01326 void hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::erase (const_iterator i)
01327 {
01328   node* p = i.m_cur_node;
01329   node* cur = *i.m_cur_bucket;
01330   if (cur == p)
01331     *i.m_cur_bucket = cur->m_next;
01332   else {
01333     node* next = cur->m_next;
01334     while (next != p) {
01335       cur = next;
01336       next = cur->m_next;
01337     }
01338     cur->m_next = next->m_next;
01339   }
01340 
01341   m_deallocate_node (p);
01342   --m_element_count;
01343 }
01344 
01345 template <typename K, typename V, 
01346       typename A, typename Ex, typename Eq,
01347       typename H1, typename H2, typename H, typename RP,
01348       bool c, bool m, bool u>
01349 typename hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::size_type 
01350 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::erase(const key_type& k)
01351 {
01352   typename hashtable::hash_code_t code = this->m_hash_code (k);
01353   size_type n = this->bucket_index (k, code, m_bucket_count);
01354 
01355   node** slot = m_buckets + n;
01356   while (*slot && ! this->compare (k, code, *slot))
01357     slot = &((*slot)->m_next);
01358 
01359   while (*slot && this->compare (k, code, *slot)) {
01360     node* n = *slot;
01361     *slot = n->m_next;
01362     m_deallocate_node (n);
01363     --m_element_count;
01364   }
01365 }
01366 
01367 // ??? This could be optimized by taking advantage of the bucket
01368 // structure, but it's not clear that it's worth doing.  It probably
01369 // wouldn't even be an optimization unless the load factor is large.
01370 template <typename K, typename V,
01371       typename A, typename Ex, typename Eq,
01372       typename H1, typename H2, typename H, typename RP,
01373       bool c, bool m, bool u>
01374 void hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>
01375 ::erase(const_iterator first, const_iterator last)
01376 {
01377   while (first != last) {
01378     const_iterator next = first;
01379     ++next;
01380     this->erase(first);
01381     first = next;
01382   }
01383 }
01384 
01385 template <typename K, typename V, 
01386       typename A, typename Ex, typename Eq,
01387       typename H1, typename H2, typename H, typename RP,
01388       bool c, bool m, bool u>
01389 void hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::clear()
01390 {
01391   m_deallocate_nodes (m_buckets, m_bucket_count);
01392   m_element_count = 0;
01393 }
01394 
01395 template <typename K, typename V, 
01396       typename A, typename Ex, typename Eq,
01397       typename H1, typename H2, typename H, typename RP,
01398       bool c, bool m, bool u>
01399 void
01400 hashtable<K,V,A,Ex,Eq,H1,H2,H,RP,c,m,u>::m_rehash (size_type N)
01401 {
01402   node** new_array = m_allocate_buckets (N);
01403   try {
01404     for (size_type i = 0; i < m_bucket_count; ++i)
01405       while (node* p = m_buckets[i]) {
01406     size_type new_index = this->bucket_index (p, N);
01407     m_buckets[i] = p->m_next;
01408     p->m_next = new_array[new_index];
01409     new_array[new_index] = p;
01410       }
01411     m_deallocate_buckets (m_buckets, m_bucket_count);
01412     m_bucket_count = N;
01413     m_buckets = new_array;
01414   }
01415   catch (...) {
01416     // A failure here means that a hash function threw an exception.
01417     // We can't restore the previous state without calling the hash
01418     // function again, so the only sensible recovery is to delete
01419     // everything.
01420     m_deallocate_nodes (new_array, N);
01421     m_deallocate_buckets (new_array, N);
01422     m_deallocate_nodes (m_buckets, m_bucket_count);
01423     m_element_count = 0;
01424     throw;
01425   }
01426 }
01427 
01428 } }             // Namespace std::tr1
01429 
01430 #endif /* GNU_LIBSTDCXX_TR1_HASHTABLE_ */
01431 

Generated on Wed Apr 27 18:35:11 2005 for libstdc++ source by  doxygen 1.4.2