hashtable

Go to the documentation of this file.
00001 // Internal header for TR1 unordered_set and unordered_map -*- C++ -*-
00002 
00003 // Copyright (C) 2005, 2006 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 
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 <bits/functexcept.h>
00063 #include <tr1/type_traits>  // For true_type and false_type
00064 
00065 //----------------------------------------------------------------------
00066 // General utilities
00067 
00068 namespace Internal
00069 {
00070   template<bool Flag, typename IfTrue, typename IfFalse>
00071     struct IF;
00072 
00073   template<typename IfTrue, typename IfFalse>
00074     struct IF<true, IfTrue, IfFalse>
00075     { typedef IfTrue type; };
00076  
00077   template <typename IfTrue, typename IfFalse>
00078     struct IF<false, IfTrue, IfFalse>
00079     { typedef IfFalse type; };
00080 
00081   // Helper function: return distance(first, last) for forward
00082   // iterators, or 0 for input iterators.
00083   template<class Iterator>
00084     inline typename std::iterator_traits<Iterator>::difference_type
00085     distance_fw(Iterator first, Iterator last, std::input_iterator_tag)
00086     { return 0; }
00087 
00088   template<class Iterator>
00089     inline typename std::iterator_traits<Iterator>::difference_type
00090     distance_fw(Iterator first, Iterator last, std::forward_iterator_tag)
00091     { return std::distance(first, last); }
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>
00115     struct hash_node;
00116 
00117   template<typename Value>
00118     struct hash_node<Value, true>
00119     {
00120       Value m_v;
00121       std::size_t hash_code;
00122       hash_node* m_next;
00123     };
00124 
00125   template<typename Value>
00126     struct hash_node<Value, false>
00127     {
00128       Value m_v;
00129       hash_node* m_next;
00130     };
00131 
00132   // Local iterators, used to iterate within a bucket but not between
00133   // buckets.
00134 
00135   template<typename Value, bool cache>
00136     struct node_iterator_base
00137     {
00138       node_iterator_base(hash_node<Value, cache>* p)
00139       : m_cur(p) { }
00140       
00141       void
00142       incr()
00143       { m_cur = m_cur->m_next; }
00144 
00145       hash_node<Value, cache>* m_cur;
00146     };
00147 
00148   template<typename Value, bool cache>
00149     inline bool
00150     operator==(const node_iterator_base<Value, cache>& x,
00151            const node_iterator_base<Value, cache>& y)
00152     { return x.m_cur == y.m_cur; }
00153 
00154   template<typename Value, bool cache>
00155     inline bool
00156     operator!=(const node_iterator_base<Value, cache>& x,
00157            const node_iterator_base<Value, cache>& y)
00158     { return x.m_cur != y.m_cur; }
00159 
00160   template<typename Value, bool constant_iterators, bool cache>
00161     struct node_iterator
00162     : public node_iterator_base<Value, cache>
00163     {
00164       typedef Value                                    value_type;
00165       typedef typename IF<constant_iterators, const Value*, Value*>::type
00166                                                        pointer;
00167       typedef typename IF<constant_iterators, const Value&, Value&>::type
00168                                                        reference;
00169       typedef std::ptrdiff_t                           difference_type;
00170       typedef std::forward_iterator_tag                iterator_category;
00171 
00172       node_iterator()
00173       : node_iterator_base<Value, cache>(0) { }
00174 
00175       explicit
00176       node_iterator(hash_node<Value, cache>* p)
00177       : node_iterator_base<Value, cache>(p) { }
00178 
00179       reference
00180       operator*() const
00181       { return this->m_cur->m_v; }
00182   
00183       pointer
00184       operator->() const
00185       { return &this->m_cur->m_v; }
00186 
00187       node_iterator&
00188       operator++()
00189       { 
00190     this->incr(); 
00191     return *this; 
00192       }
00193   
00194       node_iterator
00195       operator++(int)
00196       { 
00197     node_iterator tmp(*this);
00198     this->incr();
00199     return tmp;
00200       }
00201     };
00202 
00203   template<typename Value, bool constant_iterators, bool cache>
00204     struct node_const_iterator
00205     : public node_iterator_base<Value, cache>
00206     {
00207       typedef Value                                    value_type;
00208       typedef const Value*                             pointer;
00209       typedef const Value&                             reference;
00210       typedef std::ptrdiff_t                           difference_type;
00211       typedef std::forward_iterator_tag                iterator_category;
00212 
00213       node_const_iterator()
00214       : node_iterator_base<Value, cache>(0) { }
00215 
00216       explicit
00217       node_const_iterator(hash_node<Value, cache>* p)
00218       : node_iterator_base<Value, cache>(p) { }
00219 
00220       node_const_iterator(const node_iterator<Value, constant_iterators,
00221               cache>& x)
00222       : node_iterator_base<Value, cache>(x.m_cur) { }
00223 
00224       reference
00225       operator*() const
00226       { return this->m_cur->m_v; }
00227   
00228       pointer
00229       operator->() const
00230       { return &this->m_cur->m_v; }
00231 
00232       node_const_iterator&
00233       operator++()
00234       { 
00235     this->incr(); 
00236     return *this; 
00237       }
00238   
00239       node_const_iterator
00240       operator++(int)
00241       { 
00242     node_const_iterator tmp(*this);
00243     this->incr();
00244     return tmp;
00245       }
00246     };
00247 
00248   template<typename Value, bool cache>
00249     struct hashtable_iterator_base
00250     {
00251       hashtable_iterator_base(hash_node<Value, cache>* node,
00252                   hash_node<Value, cache>** bucket)
00253       : m_cur_node(node), m_cur_bucket(bucket) { }
00254 
00255       void
00256       incr()
00257       {
00258     m_cur_node = m_cur_node->m_next;
00259     if (!m_cur_node)
00260       m_incr_bucket();
00261       }
00262 
00263       void
00264       m_incr_bucket();
00265 
00266       hash_node<Value, cache>* m_cur_node;
00267       hash_node<Value, cache>** m_cur_bucket;
00268     };
00269 
00270   // Global iterators, used for arbitrary iteration within a hash
00271   // table.  Larger and more expensive than local iterators.
00272   template<typename Value, bool cache>
00273     void
00274     hashtable_iterator_base<Value, cache>::
00275     m_incr_bucket()
00276     {
00277       ++m_cur_bucket;
00278 
00279       // This loop requires the bucket array to have a non-null sentinel.
00280       while (!*m_cur_bucket)
00281     ++m_cur_bucket;
00282       m_cur_node = *m_cur_bucket;
00283     }
00284 
00285   template<typename Value, bool cache>
00286     inline bool
00287     operator==(const hashtable_iterator_base<Value, cache>& x,
00288            const hashtable_iterator_base<Value, cache>& y)
00289     { return x.m_cur_node == y.m_cur_node; }
00290 
00291   template<typename Value, bool cache>
00292     inline bool
00293     operator!=(const hashtable_iterator_base<Value, cache>& x,
00294            const hashtable_iterator_base<Value, cache>& y)
00295     { return x.m_cur_node != y.m_cur_node; }
00296 
00297   template<typename Value, bool constant_iterators, bool cache>
00298     struct hashtable_iterator
00299     : public hashtable_iterator_base<Value, cache>
00300     {
00301       typedef Value                                    value_type;
00302       typedef typename IF<constant_iterators, const Value*, Value*>::type
00303                                                        pointer;
00304       typedef typename IF<constant_iterators, const Value&, Value&>::type
00305                                                        reference;
00306       typedef std::ptrdiff_t                           difference_type;
00307       typedef std::forward_iterator_tag                iterator_category;
00308 
00309       hashtable_iterator()
00310       : hashtable_iterator_base<Value, cache>(0, 0) { }
00311 
00312       hashtable_iterator(hash_node<Value, cache>* p,
00313              hash_node<Value, cache>** b)
00314       : hashtable_iterator_base<Value, cache>(p, b) { }
00315 
00316       explicit
00317       hashtable_iterator(hash_node<Value, cache>** b)
00318       : hashtable_iterator_base<Value, cache>(*b, b) { }
00319 
00320       reference
00321       operator*() const
00322       { return this->m_cur_node->m_v; }
00323   
00324       pointer
00325       operator->() const
00326       { return &this->m_cur_node->m_v; }
00327 
00328       hashtable_iterator&
00329       operator++()
00330       { 
00331     this->incr();
00332     return *this;
00333       }
00334   
00335       hashtable_iterator
00336       operator++(int)
00337       { 
00338     hashtable_iterator tmp(*this);
00339     this->incr();
00340     return tmp;
00341       }
00342     };
00343 
00344   template<typename Value, bool constant_iterators, bool cache>
00345     struct hashtable_const_iterator
00346     : public hashtable_iterator_base<Value, cache>
00347     {
00348       typedef Value                                    value_type;
00349       typedef const Value*                             pointer;
00350       typedef const Value&                             reference;
00351       typedef std::ptrdiff_t                           difference_type;
00352       typedef std::forward_iterator_tag                iterator_category;
00353 
00354       hashtable_const_iterator()
00355       : hashtable_iterator_base<Value, cache>(0, 0) { }
00356 
00357       hashtable_const_iterator(hash_node<Value, cache>* p,
00358                    hash_node<Value, cache>** b)
00359       : hashtable_iterator_base<Value, cache>(p, b) { }
00360 
00361       explicit
00362       hashtable_const_iterator(hash_node<Value, cache>** b)
00363       : hashtable_iterator_base<Value, cache>(*b, b) { }
00364 
00365       hashtable_const_iterator(const hashtable_iterator<Value,
00366                    constant_iterators, cache>& x)
00367       : hashtable_iterator_base<Value, cache>(x.m_cur_node, x.m_cur_bucket) { }
00368 
00369       reference
00370       operator*() const
00371       { return this->m_cur_node->m_v; }
00372   
00373       pointer
00374       operator->() const
00375       { return &this->m_cur_node->m_v; }
00376 
00377       hashtable_const_iterator&
00378       operator++()
00379       { 
00380     this->incr();
00381     return *this;
00382       }
00383   
00384       hashtable_const_iterator
00385       operator++(int)
00386       { 
00387     hashtable_const_iterator tmp(*this);
00388     this->incr();
00389     return tmp;
00390       }
00391     };
00392 } // namespace Internal
00393 
00394 // ----------------------------------------------------------------------
00395 // Many of class template hashtable's template parameters are policy
00396 // classes.  These are defaults for the policies.
00397 
00398 namespace Internal
00399 {
00400   // The two key extraction policies used by the *set and *map variants.
00401   template<typename T>
00402     struct identity
00403     {
00404       const T&
00405       operator()(const T& t) const
00406       { return t; }
00407     };
00408 
00409   template<typename Pair>
00410     struct extract1st
00411     {
00412       const typename Pair::first_type&
00413       operator()(const Pair& p) const
00414       { return p.first; }
00415     };
00416 
00417   // Default range hashing function: use division to fold a large number
00418   // into the range [0, N).
00419   struct mod_range_hashing
00420   {
00421     typedef std::size_t first_argument_type;
00422     typedef std::size_t second_argument_type;
00423     typedef std::size_t result_type;
00424 
00425     result_type
00426     operator()(first_argument_type r, second_argument_type N) const
00427     { return r % N; }
00428   };
00429 
00430   // Default ranged hash function H.  In principle it should be a
00431   // function object composed from objects of type H1 and H2 such that
00432   // h(k, N) = h2(h1(k), N), but that would mean making extra copies of
00433   // h1 and h2.  So instead we'll just use a tag to tell class template
00434   // hashtable to do that composition.
00435   struct default_ranged_hash { };
00436 
00437   // Default value for rehash policy.  Bucket size is (usually) the
00438   // smallest prime that keeps the load factor small enough.
00439   struct prime_rehash_policy
00440   {
00441     prime_rehash_policy(float z = 1.0);
00442     
00443     float
00444     max_load_factor() const;
00445 
00446     // Return a bucket size no smaller than n.
00447     std::size_t
00448     next_bkt(std::size_t n) const;
00449     
00450     // Return a bucket count appropriate for n elements
00451     std::size_t
00452     bkt_for_elements(std::size_t n) const;
00453     
00454     // n_bkt is current bucket count, n_elt is current element count,
00455     // and n_ins is number of elements to be inserted.  Do we need to
00456     // increase bucket count?  If so, return make_pair(true, n), where n
00457     // is the new bucket count.  If not, return make_pair(false, 0).
00458     std::pair<bool, std::size_t>
00459     need_rehash(std::size_t n_bkt, std::size_t n_elt, std::size_t n_ins) const;
00460     
00461     float m_max_load_factor;
00462     float m_growth_factor;
00463     mutable std::size_t m_next_resize;
00464   };
00465 
00466   // XXX This is a hack.  prime_rehash_policy's member functions, and
00467   // certainly the list of primes, should be defined in a .cc file.
00468   // We're temporarily putting them in a header because we don't have a
00469   // place to put TR1 .cc files yet.  There's no good reason for any of
00470   // prime_rehash_policy's member functions to be inline, and there's
00471   // certainly no good reason for X<> to exist at all.
00472   
00473   struct lt
00474   {
00475     template<typename X, typename Y>
00476       bool
00477       operator()(X x, Y y)
00478       { return x < y; }
00479   };
00480 
00481   template<int ulongsize = sizeof(unsigned long)>
00482     struct X
00483     {
00484       static const int n_primes = ulongsize != 8 ? 256 : 256 + 48;
00485       static const unsigned long primes[256 + 48 + 1];
00486     };
00487 
00488   template<int ulongsize>
00489     const int X<ulongsize>::n_primes;
00490 
00491   template<int ulongsize>
00492     const unsigned long X<ulongsize>::primes[256 + 48 + 1] =
00493     {
00494       2ul, 3ul, 5ul, 7ul, 11ul, 13ul, 17ul, 19ul, 23ul, 29ul, 31ul,
00495       37ul, 41ul, 43ul, 47ul, 53ul, 59ul, 61ul, 67ul, 71ul, 73ul, 79ul,
00496       83ul, 89ul, 97ul, 103ul, 109ul, 113ul, 127ul, 137ul, 139ul, 149ul,
00497       157ul, 167ul, 179ul, 193ul, 199ul, 211ul, 227ul, 241ul, 257ul,
00498       277ul, 293ul, 313ul, 337ul, 359ul, 383ul, 409ul, 439ul, 467ul,
00499       503ul, 541ul, 577ul, 619ul, 661ul, 709ul, 761ul, 823ul, 887ul,
00500       953ul, 1031ul, 1109ul, 1193ul, 1289ul, 1381ul, 1493ul, 1613ul,
00501       1741ul, 1879ul, 2029ul, 2179ul, 2357ul, 2549ul, 2753ul, 2971ul,
00502       3209ul, 3469ul, 3739ul, 4027ul, 4349ul, 4703ul, 5087ul, 5503ul,
00503       5953ul, 6427ul, 6949ul, 7517ul, 8123ul, 8783ul, 9497ul, 10273ul,
00504       11113ul, 12011ul, 12983ul, 14033ul, 15173ul, 16411ul, 17749ul,
00505       19183ul, 20753ul, 22447ul, 24281ul, 26267ul, 28411ul, 30727ul,
00506       33223ul, 35933ul, 38873ul, 42043ul, 45481ul, 49201ul, 53201ul,
00507       57557ul, 62233ul, 67307ul, 72817ul, 78779ul, 85229ul, 92203ul,
00508       99733ul, 107897ul, 116731ul, 126271ul, 136607ul, 147793ul,
00509       159871ul, 172933ul, 187091ul, 202409ul, 218971ul, 236897ul,
00510       256279ul, 277261ul, 299951ul, 324503ul, 351061ul, 379787ul,
00511       410857ul, 444487ul, 480881ul, 520241ul, 562841ul, 608903ul,
00512       658753ul, 712697ul, 771049ul, 834181ul, 902483ul, 976369ul,
00513       1056323ul, 1142821ul, 1236397ul, 1337629ul, 1447153ul, 1565659ul,
00514       1693859ul, 1832561ul, 1982627ul, 2144977ul, 2320627ul, 2510653ul,
00515       2716249ul, 2938679ul, 3179303ul, 3439651ul, 3721303ul, 4026031ul,
00516       4355707ul, 4712381ul, 5098259ul, 5515729ul, 5967347ul, 6456007ul,
00517       6984629ul, 7556579ul, 8175383ul, 8844859ul, 9569143ul, 10352717ul,
00518       11200489ul, 12117689ul, 13109983ul, 14183539ul, 15345007ul,
00519       16601593ul, 17961079ul, 19431899ul, 21023161ul, 22744717ul,
00520       24607243ul, 26622317ul, 28802401ul, 31160981ul, 33712729ul,
00521       36473443ul, 39460231ul, 42691603ul, 46187573ul, 49969847ul,
00522       54061849ul, 58488943ul, 63278561ul, 68460391ul, 74066549ul,
00523       80131819ul, 86693767ul, 93793069ul, 101473717ul, 109783337ul,
00524       118773397ul, 128499677ul, 139022417ul, 150406843ul, 162723577ul,
00525       176048909ul, 190465427ul, 206062531ul, 222936881ul, 241193053ul,
00526       260944219ul, 282312799ul, 305431229ul, 330442829ul, 357502601ul,
00527       386778277ul, 418451333ul, 452718089ul, 489790921ul, 529899637ul,
00528       573292817ul, 620239453ul, 671030513ul, 725980837ul, 785430967ul,
00529       849749479ul, 919334987ul, 994618837ul, 1076067617ul, 1164186217ul,
00530       1259520799ul, 1362662261ul, 1474249943ul, 1594975441ul,
00531       1725587117ul, 1866894511ul, 2019773507ul, 2185171673ul,
00532       2364114217ul, 2557710269ul, 2767159799ul, 2993761039ul,
00533       3238918481ul, 3504151727ul, 3791104843ul, 4101556399ul,
00534       4294967291ul,
00535       // Sentinel, so we don't have to test the result of lower_bound,
00536       // or, on 64-bit machines, rest of the table.
00537       ulongsize != 8 ? 4294967291ul : (unsigned long)6442450933ull,
00538       (unsigned long)8589934583ull,
00539       (unsigned long)12884901857ull, (unsigned long)17179869143ull,
00540       (unsigned long)25769803693ull, (unsigned long)34359738337ull,
00541       (unsigned long)51539607367ull, (unsigned long)68719476731ull,
00542       (unsigned long)103079215087ull, (unsigned long)137438953447ull,
00543       (unsigned long)206158430123ull, (unsigned long)274877906899ull,
00544       (unsigned long)412316860387ull, (unsigned long)549755813881ull,
00545       (unsigned long)824633720731ull, (unsigned long)1099511627689ull,
00546       (unsigned long)1649267441579ull, (unsigned long)2199023255531ull,
00547       (unsigned long)3298534883309ull, (unsigned long)4398046511093ull,
00548       (unsigned long)6597069766607ull, (unsigned long)8796093022151ull,
00549       (unsigned long)13194139533241ull, (unsigned long)17592186044399ull,
00550       (unsigned long)26388279066581ull, (unsigned long)35184372088777ull,
00551       (unsigned long)52776558133177ull, (unsigned long)70368744177643ull,
00552       (unsigned long)105553116266399ull, (unsigned long)140737488355213ull,
00553       (unsigned long)211106232532861ull, (unsigned long)281474976710597ull,
00554       (unsigned long)562949953421231ull, (unsigned long)1125899906842597ull,
00555       (unsigned long)2251799813685119ull, (unsigned long)4503599627370449ull,
00556       (unsigned long)9007199254740881ull, (unsigned long)18014398509481951ull,
00557       (unsigned long)36028797018963913ull, (unsigned long)72057594037927931ull,
00558       (unsigned long)144115188075855859ull,
00559       (unsigned long)288230376151711717ull,
00560       (unsigned long)576460752303423433ull,
00561       (unsigned long)1152921504606846883ull,
00562       (unsigned long)2305843009213693951ull,
00563       (unsigned long)4611686018427387847ull,
00564       (unsigned long)9223372036854775783ull,
00565       (unsigned long)18446744073709551557ull,
00566       (unsigned long)18446744073709551557ull
00567     };
00568 
00569   inline
00570   prime_rehash_policy::
00571   prime_rehash_policy(float z)
00572   : m_max_load_factor(z), m_growth_factor(2.f), m_next_resize(0)
00573   { }
00574 
00575   inline float
00576   prime_rehash_policy::
00577   max_load_factor() const
00578   { return m_max_load_factor; }
00579 
00580   // Return a prime no smaller than n.
00581   inline std::size_t
00582   prime_rehash_policy::
00583   next_bkt(std::size_t n) const
00584   {
00585     const unsigned long* const last = X<>::primes + X<>::n_primes;
00586     const unsigned long* p = std::lower_bound(X<>::primes, last, n);
00587     m_next_resize = static_cast<std::size_t>(std::ceil(*p * m_max_load_factor));
00588     return *p;
00589   }
00590 
00591   // Return the smallest prime p such that alpha p >= n, where alpha
00592   // is the load factor.
00593   inline std::size_t
00594   prime_rehash_policy::
00595   bkt_for_elements(std::size_t n) const
00596   {
00597     const unsigned long* const last = X<>::primes + X<>::n_primes;
00598     const float min_bkts = n / m_max_load_factor;
00599     const unsigned long* p = std::lower_bound(X<>::primes, last,
00600                           min_bkts, lt());
00601     m_next_resize = static_cast<std::size_t>(std::ceil(*p * m_max_load_factor));
00602     return *p;
00603   }
00604 
00605   // Finds the smallest prime p such that alpha p > n_elt + n_ins.
00606   // If p > n_bkt, return make_pair(true, p); otherwise return
00607   // make_pair(false, 0).  In principle this isn't very different from 
00608   // bkt_for_elements.
00609   
00610   // The only tricky part is that we're caching the element count at
00611   // which we need to rehash, so we don't have to do a floating-point
00612   // multiply for every insertion.
00613   
00614   inline std::pair<bool, std::size_t>
00615   prime_rehash_policy::
00616   need_rehash(std::size_t n_bkt, std::size_t n_elt, std::size_t n_ins) const
00617   {
00618     if (n_elt + n_ins > m_next_resize)
00619       {
00620     float min_bkts = (float(n_ins) + float(n_elt)) / m_max_load_factor;
00621     if (min_bkts > n_bkt)
00622       {
00623         min_bkts = std::max(min_bkts, m_growth_factor * n_bkt);
00624         const unsigned long* const last = X<>::primes + X<>::n_primes;
00625         const unsigned long* p = std::lower_bound(X<>::primes, last,
00626                               min_bkts, lt());
00627         m_next_resize = 
00628           static_cast<std::size_t>(std::ceil(*p * m_max_load_factor));
00629         return std::make_pair(true, *p);
00630       }
00631     else 
00632       {
00633         m_next_resize = 
00634           static_cast<std::size_t>(std::ceil(n_bkt * m_max_load_factor));
00635         return std::make_pair(false, 0);
00636       }
00637       }
00638     else
00639       return std::make_pair(false, 0);
00640   }
00641 
00642 } // namespace Internal
00643 
00644 //----------------------------------------------------------------------
00645 // Base classes for std::tr1::hashtable.  We define these base classes
00646 // because in some cases we want to do different things depending on
00647 // the value of a policy class.  In some cases the policy class affects
00648 // which member functions and nested typedefs are defined; we handle that
00649 // by specializing base class templates.  Several of the base class templates
00650 // need to access other members of class template hashtable, so we use
00651 // the "curiously recurring template pattern" for them.
00652 
00653 namespace Internal
00654 {
00655   // class template map_base.  If the hashtable has a value type of the
00656   // form pair<T1, T2> and a key extraction policy that returns the
00657   // first part of the pair, the hashtable gets a mapped_type typedef.
00658   // If it satisfies those criteria and also has unique keys, then it
00659   // also gets an operator[].
00660   
00661   template<typename K, typename V, typename Ex, bool unique, typename Hashtable>
00662     struct map_base { };
00663       
00664   template<typename K, typename Pair, typename Hashtable>
00665     struct map_base<K, Pair, extract1st<Pair>, false, Hashtable>
00666     {
00667       typedef typename Pair::second_type mapped_type;
00668     };
00669 
00670   template<typename K, typename Pair, typename Hashtable>
00671     struct map_base<K, Pair, extract1st<Pair>, true, Hashtable>
00672     {
00673       typedef typename Pair::second_type mapped_type;
00674       
00675       mapped_type&
00676       operator[](const K& k);
00677     };
00678 
00679   template<typename K, typename Pair, typename Hashtable>
00680     typename map_base<K, Pair, extract1st<Pair>, true, Hashtable>::mapped_type&
00681     map_base<K, Pair, extract1st<Pair>, true, Hashtable>::
00682     operator[](const K& k)
00683     {
00684       Hashtable* h = static_cast<Hashtable*>(this);
00685       typename Hashtable::hash_code_t code = h->m_hash_code(k);
00686       std::size_t n = h->bucket_index(k, code, h->bucket_count());
00687 
00688       typename Hashtable::node* p = h->m_find_node(h->m_buckets[n], k, code);
00689       if (!p)
00690     return h->m_insert_bucket(std::make_pair(k, mapped_type()),
00691                   n, code)->second;
00692       return (p->m_v).second;
00693     }
00694 
00695   // class template rehash_base.  Give hashtable the max_load_factor
00696   // functions iff the rehash policy is prime_rehash_policy.
00697   template<typename RehashPolicy, typename Hashtable>
00698     struct rehash_base { };
00699 
00700   template<typename Hashtable>
00701     struct rehash_base<prime_rehash_policy, Hashtable>
00702     {
00703       float
00704       max_load_factor() const
00705       {
00706     const Hashtable* This = static_cast<const Hashtable*>(this);
00707     return This->rehash_policy().max_load_factor();
00708       }
00709 
00710       void
00711       max_load_factor(float z)
00712       {
00713     Hashtable* This = static_cast<Hashtable*>(this);
00714     This->rehash_policy(prime_rehash_policy(z));    
00715       }
00716     };
00717 
00718   // Class template hash_code_base.  Encapsulates two policy issues that
00719   // aren't quite orthogonal.
00720   //   (1) the difference between using a ranged hash function and using
00721   //       the combination of a hash function and a range-hashing function.
00722   //       In the former case we don't have such things as hash codes, so
00723   //       we have a dummy type as placeholder.
00724   //   (2) Whether or not we cache hash codes.  Caching hash codes is
00725   //       meaningless if we have a ranged hash function.
00726   // We also put the key extraction and equality comparison function 
00727   // objects here, for convenience.
00728   
00729   // Primary template: unused except as a hook for specializations.
00730   
00731   template<typename Key, typename Value,
00732        typename ExtractKey, typename Equal,
00733        typename H1, typename H2, typename H,
00734        bool cache_hash_code>
00735     struct hash_code_base;
00736 
00737   // Specialization: ranged hash function, no caching hash codes.  H1
00738   // and H2 are provided but ignored.  We define a dummy hash code type.
00739   template<typename Key, typename Value,
00740        typename ExtractKey, typename Equal,
00741        typename H1, typename H2, typename H>
00742     struct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H, false>
00743     {
00744     protected:
00745       hash_code_base(const ExtractKey& ex, const Equal& eq,
00746              const H1&, const H2&, const H& h)
00747       : m_extract(ex), m_eq(eq), m_ranged_hash(h) { }
00748 
00749       typedef void* hash_code_t;
00750   
00751       hash_code_t
00752       m_hash_code(const Key& k) const
00753       { return 0; }
00754   
00755       std::size_t
00756       bucket_index(const Key& k, hash_code_t, std::size_t N) const
00757       { return m_ranged_hash(k, N); }
00758 
00759       std::size_t
00760       bucket_index(const hash_node<Value, false>* p, std::size_t N) const
00761       { return m_ranged_hash(m_extract(p->m_v), N); }
00762   
00763       bool
00764       compare(const Key& k, hash_code_t, hash_node<Value, false>* n) const
00765       { return m_eq(k, m_extract(n->m_v)); }
00766 
00767       void
00768       store_code(hash_node<Value, false>*, hash_code_t) const
00769       { }
00770 
00771       void
00772       copy_code(hash_node<Value, false>*, const hash_node<Value, false>*) const
00773       { }
00774       
00775       void
00776       m_swap(hash_code_base& x)
00777       {
00778     std::swap(m_extract, x.m_extract);
00779     std::swap(m_eq, x.m_eq);
00780     std::swap(m_ranged_hash, x.m_ranged_hash);
00781       }
00782 
00783     protected:
00784       ExtractKey m_extract;
00785       Equal m_eq;
00786       H m_ranged_hash;
00787     };
00788 
00789 
00790   // No specialization for ranged hash function while caching hash codes.
00791   // That combination is meaningless, and trying to do it is an error.
00792   
00793   
00794   // Specialization: ranged hash function, cache hash codes.  This
00795   // combination is meaningless, so we provide only a declaration
00796   // and no definition.
00797   
00798   template<typename Key, typename Value,
00799         typename ExtractKey, typename Equal,
00800         typename H1, typename H2, typename H>
00801     struct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H, true>;
00802 
00803 
00804   // Specialization: hash function and range-hashing function, no
00805   // caching of hash codes.  H is provided but ignored.  Provides
00806   // typedef and accessor required by TR1.
00807   
00808   template<typename Key, typename Value,
00809        typename ExtractKey, typename Equal,
00810        typename H1, typename H2>
00811     struct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2,
00812               default_ranged_hash, false>
00813     {
00814       typedef H1 hasher;
00815       
00816       hasher
00817       hash_function() const
00818       { return m_h1; }
00819 
00820     protected:
00821       hash_code_base(const ExtractKey& ex, const Equal& eq,
00822              const H1& h1, const H2& h2, const default_ranged_hash&)
00823       : m_extract(ex), m_eq(eq), m_h1(h1), m_h2(h2) { }
00824 
00825       typedef std::size_t hash_code_t;
00826       
00827       hash_code_t
00828       m_hash_code(const Key& k) const
00829       { return m_h1(k); }
00830       
00831       std::size_t
00832       bucket_index(const Key&, hash_code_t c, std::size_t N) const
00833       { return m_h2(c, N); }
00834 
00835       std::size_t
00836       bucket_index(const hash_node<Value, false>* p, std::size_t N) const
00837       { return m_h2(m_h1(m_extract(p->m_v)), N); }
00838 
00839       bool
00840       compare(const Key& k, hash_code_t, hash_node<Value, false>* n) const
00841       { return m_eq(k, m_extract(n->m_v)); }
00842 
00843       void
00844       store_code(hash_node<Value, false>*, hash_code_t) const
00845       { }
00846 
00847       void
00848       copy_code(hash_node<Value, false>*, const hash_node<Value, false>*) const
00849       { }
00850 
00851       void
00852       m_swap(hash_code_base& x)
00853       {
00854     std::swap(m_extract, x.m_extract);
00855     std::swap(m_eq, x.m_eq);
00856     std::swap(m_h1, x.m_h1);
00857     std::swap(m_h2, x.m_h2);
00858       }
00859 
00860     protected:
00861       ExtractKey m_extract;
00862       Equal m_eq;
00863       H1 m_h1;
00864       H2 m_h2;
00865     };
00866 
00867   // Specialization: hash function and range-hashing function, 
00868   // caching hash codes.  H is provided but ignored.  Provides
00869   // typedef and accessor required by TR1.
00870   template<typename Key, typename Value,
00871        typename ExtractKey, typename Equal,
00872        typename H1, typename H2>
00873     struct hash_code_base<Key, Value, ExtractKey, Equal, H1, H2,
00874               default_ranged_hash, true>
00875     {
00876       typedef H1 hasher;
00877       
00878       hasher
00879       hash_function() const
00880       { return m_h1; }
00881 
00882     protected:
00883       hash_code_base(const ExtractKey& ex, const Equal& eq,
00884              const H1& h1, const H2& h2, const default_ranged_hash&)
00885       : m_extract(ex), m_eq(eq), m_h1(h1), m_h2(h2) { }
00886 
00887       typedef std::size_t hash_code_t;
00888   
00889       hash_code_t
00890       m_hash_code(const Key& k) const
00891       { return m_h1(k); }
00892   
00893       std::size_t
00894       bucket_index(const Key&, hash_code_t c, std::size_t N) const
00895       { return m_h2(c, N); }
00896 
00897       std::size_t
00898       bucket_index(const hash_node<Value, true>* p, std::size_t N) const
00899       { return m_h2(p->hash_code, N); }
00900 
00901       bool
00902       compare(const Key& k, hash_code_t c, hash_node<Value, true>* n) const
00903       { return c == n->hash_code && m_eq(k, m_extract(n->m_v)); }
00904 
00905       void
00906       store_code(hash_node<Value, true>* n, hash_code_t c) const
00907       { n->hash_code = c; }
00908 
00909       void
00910       copy_code(hash_node<Value, true>* to,
00911         const hash_node<Value, true>* from) const
00912       { to->hash_code = from->hash_code; }
00913 
00914       void
00915       m_swap(hash_code_base& x)
00916       {
00917     std::swap(m_extract, x.m_extract);
00918     std::swap(m_eq, x.m_eq);
00919     std::swap(m_h1, x.m_h1);
00920     std::swap(m_h2, x.m_h2);
00921       }
00922       
00923     protected:
00924       ExtractKey m_extract;
00925       Equal m_eq;
00926       H1 m_h1;
00927       H2 m_h2;
00928     };
00929 
00930 } // namespace internal
00931 
00932 namespace std
00933 { 
00934 namespace tr1
00935 {
00936   //----------------------------------------------------------------------
00937   // Class template hashtable, class definition.
00938   
00939   // Meaning of class template hashtable's template parameters
00940   
00941   // Key and Value: arbitrary CopyConstructible types.
00942   
00943   // Allocator: an allocator type ([lib.allocator.requirements]) whose
00944   // value type is Value.
00945   
00946   // ExtractKey: function object that takes a object of type Value
00947   // and returns a value of type Key.
00948   
00949   // Equal: function object that takes two objects of type k and returns
00950   // a bool-like value that is true if the two objects are considered equal.
00951   
00952   // H1: the hash function.  A unary function object with argument type
00953   // Key and result type size_t.  Return values should be distributed
00954   // over the entire range [0, numeric_limits<size_t>:::max()].
00955   
00956   // H2: the range-hashing function (in the terminology of Tavori and
00957   // Dreizin).  A binary function object whose argument types and result
00958   // type are all size_t.  Given arguments r and N, the return value is
00959   // in the range [0, N).
00960   
00961   // H: the ranged hash function (Tavori and Dreizin). A binary function
00962   // whose argument types are Key and size_t and whose result type is
00963   // size_t.  Given arguments k and N, the return value is in the range
00964   // [0, N).  Default: h(k, N) = h2(h1(k), N).  If H is anything other
00965   // than the default, H1 and H2 are ignored.
00966   
00967   // RehashPolicy: Policy class with three members, all of which govern
00968   // the bucket count. n_bkt(n) returns a bucket count no smaller
00969   // than n.  bkt_for_elements(n) returns a bucket count appropriate
00970   // for an element count of n.  need_rehash(n_bkt, n_elt, n_ins)
00971   // determines whether, if the current bucket count is n_bkt and the
00972   // current element count is n_elt, we need to increase the bucket
00973   // count.  If so, returns make_pair(true, n), where n is the new
00974   // bucket count.  If not, returns make_pair(false, <anything>).
00975   
00976   // ??? Right now it is hard-wired that the number of buckets never
00977   // shrinks.  Should we allow RehashPolicy to change that?
00978   
00979   // cache_hash_code: bool.  true if we store the value of the hash
00980   // function along with the value.  This is a time-space tradeoff.
00981   // Storing it may improve lookup speed by reducing the number of times
00982   // we need to call the Equal function.
00983   
00984   // constant_iterators: bool.  true if iterator and const_iterator are
00985   // both constant iterator types.  This is true for unordered_set and
00986   // unordered_multiset, false for unordered_map and unordered_multimap.
00987   
00988   // unique_keys: bool.  true if the return value of hashtable::count(k)
00989   // is always at most one, false if it may be an arbitrary number.  This
00990   // true for unordered_set and unordered_map, false for unordered_multiset
00991   // and unordered_multimap.
00992   
00993   template<typename Key, typename Value, 
00994        typename Allocator,
00995        typename ExtractKey, typename Equal,
00996        typename H1, typename H2,
00997        typename H, typename RehashPolicy,
00998        bool cache_hash_code,
00999        bool constant_iterators,
01000        bool unique_keys>
01001     class hashtable
01002     : public Internal::rehash_base<RehashPolicy,
01003                    hashtable<Key, Value, Allocator, ExtractKey,
01004                          Equal, H1, H2, H, RehashPolicy,
01005                          cache_hash_code, constant_iterators,
01006                          unique_keys> >,
01007       public Internal::hash_code_base<Key, Value, ExtractKey, Equal, H1, H2, H,
01008                       cache_hash_code>,
01009       public Internal::map_base<Key, Value, ExtractKey, unique_keys,
01010                 hashtable<Key, Value, Allocator, ExtractKey,
01011                       Equal, H1, H2, H, RehashPolicy,
01012                       cache_hash_code, constant_iterators,
01013                       unique_keys> >
01014     {
01015     public:
01016       typedef Allocator                                      allocator_type;
01017       typedef Value                                          value_type;
01018       typedef Key                                            key_type;
01019       typedef Equal                                          key_equal;
01020       // mapped_type, if present, comes from map_base.
01021       // hasher, if present, comes from hash_code_base.
01022       typedef typename Allocator::difference_type            difference_type;
01023       typedef typename Allocator::size_type                  size_type;
01024       typedef typename Allocator::reference                  reference;
01025       typedef typename Allocator::const_reference            const_reference;
01026       
01027       typedef Internal::node_iterator<value_type, constant_iterators,
01028                       cache_hash_code>
01029         local_iterator;
01030       typedef Internal::node_const_iterator<value_type, constant_iterators,
01031                         cache_hash_code>
01032         const_local_iterator;
01033 
01034       typedef Internal::hashtable_iterator<value_type, constant_iterators,
01035                        cache_hash_code>
01036         iterator;
01037       typedef Internal::hashtable_const_iterator<value_type, constant_iterators,
01038                          cache_hash_code>
01039         const_iterator;
01040 
01041       template<typename K, typename Pair, typename Hashtable>
01042         friend struct Internal::map_base;
01043 
01044     private:
01045       typedef Internal::hash_node<Value, cache_hash_code>    node;
01046       typedef typename Allocator::template rebind<node>::other
01047         node_allocator_t;
01048       typedef typename Allocator::template rebind<node*>::other
01049         bucket_allocator_t;
01050 
01051     private:
01052       node_allocator_t m_node_allocator;
01053       node** m_buckets;
01054       size_type m_bucket_count;
01055       size_type m_element_count;
01056       RehashPolicy m_rehash_policy;
01057       
01058       node*
01059       m_allocate_node(const value_type& v);
01060   
01061       void
01062       m_deallocate_node(node* n);
01063   
01064       void
01065       m_deallocate_nodes(node**, size_type);
01066 
01067       node**
01068       m_allocate_buckets(size_type n);
01069   
01070       void
01071       m_deallocate_buckets(node**, size_type n);
01072 
01073     public:             // Constructor, destructor, assignment, swap
01074       hashtable(size_type bucket_hint,
01075         const H1&, const H2&, const H&,
01076         const Equal&, const ExtractKey&,
01077         const allocator_type&);
01078   
01079       template<typename InIter>
01080         hashtable(InIter first, InIter last,
01081           size_type bucket_hint,
01082           const H1&, const H2&, const H&,
01083           const Equal&, const ExtractKey&,
01084           const allocator_type&);
01085   
01086       hashtable(const hashtable&);
01087       
01088       hashtable&
01089       operator=(const hashtable&);
01090   
01091       ~hashtable();
01092 
01093       void swap(hashtable&);
01094 
01095     public:             // Basic container operations
01096       iterator
01097       begin()
01098       {
01099     iterator i(m_buckets);
01100     if (!i.m_cur_node)
01101       i.m_incr_bucket();
01102     return i;
01103       }
01104 
01105       const_iterator
01106       begin() const
01107       {
01108     const_iterator i(m_buckets);
01109     if (!i.m_cur_node)
01110       i.m_incr_bucket();
01111     return i;
01112       }
01113 
01114       iterator
01115       end()
01116       { return iterator(m_buckets + m_bucket_count); }
01117 
01118       const_iterator
01119       end() const
01120       { return const_iterator(m_buckets + m_bucket_count); }
01121 
01122       size_type
01123       size() const
01124       { return m_element_count; }
01125   
01126       bool
01127       empty() const
01128       { return size() == 0; }
01129 
01130       allocator_type
01131       get_allocator() const
01132       { return m_node_allocator; }
01133   
01134       size_type
01135       max_size() const
01136       { return m_node_allocator.max_size(); }
01137 
01138     public:                             // Observers
01139       key_equal
01140       key_eq() const
01141       { return this->m_eq; }
01142 
01143       // hash_function, if present, comes from hash_code_base.
01144 
01145     public:             // Bucket operations
01146       size_type
01147       bucket_count() const
01148       { return m_bucket_count; }
01149   
01150       size_type
01151       max_bucket_count() const
01152       { return max_size(); }
01153   
01154       size_type
01155       bucket_size(size_type n) const
01156       { return std::distance(begin(n), end(n)); }
01157   
01158       size_type
01159       bucket(const key_type& k) const
01160       { 
01161     return this->bucket_index(k, this->m_hash_code(k),
01162                   this->m_bucket_count);
01163       }
01164 
01165       local_iterator
01166       begin(size_type n)
01167       { return local_iterator(m_buckets[n]); }
01168   
01169       local_iterator
01170       end(size_type)
01171       { return local_iterator(0); }
01172   
01173       const_local_iterator
01174       begin(size_type n) const
01175       { return const_local_iterator(m_buckets[n]); }
01176   
01177       const_local_iterator
01178       end(size_type) const
01179       { return const_local_iterator(0); }
01180 
01181       float
01182       load_factor() const
01183       { 
01184     return static_cast<float>(size()) / static_cast<float>(bucket_count());
01185       }
01186       // max_load_factor, if present, comes from rehash_base.
01187 
01188       // Generalization of max_load_factor.  Extension, not found in TR1.  Only
01189       // useful if RehashPolicy is something other than the default.
01190       const RehashPolicy&
01191       rehash_policy() const
01192       { return m_rehash_policy; }
01193       
01194       void 
01195       rehash_policy(const RehashPolicy&);
01196 
01197     public:             // lookup
01198       iterator
01199       find(const key_type& k);
01200 
01201       const_iterator
01202       find(const key_type& k) const;
01203 
01204       size_type
01205       count(const key_type& k) const;
01206 
01207       std::pair<iterator, iterator>
01208       equal_range(const key_type& k);
01209 
01210       std::pair<const_iterator, const_iterator>
01211       equal_range(const key_type& k) const;
01212 
01213     private:            // Find, insert and erase helper functions
01214       // ??? This dispatching is a workaround for the fact that we don't
01215       // have partial specialization of member templates; it would be
01216       // better to just specialize insert on unique_keys.  There may be a
01217       // cleaner workaround.
01218       typedef typename Internal::IF<unique_keys,
01219                     std::pair<iterator, bool>, iterator>::type
01220         Insert_Return_Type;
01221 
01222       typedef typename Internal::IF<unique_keys,
01223                     Internal::extract1st<Insert_Return_Type>,
01224                     Internal::identity<Insert_Return_Type>
01225                                    >::type
01226         Insert_Conv_Type;
01227 
01228       node*
01229       m_find_node(node*, const key_type&,
01230           typename hashtable::hash_code_t) const;
01231 
01232       iterator
01233       m_insert_bucket(const value_type&, size_type,
01234               typename hashtable::hash_code_t);
01235 
01236       std::pair<iterator, bool>
01237       m_insert(const value_type&, std::tr1::true_type);
01238   
01239       iterator
01240       m_insert(const value_type&, std::tr1::false_type);
01241 
01242       void
01243       m_erase_node(node*, node**);
01244 
01245     public:             // Insert and erase
01246       Insert_Return_Type
01247       insert(const value_type& v) 
01248       { return m_insert(v, std::tr1::integral_constant<bool, unique_keys>()); }
01249 
01250       iterator
01251       insert(iterator, const value_type& v)
01252       { return iterator(Insert_Conv_Type()(this->insert(v))); }
01253       
01254       const_iterator
01255       insert(const_iterator, const value_type& v)
01256       { return const_iterator(Insert_Conv_Type()(this->insert(v))); }
01257 
01258       template<typename InIter>
01259         void
01260         insert(InIter first, InIter last);
01261 
01262       iterator
01263       erase(iterator);
01264 
01265       const_iterator
01266       erase(const_iterator);
01267 
01268       size_type
01269       erase(const key_type&);
01270 
01271       iterator
01272       erase(iterator, iterator);
01273 
01274       const_iterator
01275       erase(const_iterator, const_iterator);
01276 
01277       void
01278       clear();
01279 
01280     public:
01281       // Set number of buckets to be appropriate for container of n element.
01282       void rehash(size_type n);
01283       
01284     private:
01285       // Unconditionally change size of bucket array to n.
01286       void m_rehash(size_type n);
01287     };
01288 
01289   //----------------------------------------------------------------------
01290   // Definitions of class template hashtable's out-of-line member functions.
01291   
01292   template<typename K, typename V, 
01293        typename A, typename Ex, typename Eq,
01294        typename H1, typename H2, typename H, typename RP,
01295        bool c, bool ci, bool u>
01296     typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::node*
01297     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01298     m_allocate_node(const value_type& v)
01299     {
01300       node* n = m_node_allocator.allocate(1);
01301       try
01302     {
01303       get_allocator().construct(&n->m_v, v);
01304       n->m_next = 0;
01305       return n;
01306     }
01307       catch(...)
01308     {
01309       m_node_allocator.deallocate(n, 1);
01310       __throw_exception_again;
01311     }
01312     }
01313 
01314   template<typename K, typename V, 
01315        typename A, typename Ex, typename Eq,
01316        typename H1, typename H2, typename H, typename RP,
01317        bool c, bool ci, bool u>
01318     void
01319     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01320     m_deallocate_node(node* n)
01321     {
01322       get_allocator().destroy(&n->m_v);
01323       m_node_allocator.deallocate(n, 1);
01324     }
01325 
01326   template<typename K, typename V, 
01327        typename A, typename Ex, typename Eq,
01328        typename H1, typename H2, typename H, typename RP,
01329        bool c, bool ci, bool u>
01330     void
01331     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01332     m_deallocate_nodes(node** array, size_type n)
01333     {
01334       for (size_type i = 0; i < n; ++i)
01335     {
01336       node* p = array[i];
01337       while (p)
01338         {
01339           node* tmp = p;
01340           p = p->m_next;
01341           m_deallocate_node(tmp);
01342         }
01343       array[i] = 0;
01344     }
01345     }
01346 
01347   template<typename K, typename V, 
01348        typename A, typename Ex, typename Eq,
01349        typename H1, typename H2, typename H, typename RP,
01350        bool c, bool ci, bool u>
01351     typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::node**
01352     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01353     m_allocate_buckets(size_type n)
01354     {
01355       bucket_allocator_t alloc(m_node_allocator);
01356 
01357       // We allocate one extra bucket to hold a sentinel, an arbitrary
01358       // non-null pointer.  Iterator increment relies on this.
01359       node** p = alloc.allocate(n + 1);
01360       std::fill(p, p + n, (node*) 0);
01361       p[n] = reinterpret_cast<node*>(0x1000);
01362       return p;
01363     }
01364 
01365   template<typename K, typename V, 
01366        typename A, typename Ex, typename Eq,
01367        typename H1, typename H2, typename H, typename RP,
01368        bool c, bool ci, bool u>
01369     void
01370     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01371     m_deallocate_buckets(node** p, size_type n)
01372     {
01373       bucket_allocator_t alloc(m_node_allocator);
01374       alloc.deallocate(p, n + 1);
01375     }
01376 
01377   template<typename K, typename V, 
01378        typename A, typename Ex, typename Eq,
01379        typename H1, typename H2, typename H, typename RP,
01380        bool c, bool ci, bool u>
01381     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01382     hashtable(size_type bucket_hint,
01383           const H1& h1, const H2& h2, const H& h,
01384           const Eq& eq, const Ex& exk,
01385           const allocator_type& a)
01386     : Internal::rehash_base<RP, hashtable>(),
01387       Internal::hash_code_base<K, V, Ex, Eq, H1, H2, H, c>(exk, eq, h1, h2, h),
01388       Internal::map_base<K, V, Ex, u, hashtable>(),
01389       m_node_allocator(a),
01390       m_bucket_count(0),
01391       m_element_count(0),
01392       m_rehash_policy()
01393     {
01394       m_bucket_count = m_rehash_policy.next_bkt(bucket_hint);
01395       m_buckets = m_allocate_buckets(m_bucket_count);
01396     }
01397 
01398   template<typename K, typename V, 
01399        typename A, typename Ex, typename Eq,
01400        typename H1, typename H2, typename H, typename RP,
01401        bool c, bool ci, bool u>
01402     template<typename InIter>
01403       hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01404       hashtable(InIter f, InIter l,
01405         size_type bucket_hint,
01406         const H1& h1, const H2& h2, const H& h,
01407         const Eq& eq, const Ex& exk,
01408         const allocator_type& a)
01409       : Internal::rehash_base<RP, hashtable>(),
01410     Internal::hash_code_base<K, V, Ex, Eq, H1, H2, H, c>(exk, eq,
01411                                  h1, h2, h),
01412     Internal::map_base<K, V, Ex, u, hashtable>(),
01413     m_node_allocator(a),
01414     m_bucket_count(0),
01415     m_element_count(0),
01416     m_rehash_policy()
01417       {
01418     m_bucket_count = std::max(m_rehash_policy.next_bkt(bucket_hint),
01419                   m_rehash_policy.
01420                   bkt_for_elements(Internal::
01421                            distance_fw(f, l)));
01422     m_buckets = m_allocate_buckets(m_bucket_count);
01423     try
01424       {
01425         for (; f != l; ++f)
01426           this->insert(*f);
01427       }
01428     catch(...)
01429       {
01430         clear();
01431         m_deallocate_buckets(m_buckets, m_bucket_count);
01432         __throw_exception_again;
01433       }
01434       }
01435   
01436   template<typename K, typename V, 
01437        typename A, typename Ex, typename Eq,
01438        typename H1, typename H2, typename H, typename RP,
01439        bool c, bool ci, bool u>
01440     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01441     hashtable(const hashtable& ht)
01442     : Internal::rehash_base<RP, hashtable>(ht),
01443       Internal::hash_code_base<K, V, Ex, Eq, H1, H2, H, c>(ht),
01444       Internal::map_base<K, V, Ex, u, hashtable>(ht),
01445       m_node_allocator(ht.get_allocator()),
01446       m_bucket_count(ht.m_bucket_count),
01447       m_element_count(ht.m_element_count),
01448       m_rehash_policy(ht.m_rehash_policy)
01449     {
01450       m_buckets = m_allocate_buckets(m_bucket_count);
01451       try
01452     {
01453       for (size_type i = 0; i < ht.m_bucket_count; ++i)
01454         {
01455           node* n = ht.m_buckets[i];
01456           node** tail = m_buckets + i;
01457           while (n)
01458         {
01459           *tail = m_allocate_node(n->m_v);
01460           this->copy_code(*tail, n);
01461           tail = &((*tail)->m_next);
01462           n = n->m_next;
01463         }
01464         }
01465     }
01466       catch(...)
01467     {
01468       clear();
01469       m_deallocate_buckets(m_buckets, m_bucket_count);
01470       __throw_exception_again;
01471     }
01472     }
01473 
01474   template<typename K, typename V, 
01475        typename A, typename Ex, typename Eq,
01476        typename H1, typename H2, typename H, typename RP,
01477        bool c, bool ci, bool u>
01478     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>&
01479     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01480     operator=(const hashtable& ht)
01481     {
01482       hashtable tmp(ht);
01483       this->swap(tmp);
01484       return *this;
01485     }
01486 
01487   template<typename K, typename V, 
01488        typename A, typename Ex, typename Eq,
01489        typename H1, typename H2, typename H, typename RP,
01490        bool c, bool ci, bool u>
01491     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01492     ~hashtable()
01493     {
01494       clear();
01495       m_deallocate_buckets(m_buckets, m_bucket_count);
01496     }
01497 
01498   template<typename K, typename V, 
01499        typename A, typename Ex, typename Eq,
01500        typename H1, typename H2, typename H, typename RP,
01501        bool c, bool ci, bool u>
01502     void
01503     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01504     swap(hashtable& x)
01505     {
01506       // The only base class with member variables is hash_code_base.  We
01507       // define hash_code_base::m_swap because different specializations
01508       // have different members.
01509       Internal::hash_code_base<K, V, Ex, Eq, H1, H2, H, c>::m_swap(x);
01510 
01511       // open LWG issue 431
01512       // std::swap(m_node_allocator, x.m_node_allocator);
01513       std::swap(m_rehash_policy, x.m_rehash_policy);
01514       std::swap(m_buckets, x.m_buckets);
01515       std::swap(m_bucket_count, x.m_bucket_count);
01516       std::swap(m_element_count, x.m_element_count);
01517     }
01518 
01519   template<typename K, typename V, 
01520        typename A, typename Ex, typename Eq,
01521        typename H1, typename H2, typename H, typename RP,
01522        bool c, bool ci, bool u>
01523     void
01524     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01525     rehash_policy(const RP& pol)
01526     {
01527       m_rehash_policy = pol;
01528       size_type n_bkt = pol.bkt_for_elements(m_element_count);
01529       if (n_bkt > m_bucket_count)
01530     m_rehash(n_bkt);
01531     }
01532 
01533   template<typename K, typename V, 
01534        typename A, typename Ex, typename Eq,
01535        typename H1, typename H2, typename H, typename RP,
01536        bool c, bool ci, bool u>
01537     typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::iterator
01538     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01539     find(const key_type& k)
01540     {
01541       typename hashtable::hash_code_t code = this->m_hash_code(k);
01542       std::size_t n = this->bucket_index(k, code, this->bucket_count());
01543       node* p = m_find_node(m_buckets[n], k, code);
01544       return p ? iterator(p, m_buckets + n) : this->end();
01545     }
01546   
01547   template<typename K, typename V, 
01548        typename A, typename Ex, typename Eq,
01549        typename H1, typename H2, typename H, typename RP,
01550        bool c, bool ci, bool u>
01551     typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::const_iterator
01552     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01553     find(const key_type& k) const
01554     {
01555       typename hashtable::hash_code_t code = this->m_hash_code(k);
01556       std::size_t n = this->bucket_index(k, code, this->bucket_count());
01557       node* p = m_find_node(m_buckets[n], k, code);
01558       return p ? const_iterator(p, m_buckets + n) : this->end();
01559     }
01560   
01561   template<typename K, typename V, 
01562        typename A, typename Ex, typename Eq,
01563        typename H1, typename H2, typename H, typename RP,
01564        bool c, bool ci, bool u>
01565     typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::size_type
01566     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01567     count(const key_type& k) const
01568     {
01569       typename hashtable::hash_code_t code = this->m_hash_code(k);
01570       std::size_t n = this->bucket_index(k, code, this->bucket_count());
01571       std::size_t result = 0;
01572       for (node* p = m_buckets[n]; p; p = p->m_next)
01573     if (this->compare(k, code, p))
01574       ++result;
01575       return result;
01576     }
01577 
01578   template<typename K, typename V, 
01579        typename A, typename Ex, typename Eq,
01580        typename H1, typename H2, typename H, typename RP,
01581        bool c, bool ci, bool u>
01582     std::pair<typename hashtable<K, V, A, Ex, Eq, H1,
01583                  H2, H, RP, c, ci, u>::iterator,
01584           typename hashtable<K, V, A, Ex, Eq, H1,
01585                  H2, H, RP, c, ci, u>::iterator>
01586     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01587     equal_range(const key_type& k)
01588     {
01589       typename hashtable::hash_code_t code = this->m_hash_code(k);
01590       std::size_t n = this->bucket_index(k, code, this->bucket_count());
01591       node** head = m_buckets + n;
01592       node* p = m_find_node(*head, k, code);
01593 
01594       if (p)
01595     {
01596       node* p1 = p->m_next;
01597       for (; p1; p1 = p1->m_next)
01598         if (!this->compare(k, code, p1))
01599           break;
01600 
01601       iterator first(p, head);
01602       iterator last(p1, head);
01603       if (!p1)
01604         last.m_incr_bucket();
01605       return std::make_pair(first, last);
01606     }
01607       else
01608     return std::make_pair(this->end(), this->end());
01609     }
01610 
01611   template<typename K, typename V, 
01612        typename A, typename Ex, typename Eq,
01613        typename H1, typename H2, typename H, typename RP,
01614        bool c, bool ci, bool u>
01615     std::pair<typename hashtable<K, V, A, Ex, Eq, H1,
01616                  H2, H, RP, c, ci, u>::const_iterator,
01617           typename hashtable<K, V, A, Ex, Eq, H1,
01618                  H2, H, RP, c, ci, u>::const_iterator>
01619     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01620     equal_range(const key_type& k) const
01621     {
01622       typename hashtable::hash_code_t code = this->m_hash_code(k);
01623       std::size_t n = this->bucket_index(k, code, this->bucket_count());
01624       node** head = m_buckets + n;
01625       node* p = m_find_node(*head, k, code);
01626 
01627       if (p)
01628     {
01629       node* p1 = p->m_next;
01630       for (; p1; p1 = p1->m_next)
01631         if (!this->compare(k, code, p1))
01632           break;
01633 
01634       const_iterator first(p, head);
01635       const_iterator last(p1, head);
01636       if (!p1)
01637         last.m_incr_bucket();
01638       return std::make_pair(first, last);
01639     }
01640       else
01641     return std::make_pair(this->end(), this->end());
01642     }
01643 
01644   // Find the node whose key compares equal to k, beginning the search
01645   // at p (usually the head of a bucket).  Return nil if no node is found.
01646   template<typename K, typename V, 
01647        typename A, typename Ex, typename Eq,
01648        typename H1, typename H2, typename H, typename RP,
01649        bool c, bool ci, bool u>
01650     typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::node* 
01651     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01652     m_find_node(node* p, const key_type& k,
01653         typename hashtable::hash_code_t code) const
01654     {
01655       for (; p; p = p->m_next)
01656     if (this->compare(k, code, p))
01657       return p;
01658       return false;
01659     }
01660 
01661   // Insert v in bucket n (assumes no element with its key already present).
01662   template<typename K, typename V, 
01663        typename A, typename Ex, typename Eq,
01664        typename H1, typename H2, typename H, typename RP,
01665        bool c, bool ci, bool u>
01666     typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::iterator
01667     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01668     m_insert_bucket(const value_type& v, size_type n,
01669             typename hashtable::hash_code_t code)
01670     {
01671       std::pair<bool, std::size_t> do_rehash
01672     = m_rehash_policy.need_rehash(m_bucket_count, m_element_count, 1);
01673 
01674       // Allocate the new node before doing the rehash so that we don't
01675       // do a rehash if the allocation throws.
01676       node* new_node = m_allocate_node(v);
01677 
01678       try
01679     {
01680       if (do_rehash.first)
01681         {
01682           const key_type& k = this->m_extract(v);
01683           n = this->bucket_index(k, code, do_rehash.second);
01684           m_rehash(do_rehash.second);
01685         }
01686 
01687       new_node->m_next = m_buckets[n];
01688       this->store_code(new_node, code);
01689       m_buckets[n] = new_node;
01690       ++m_element_count;
01691       return iterator(new_node, m_buckets + n);
01692     }
01693       catch(...)
01694     {
01695       m_deallocate_node(new_node);
01696       __throw_exception_again;
01697     }
01698     }
01699 
01700   // Insert v if no element with its key is already present.
01701   template<typename K, typename V, 
01702        typename A, typename Ex, typename Eq,
01703        typename H1, typename H2, typename H, typename RP,
01704        bool c, bool ci, bool u>
01705     std::pair<typename hashtable<K, V, A, Ex, Eq, H1,
01706                  H2, H, RP, c, ci, u>::iterator, bool>
01707     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01708     m_insert(const value_type& v, std::tr1::true_type)
01709     {
01710       const key_type& k = this->m_extract(v);
01711       typename hashtable::hash_code_t code = this->m_hash_code(k);
01712       size_type n = this->bucket_index(k, code, m_bucket_count);
01713 
01714       if (node* p = m_find_node(m_buckets[n], k, code))
01715     return std::make_pair(iterator(p, m_buckets + n), false);
01716       return std::make_pair(m_insert_bucket(v, n, code), true);
01717     }
01718 
01719   // Insert v unconditionally.
01720   template<typename K, typename V, 
01721        typename A, typename Ex, typename Eq,
01722        typename H1, typename H2, typename H, typename RP,
01723        bool c, bool ci, bool u>
01724     typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::iterator
01725     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01726     m_insert(const value_type& v, std::tr1::false_type)
01727     {
01728       std::pair<bool, std::size_t> do_rehash
01729     = m_rehash_policy.need_rehash(m_bucket_count, m_element_count, 1);
01730       if (do_rehash.first)
01731     m_rehash(do_rehash.second);
01732 
01733       const key_type& k = this->m_extract(v);
01734       typename hashtable::hash_code_t code = this->m_hash_code(k);
01735       size_type n = this->bucket_index(k, code, m_bucket_count);
01736 
01737       // First find the node, avoid leaking new_node if compare throws.
01738       node* prev = m_find_node(m_buckets[n], k, code);
01739       node* new_node = m_allocate_node(v);
01740 
01741       if (prev)
01742     {
01743       new_node->m_next = prev->m_next;
01744       prev->m_next = new_node;
01745     }
01746       else
01747     {
01748       new_node->m_next = m_buckets[n];
01749       m_buckets[n] = new_node;
01750     }
01751       this->store_code(new_node, code);
01752 
01753       ++m_element_count;
01754       return iterator(new_node, m_buckets + n);
01755     }
01756 
01757   // For erase(iterator) and erase(const_iterator).
01758   template<typename K, typename V, 
01759        typename A, typename Ex, typename Eq,
01760        typename H1, typename H2, typename H, typename RP,
01761        bool c, bool ci, bool u>
01762     void
01763     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01764     m_erase_node(node* p, node** b)
01765     {
01766       node* cur = *b;
01767       if (cur == p)
01768     *b = cur->m_next;
01769       else
01770     {
01771       node* next = cur->m_next;
01772       while (next != p)
01773         {
01774           cur = next;
01775           next = cur->m_next;
01776         }
01777       cur->m_next = next->m_next;
01778     }
01779 
01780       m_deallocate_node(p);
01781       --m_element_count;
01782     }
01783 
01784   template<typename K, typename V, 
01785        typename A, typename Ex, typename Eq,
01786        typename H1, typename H2, typename H, typename RP,
01787        bool c, bool ci, bool u>
01788     template<typename InIter>
01789       void 
01790       hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01791       insert(InIter first, InIter last)
01792       {
01793     size_type n_elt = Internal::distance_fw(first, last);
01794     std::pair<bool, std::size_t> do_rehash
01795       = m_rehash_policy.need_rehash(m_bucket_count, m_element_count, n_elt);
01796     if (do_rehash.first)
01797       m_rehash(do_rehash.second);
01798 
01799     for (; first != last; ++first)
01800       this->insert(*first);
01801       }
01802 
01803   template<typename K, typename V, 
01804        typename A, typename Ex, typename Eq,
01805        typename H1, typename H2, typename H, typename RP,
01806        bool c, bool ci, bool u>
01807     typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::iterator
01808     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01809     erase(iterator it)
01810     {
01811       iterator result = it;
01812       ++result;
01813       m_erase_node(it.m_cur_node, it.m_cur_bucket);
01814       return result;
01815     }
01816   
01817   template<typename K, typename V, 
01818        typename A, typename Ex, typename Eq,
01819        typename H1, typename H2, typename H, typename RP,
01820        bool c, bool ci, bool u>
01821     typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::const_iterator
01822     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01823     erase(const_iterator it)
01824     {
01825       const_iterator result = it;
01826       ++result;
01827       m_erase_node(it.m_cur_node, it.m_cur_bucket);
01828       return result;
01829     }
01830 
01831   template<typename K, typename V, 
01832        typename A, typename Ex, typename Eq,
01833        typename H1, typename H2, typename H, typename RP,
01834        bool c, bool ci, bool u>
01835     typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::size_type
01836     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01837     erase(const key_type& k)
01838     {
01839       typename hashtable::hash_code_t code = this->m_hash_code(k);
01840       size_type n = this->bucket_index(k, code, m_bucket_count);
01841       size_type result = 0;
01842       
01843       node** slot = m_buckets + n;
01844       while (*slot && !this->compare(k, code, *slot))
01845     slot = &((*slot)->m_next);
01846 
01847       while (*slot && this->compare(k, code, *slot))
01848     {
01849       node* p = *slot;
01850       *slot = p->m_next;
01851       m_deallocate_node(p);
01852       --m_element_count;
01853       ++result;
01854     }
01855 
01856       return result;
01857     }
01858 
01859   // ??? This could be optimized by taking advantage of the bucket
01860   // structure, but it's not clear that it's worth doing.  It probably
01861   // wouldn't even be an optimization unless the load factor is large.
01862   template<typename K, typename V, 
01863        typename A, typename Ex, typename Eq,
01864        typename H1, typename H2, typename H, typename RP,
01865        bool c, bool ci, bool u>
01866     typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::iterator
01867     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01868     erase(iterator first, iterator last)
01869     {
01870       while (first != last)
01871     first = this->erase(first);
01872       return last;
01873     }
01874   
01875   template<typename K, typename V, 
01876        typename A, typename Ex, typename Eq,
01877        typename H1, typename H2, typename H, typename RP,
01878        bool c, bool ci, bool u>
01879     typename hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::const_iterator
01880     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01881     erase(const_iterator first, const_iterator last)
01882     {
01883       while (first != last)
01884     first = this->erase(first);
01885       return last;
01886     }
01887 
01888   template<typename K, typename V, 
01889        typename A, typename Ex, typename Eq,
01890        typename H1, typename H2, typename H, typename RP,
01891        bool c, bool ci, bool u>
01892     void
01893     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01894     clear()
01895     {
01896       m_deallocate_nodes(m_buckets, m_bucket_count);
01897       m_element_count = 0;
01898     }
01899 
01900   template<typename K, typename V, 
01901        typename A, typename Ex, typename Eq,
01902        typename H1, typename H2, typename H, typename RP,
01903        bool c, bool ci, bool u>
01904     void
01905     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01906     rehash(size_type n)
01907     {
01908       m_rehash(std::max(m_rehash_policy.next_bkt(n),
01909             m_rehash_policy.bkt_for_elements(m_element_count
01910                              + 1)));
01911     }
01912 
01913   template<typename K, typename V, 
01914        typename A, typename Ex, typename Eq,
01915        typename H1, typename H2, typename H, typename RP,
01916        bool c, bool ci, bool u>
01917     void
01918     hashtable<K, V, A, Ex, Eq, H1, H2, H, RP, c, ci, u>::
01919     m_rehash(size_type n)
01920     {
01921       node** new_array = m_allocate_buckets(n);
01922       try
01923     {
01924       for (size_type i = 0; i < m_bucket_count; ++i)
01925         while (node* p = m_buckets[i])
01926           {
01927         size_type new_index = this->bucket_index(p, n);
01928         m_buckets[i] = p->m_next;
01929         p->m_next = new_array[new_index];
01930         new_array[new_index] = p;
01931           }
01932       m_deallocate_buckets(m_buckets, m_bucket_count);
01933       m_bucket_count = n;
01934       m_buckets = new_array;
01935     }
01936       catch(...)
01937     {
01938       // A failure here means that a hash function threw an exception.
01939       // We can't restore the previous state without calling the hash
01940       // function again, so the only sensible recovery is to delete
01941       // everything.
01942       m_deallocate_nodes(new_array, n);
01943       m_deallocate_buckets(new_array, n);
01944       m_deallocate_nodes(m_buckets, m_bucket_count);
01945       m_element_count = 0;
01946       __throw_exception_again;
01947     }
01948     }
01949 }
01950 }               // Namespace std::tr1
01951 
01952 #endif /* GNU_LIBSTDCXX_TR1_HASHTABLE_ */
01953 

Generated on Tue Feb 2 16:56:08 2010 for GNU C++ STL by  doxygen 1.4.7