bits/hashtable.h

Go to the documentation of this file.
00001 // hashtable.h header -*- C++ -*-
00002 
00003 // Copyright (C) 2007, 2008, 2009, 2010 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 3, 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 // Under Section 7 of GPL version 3, you are granted additional
00017 // permissions described in the GCC Runtime Library Exception, version
00018 // 3.1, as published by the Free Software Foundation.
00019 
00020 // You should have received a copy of the GNU General Public License and
00021 // a copy of the GCC Runtime Library Exception along with this program;
00022 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
00023 // <http://www.gnu.org/licenses/>.
00024 
00025 /** @file bits/hashtable.h
00026  *  This is an internal header file, included by other library headers.
00027  *  You should not attempt to use it directly.
00028  */
00029 
00030 #ifndef _HASHTABLE_H
00031 #define _HASHTABLE_H 1
00032 
00033 #pragma GCC system_header
00034 
00035 #include <bits/hashtable_policy.h>
00036 
00037 namespace std
00038 {
00039   // Class template _Hashtable, class definition.
00040   
00041   // Meaning of class template _Hashtable's template parameters
00042   
00043   // _Key and _Value: arbitrary CopyConstructible types.
00044   
00045   // _Allocator: an allocator type ([lib.allocator.requirements]) whose
00046   // value type is Value.  As a conforming extension, we allow for
00047   // value type != Value.
00048 
00049   // _ExtractKey: function object that takes a object of type Value
00050   // and returns a value of type _Key.
00051   
00052   // _Equal: function object that takes two objects of type k and returns
00053   // a bool-like value that is true if the two objects are considered equal.
00054   
00055   // _H1: the hash function.  A unary function object with argument type
00056   // Key and result type size_t.  Return values should be distributed
00057   // over the entire range [0, numeric_limits<size_t>:::max()].
00058   
00059   // _H2: the range-hashing function (in the terminology of Tavori and
00060   // Dreizin).  A binary function object whose argument types and result
00061   // type are all size_t.  Given arguments r and N, the return value is
00062   // in the range [0, N).
00063   
00064   // _Hash: the ranged hash function (Tavori and Dreizin). A binary function
00065   // whose argument types are _Key and size_t and whose result type is
00066   // size_t.  Given arguments k and N, the return value is in the range
00067   // [0, N).  Default: hash(k, N) = h2(h1(k), N).  If _Hash is anything other
00068   // than the default, _H1 and _H2 are ignored.
00069   
00070   // _RehashPolicy: Policy class with three members, all of which govern
00071   // the bucket count. _M_next_bkt(n) returns a bucket count no smaller
00072   // than n.  _M_bkt_for_elements(n) returns a bucket count appropriate
00073   // for an element count of n.  _M_need_rehash(n_bkt, n_elt, n_ins)
00074   // determines whether, if the current bucket count is n_bkt and the
00075   // current element count is n_elt, we need to increase the bucket
00076   // count.  If so, returns make_pair(true, n), where n is the new
00077   // bucket count.  If not, returns make_pair(false, <anything>).
00078   
00079   // ??? Right now it is hard-wired that the number of buckets never
00080   // shrinks.  Should we allow _RehashPolicy to change that?
00081   
00082   // __cache_hash_code: bool.  true if we store the value of the hash
00083   // function along with the value.  This is a time-space tradeoff.
00084   // Storing it may improve lookup speed by reducing the number of times
00085   // we need to call the Equal function.
00086   
00087   // __constant_iterators: bool.  true if iterator and const_iterator are
00088   // both constant iterator types.  This is true for unordered_set and
00089   // unordered_multiset, false for unordered_map and unordered_multimap.
00090   
00091   // __unique_keys: bool.  true if the return value of _Hashtable::count(k)
00092   // is always at most one, false if it may be an arbitrary number.  This
00093   // true for unordered_set and unordered_map, false for unordered_multiset
00094   // and unordered_multimap.
00095   
00096   template<typename _Key, typename _Value, typename _Allocator,
00097        typename _ExtractKey, typename _Equal,
00098        typename _H1, typename _H2, typename _Hash, 
00099        typename _RehashPolicy,
00100        bool __cache_hash_code,
00101        bool __constant_iterators,
00102        bool __unique_keys>
00103     class _Hashtable
00104     : public __detail::_Rehash_base<_RehashPolicy,
00105                     _Hashtable<_Key, _Value, _Allocator,
00106                            _ExtractKey,
00107                            _Equal, _H1, _H2, _Hash,
00108                            _RehashPolicy,
00109                            __cache_hash_code,
00110                            __constant_iterators,
00111                            __unique_keys> >,
00112       public __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
00113                        _H1, _H2, _Hash, __cache_hash_code>,
00114       public __detail::_Map_base<_Key, _Value, _ExtractKey, __unique_keys,
00115                  _Hashtable<_Key, _Value, _Allocator,
00116                         _ExtractKey,
00117                         _Equal, _H1, _H2, _Hash,
00118                         _RehashPolicy,
00119                         __cache_hash_code,
00120                         __constant_iterators,
00121                         __unique_keys> >,
00122       public __detail::_Equality_base<_ExtractKey, __unique_keys,
00123                       _Hashtable<_Key, _Value, _Allocator,
00124                          _ExtractKey,
00125                          _Equal, _H1, _H2, _Hash,
00126                          _RehashPolicy,
00127                          __cache_hash_code,
00128                          __constant_iterators,
00129                          __unique_keys> >
00130     {
00131     public:
00132       typedef _Allocator                                  allocator_type;
00133       typedef _Value                                      value_type;
00134       typedef _Key                                        key_type;
00135       typedef _Equal                                      key_equal;
00136       // mapped_type, if present, comes from _Map_base.
00137       // hasher, if present, comes from _Hash_code_base.
00138       typedef typename _Allocator::pointer                pointer;
00139       typedef typename _Allocator::const_pointer          const_pointer;
00140       typedef typename _Allocator::reference              reference;
00141       typedef typename _Allocator::const_reference        const_reference;
00142 
00143       typedef std::size_t                                 size_type;
00144       typedef std::ptrdiff_t                              difference_type;
00145       typedef __detail::_Node_iterator<value_type, __constant_iterators,
00146                        __cache_hash_code>
00147                                                           local_iterator;
00148       typedef __detail::_Node_const_iterator<value_type,
00149                          __constant_iterators,
00150                          __cache_hash_code>
00151                                                           const_local_iterator;
00152 
00153       typedef __detail::_Hashtable_iterator<value_type, __constant_iterators,
00154                         __cache_hash_code>
00155                                                           iterator;
00156       typedef __detail::_Hashtable_const_iterator<value_type,
00157                           __constant_iterators,
00158                           __cache_hash_code>
00159                                                           const_iterator;
00160 
00161       template<typename _Key2, typename _Value2, typename _Ex2, bool __unique2,
00162            typename _Hashtable2>
00163         friend struct __detail::_Map_base;
00164 
00165     private:
00166       typedef __detail::_Hash_node<_Value, __cache_hash_code> _Node;
00167       typedef typename _Allocator::template rebind<_Node>::other
00168                                                         _Node_allocator_type;
00169       typedef typename _Allocator::template rebind<_Node*>::other
00170                                                         _Bucket_allocator_type;
00171 
00172       typedef typename _Allocator::template rebind<_Value>::other
00173                                                         _Value_allocator_type;
00174 
00175       _Node_allocator_type   _M_node_allocator;
00176       _Node**                _M_buckets;
00177       size_type              _M_bucket_count;
00178       size_type              _M_element_count;
00179       _RehashPolicy          _M_rehash_policy;
00180       
00181       _Node*
00182       _M_allocate_node(const value_type& __v);
00183   
00184       void
00185       _M_deallocate_node(_Node* __n);
00186   
00187       void
00188       _M_deallocate_nodes(_Node**, size_type);
00189 
00190       _Node**
00191       _M_allocate_buckets(size_type __n);
00192   
00193       void
00194       _M_deallocate_buckets(_Node**, size_type __n);
00195 
00196     public:             
00197       // Constructor, destructor, assignment, swap
00198       _Hashtable(size_type __bucket_hint,
00199          const _H1&, const _H2&, const _Hash&,
00200          const _Equal&, const _ExtractKey&,
00201          const allocator_type&);
00202   
00203       template<typename _InputIterator>
00204         _Hashtable(_InputIterator __first, _InputIterator __last,
00205            size_type __bucket_hint,
00206            const _H1&, const _H2&, const _Hash&, 
00207            const _Equal&, const _ExtractKey&,
00208            const allocator_type&);
00209   
00210       _Hashtable(const _Hashtable&);
00211 
00212       _Hashtable(_Hashtable&&);
00213       
00214       _Hashtable&
00215       operator=(const _Hashtable&);
00216 
00217       ~_Hashtable();
00218 
00219       void swap(_Hashtable&);
00220 
00221       // Basic container operations
00222       iterator
00223       begin()
00224       {
00225     iterator __i(_M_buckets);
00226     if (!__i._M_cur_node)
00227       __i._M_incr_bucket();
00228     return __i;
00229       }
00230 
00231       const_iterator
00232       begin() const
00233       {
00234     const_iterator __i(_M_buckets);
00235     if (!__i._M_cur_node)
00236       __i._M_incr_bucket();
00237     return __i;
00238       }
00239 
00240       iterator
00241       end()
00242       { return iterator(_M_buckets + _M_bucket_count); }
00243 
00244       const_iterator
00245       end() const
00246       { return const_iterator(_M_buckets + _M_bucket_count); }
00247 
00248       const_iterator
00249       cbegin() const
00250       {
00251     const_iterator __i(_M_buckets);
00252     if (!__i._M_cur_node)
00253       __i._M_incr_bucket();
00254     return __i;
00255       }
00256 
00257       const_iterator
00258       cend() const
00259       { return const_iterator(_M_buckets + _M_bucket_count); }
00260 
00261       size_type
00262       size() const
00263       { return _M_element_count; }
00264   
00265       bool
00266       empty() const
00267       { return size() == 0; }
00268 
00269       allocator_type
00270       get_allocator() const
00271       { return allocator_type(_M_node_allocator); }
00272 
00273       _Value_allocator_type
00274       _M_get_Value_allocator() const
00275       { return _Value_allocator_type(_M_node_allocator); }
00276 
00277       size_type
00278       max_size() const
00279       { return _M_node_allocator.max_size(); }
00280 
00281       // Observers
00282       key_equal
00283       key_eq() const
00284       { return this->_M_eq; }
00285 
00286       // hash_function, if present, comes from _Hash_code_base.
00287 
00288       // Bucket operations
00289       size_type
00290       bucket_count() const
00291       { return _M_bucket_count; }
00292   
00293       size_type
00294       max_bucket_count() const
00295       { return max_size(); }
00296   
00297       size_type
00298       bucket_size(size_type __n) const
00299       { return std::distance(begin(__n), end(__n)); }
00300   
00301       size_type
00302       bucket(const key_type& __k) const
00303       { 
00304     return this->_M_bucket_index(__k, this->_M_hash_code(__k),
00305                      bucket_count());
00306       }
00307 
00308       local_iterator
00309       begin(size_type __n)
00310       { return local_iterator(_M_buckets[__n]); }
00311 
00312       local_iterator
00313       end(size_type)
00314       { return local_iterator(0); }
00315 
00316       const_local_iterator
00317       begin(size_type __n) const
00318       { return const_local_iterator(_M_buckets[__n]); }
00319 
00320       const_local_iterator
00321       end(size_type) const
00322       { return const_local_iterator(0); }
00323 
00324       // DR 691.
00325       const_local_iterator
00326       cbegin(size_type __n) const
00327       { return const_local_iterator(_M_buckets[__n]); }
00328 
00329       const_local_iterator
00330       cend(size_type) const
00331       { return const_local_iterator(0); }
00332 
00333       float
00334       load_factor() const
00335       { 
00336     return static_cast<float>(size()) / static_cast<float>(bucket_count());
00337       }
00338 
00339       // max_load_factor, if present, comes from _Rehash_base.
00340 
00341       // Generalization of max_load_factor.  Extension, not found in TR1.  Only
00342       // useful if _RehashPolicy is something other than the default.
00343       const _RehashPolicy&
00344       __rehash_policy() const
00345       { return _M_rehash_policy; }
00346       
00347       void 
00348       __rehash_policy(const _RehashPolicy&);
00349 
00350       // Lookup.
00351       iterator
00352       find(const key_type& __k);
00353 
00354       const_iterator
00355       find(const key_type& __k) const;
00356 
00357       size_type
00358       count(const key_type& __k) const;
00359 
00360       std::pair<iterator, iterator>
00361       equal_range(const key_type& __k);
00362 
00363       std::pair<const_iterator, const_iterator>
00364       equal_range(const key_type& __k) const;
00365 
00366     private:            // Find, insert and erase helper functions
00367       // ??? This dispatching is a workaround for the fact that we don't
00368       // have partial specialization of member templates; it would be
00369       // better to just specialize insert on __unique_keys.  There may be a
00370       // cleaner workaround.
00371       typedef typename std::conditional<__unique_keys,
00372                     std::pair<iterator, bool>,
00373                     iterator>::type
00374         _Insert_Return_Type;
00375 
00376       typedef typename std::conditional<__unique_keys,
00377                     std::_Select1st<_Insert_Return_Type>,
00378                     std::_Identity<_Insert_Return_Type>
00379                                    >::type
00380         _Insert_Conv_Type;
00381 
00382       _Node*
00383       _M_find_node(_Node*, const key_type&,
00384            typename _Hashtable::_Hash_code_type) const;
00385 
00386       iterator
00387       _M_insert_bucket(const value_type&, size_type,
00388                typename _Hashtable::_Hash_code_type);
00389 
00390       std::pair<iterator, bool>
00391       _M_insert(const value_type&, std::true_type);
00392 
00393       iterator
00394       _M_insert(const value_type&, std::false_type);
00395 
00396       void
00397       _M_erase_node(_Node*, _Node**);
00398 
00399     public:             
00400       // Insert and erase
00401       _Insert_Return_Type
00402       insert(const value_type& __v) 
00403       { return _M_insert(__v, std::integral_constant<bool,
00404              __unique_keys>()); }
00405 
00406       iterator
00407       insert(const_iterator, const value_type& __v)
00408       { return iterator(_Insert_Conv_Type()(this->insert(__v))); }
00409 
00410       template<typename _InputIterator>
00411         void
00412         insert(_InputIterator __first, _InputIterator __last);
00413 
00414       void
00415       insert(initializer_list<value_type> __l)
00416       { this->insert(__l.begin(), __l.end()); }
00417 
00418       iterator
00419       erase(const_iterator);
00420 
00421       size_type
00422       erase(const key_type&);
00423 
00424       iterator
00425       erase(const_iterator, const_iterator);
00426 
00427       void
00428       clear();
00429 
00430       // Set number of buckets to be appropriate for container of n element.
00431       void rehash(size_type __n);
00432 
00433       // DR 1189.
00434       // reserve, if present, comes from _Rehash_base.
00435 
00436     private:
00437       // Unconditionally change size of bucket array to n.
00438       void _M_rehash(size_type __n);
00439     };
00440 
00441 
00442   // Definitions of class template _Hashtable's out-of-line member functions.
00443   template<typename _Key, typename _Value, 
00444        typename _Allocator, typename _ExtractKey, typename _Equal,
00445        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00446        bool __chc, bool __cit, bool __uk>
00447     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00448             _H1, _H2, _Hash, _RehashPolicy,
00449             __chc, __cit, __uk>::_Node*
00450     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00451            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00452     _M_allocate_node(const value_type& __v)
00453     {
00454       _Node* __n = _M_node_allocator.allocate(1);
00455       __try
00456     {
00457       _M_node_allocator.construct(__n, __v);
00458       __n->_M_next = 0;
00459       return __n;
00460     }
00461       __catch(...)
00462     {
00463       _M_node_allocator.deallocate(__n, 1);
00464       __throw_exception_again;
00465     }
00466     }
00467 
00468   template<typename _Key, typename _Value, 
00469        typename _Allocator, typename _ExtractKey, typename _Equal,
00470        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00471        bool __chc, bool __cit, bool __uk>
00472     void
00473     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00474            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00475     _M_deallocate_node(_Node* __n)
00476     {
00477       _M_node_allocator.destroy(__n);
00478       _M_node_allocator.deallocate(__n, 1);
00479     }
00480 
00481   template<typename _Key, typename _Value, 
00482        typename _Allocator, typename _ExtractKey, typename _Equal,
00483        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00484        bool __chc, bool __cit, bool __uk>
00485     void
00486     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00487            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00488     _M_deallocate_nodes(_Node** __array, size_type __n)
00489     {
00490       for (size_type __i = 0; __i < __n; ++__i)
00491     {
00492       _Node* __p = __array[__i];
00493       while (__p)
00494         {
00495           _Node* __tmp = __p;
00496           __p = __p->_M_next;
00497           _M_deallocate_node(__tmp);
00498         }
00499       __array[__i] = 0;
00500     }
00501     }
00502 
00503   template<typename _Key, typename _Value, 
00504        typename _Allocator, typename _ExtractKey, typename _Equal,
00505        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00506        bool __chc, bool __cit, bool __uk>
00507     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00508             _H1, _H2, _Hash, _RehashPolicy,
00509             __chc, __cit, __uk>::_Node**
00510     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00511            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00512     _M_allocate_buckets(size_type __n)
00513     {
00514       _Bucket_allocator_type __alloc(_M_node_allocator);
00515 
00516       // We allocate one extra bucket to hold a sentinel, an arbitrary
00517       // non-null pointer.  Iterator increment relies on this.
00518       _Node** __p = __alloc.allocate(__n + 1);
00519       std::fill(__p, __p + __n, (_Node*) 0);
00520       __p[__n] = reinterpret_cast<_Node*>(0x1000);
00521       return __p;
00522     }
00523 
00524   template<typename _Key, typename _Value, 
00525        typename _Allocator, typename _ExtractKey, typename _Equal,
00526        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00527        bool __chc, bool __cit, bool __uk>
00528     void
00529     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00530            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00531     _M_deallocate_buckets(_Node** __p, size_type __n)
00532     {
00533       _Bucket_allocator_type __alloc(_M_node_allocator);
00534       __alloc.deallocate(__p, __n + 1);
00535     }
00536 
00537   template<typename _Key, typename _Value, 
00538        typename _Allocator, typename _ExtractKey, typename _Equal,
00539        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00540        bool __chc, bool __cit, bool __uk>
00541     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00542            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00543     _Hashtable(size_type __bucket_hint,
00544            const _H1& __h1, const _H2& __h2, const _Hash& __h,
00545            const _Equal& __eq, const _ExtractKey& __exk,
00546            const allocator_type& __a)
00547     : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(),
00548       __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
00549                 _H1, _H2, _Hash, __chc>(__exk, __eq,
00550                             __h1, __h2, __h),
00551       __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(),
00552       _M_node_allocator(__a),
00553       _M_bucket_count(0),
00554       _M_element_count(0),
00555       _M_rehash_policy()
00556     {
00557       _M_bucket_count = _M_rehash_policy._M_next_bkt(__bucket_hint);
00558       _M_buckets = _M_allocate_buckets(_M_bucket_count);
00559     }
00560 
00561   template<typename _Key, typename _Value, 
00562        typename _Allocator, typename _ExtractKey, typename _Equal,
00563        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00564        bool __chc, bool __cit, bool __uk>
00565     template<typename _InputIterator>
00566       _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00567          _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00568       _Hashtable(_InputIterator __f, _InputIterator __l,
00569          size_type __bucket_hint,
00570          const _H1& __h1, const _H2& __h2, const _Hash& __h,
00571          const _Equal& __eq, const _ExtractKey& __exk,
00572          const allocator_type& __a)
00573       : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(),
00574     __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
00575                   _H1, _H2, _Hash, __chc>(__exk, __eq,
00576                               __h1, __h2, __h),
00577     __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(),
00578     _M_node_allocator(__a),
00579     _M_bucket_count(0),
00580     _M_element_count(0),
00581     _M_rehash_policy()
00582       {
00583     _M_bucket_count = std::max(_M_rehash_policy._M_next_bkt(__bucket_hint),
00584                    _M_rehash_policy.
00585                    _M_bkt_for_elements(__detail::
00586                                __distance_fw(__f,
00587                                      __l)));
00588     _M_buckets = _M_allocate_buckets(_M_bucket_count);
00589     __try
00590       {
00591         for (; __f != __l; ++__f)
00592           this->insert(*__f);
00593       }
00594     __catch(...)
00595       {
00596         clear();
00597         _M_deallocate_buckets(_M_buckets, _M_bucket_count);
00598         __throw_exception_again;
00599       }
00600       }
00601   
00602   template<typename _Key, typename _Value, 
00603        typename _Allocator, typename _ExtractKey, typename _Equal,
00604        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00605        bool __chc, bool __cit, bool __uk>
00606     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00607            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00608     _Hashtable(const _Hashtable& __ht)
00609     : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(__ht),
00610       __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
00611                 _H1, _H2, _Hash, __chc>(__ht),
00612       __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(__ht),
00613       _M_node_allocator(__ht._M_node_allocator),
00614       _M_bucket_count(__ht._M_bucket_count),
00615       _M_element_count(__ht._M_element_count),
00616       _M_rehash_policy(__ht._M_rehash_policy)
00617     {
00618       _M_buckets = _M_allocate_buckets(_M_bucket_count);
00619       __try
00620     {
00621       for (size_type __i = 0; __i < __ht._M_bucket_count; ++__i)
00622         {
00623           _Node* __n = __ht._M_buckets[__i];
00624           _Node** __tail = _M_buckets + __i;
00625           while (__n)
00626         {
00627           *__tail = _M_allocate_node(__n->_M_v);
00628           this->_M_copy_code(*__tail, __n);
00629           __tail = &((*__tail)->_M_next);
00630           __n = __n->_M_next;
00631         }
00632         }
00633     }
00634       __catch(...)
00635     {
00636       clear();
00637       _M_deallocate_buckets(_M_buckets, _M_bucket_count);
00638       __throw_exception_again;
00639     }
00640     }
00641 
00642   template<typename _Key, typename _Value, 
00643        typename _Allocator, typename _ExtractKey, typename _Equal,
00644        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00645        bool __chc, bool __cit, bool __uk>
00646     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00647            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00648     _Hashtable(_Hashtable&& __ht)
00649     : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(__ht),
00650       __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
00651                 _H1, _H2, _Hash, __chc>(__ht),
00652       __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(__ht),
00653       _M_node_allocator(__ht._M_node_allocator),
00654       _M_bucket_count(__ht._M_bucket_count),
00655       _M_element_count(__ht._M_element_count),
00656       _M_rehash_policy(__ht._M_rehash_policy),
00657       _M_buckets(__ht._M_buckets)
00658     {
00659       size_type __n_bkt = __ht._M_rehash_policy._M_next_bkt(0);
00660       __ht._M_buckets = __ht._M_allocate_buckets(__n_bkt);
00661       __ht._M_bucket_count = __n_bkt;
00662       __ht._M_element_count = 0;
00663       __ht._M_rehash_policy = _RehashPolicy();
00664     }
00665 
00666   template<typename _Key, typename _Value, 
00667        typename _Allocator, typename _ExtractKey, typename _Equal,
00668        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00669        bool __chc, bool __cit, bool __uk>
00670     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00671            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>&
00672     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00673            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00674     operator=(const _Hashtable& __ht)
00675     {
00676       _Hashtable __tmp(__ht);
00677       this->swap(__tmp);
00678       return *this;
00679     }
00680 
00681   template<typename _Key, typename _Value, 
00682        typename _Allocator, typename _ExtractKey, typename _Equal,
00683        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00684        bool __chc, bool __cit, bool __uk>
00685     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00686            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00687     ~_Hashtable()
00688     {
00689       clear();
00690       _M_deallocate_buckets(_M_buckets, _M_bucket_count);
00691     }
00692 
00693   template<typename _Key, typename _Value, 
00694        typename _Allocator, typename _ExtractKey, typename _Equal,
00695        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00696        bool __chc, bool __cit, bool __uk>
00697     void
00698     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00699            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00700     swap(_Hashtable& __x)
00701     {
00702       // The only base class with member variables is hash_code_base.  We
00703       // define _Hash_code_base::_M_swap because different specializations
00704       // have different members.
00705       __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
00706     _H1, _H2, _Hash, __chc>::_M_swap(__x);
00707 
00708       // _GLIBCXX_RESOLVE_LIB_DEFECTS
00709       // 431. Swapping containers with unequal allocators.
00710       std::__alloc_swap<_Node_allocator_type>::_S_do_it(_M_node_allocator,
00711                             __x._M_node_allocator);
00712 
00713       std::swap(_M_rehash_policy, __x._M_rehash_policy);
00714       std::swap(_M_buckets, __x._M_buckets);
00715       std::swap(_M_bucket_count, __x._M_bucket_count);
00716       std::swap(_M_element_count, __x._M_element_count);
00717     }
00718 
00719   template<typename _Key, typename _Value, 
00720        typename _Allocator, typename _ExtractKey, typename _Equal,
00721        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00722        bool __chc, bool __cit, bool __uk>
00723     void
00724     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00725            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00726     __rehash_policy(const _RehashPolicy& __pol)
00727     {
00728       _M_rehash_policy = __pol;
00729       size_type __n_bkt = __pol._M_bkt_for_elements(_M_element_count);
00730       if (__n_bkt > _M_bucket_count)
00731     _M_rehash(__n_bkt);
00732     }
00733 
00734   template<typename _Key, typename _Value, 
00735        typename _Allocator, typename _ExtractKey, typename _Equal,
00736        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00737        bool __chc, bool __cit, bool __uk>
00738     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00739             _H1, _H2, _Hash, _RehashPolicy,
00740             __chc, __cit, __uk>::iterator
00741     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00742            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00743     find(const key_type& __k)
00744     {
00745       typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
00746       std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
00747       _Node* __p = _M_find_node(_M_buckets[__n], __k, __code);
00748       return __p ? iterator(__p, _M_buckets + __n) : this->end();
00749     }
00750 
00751   template<typename _Key, typename _Value, 
00752        typename _Allocator, typename _ExtractKey, typename _Equal,
00753        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00754        bool __chc, bool __cit, bool __uk>
00755     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00756             _H1, _H2, _Hash, _RehashPolicy,
00757             __chc, __cit, __uk>::const_iterator
00758     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00759            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00760     find(const key_type& __k) const
00761     {
00762       typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
00763       std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
00764       _Node* __p = _M_find_node(_M_buckets[__n], __k, __code);
00765       return __p ? const_iterator(__p, _M_buckets + __n) : this->end();
00766     }
00767 
00768   template<typename _Key, typename _Value, 
00769        typename _Allocator, typename _ExtractKey, typename _Equal,
00770        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00771        bool __chc, bool __cit, bool __uk>
00772     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00773             _H1, _H2, _Hash, _RehashPolicy,
00774             __chc, __cit, __uk>::size_type
00775     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00776            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00777     count(const key_type& __k) const
00778     {
00779       typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
00780       std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
00781       std::size_t __result = 0;
00782       for (_Node* __p = _M_buckets[__n]; __p; __p = __p->_M_next)
00783     if (this->_M_compare(__k, __code, __p))
00784       ++__result;
00785       return __result;
00786     }
00787 
00788   template<typename _Key, typename _Value, 
00789        typename _Allocator, typename _ExtractKey, typename _Equal,
00790        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00791        bool __chc, bool __cit, bool __uk>
00792     std::pair<typename _Hashtable<_Key, _Value, _Allocator,
00793                   _ExtractKey, _Equal, _H1,
00794                   _H2, _Hash, _RehashPolicy,
00795                   __chc, __cit, __uk>::iterator,
00796           typename _Hashtable<_Key, _Value, _Allocator,
00797                   _ExtractKey, _Equal, _H1,
00798                   _H2, _Hash, _RehashPolicy,
00799                   __chc, __cit, __uk>::iterator>
00800     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00801            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00802     equal_range(const key_type& __k)
00803     {
00804       typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
00805       std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
00806       _Node** __head = _M_buckets + __n;
00807       _Node* __p = _M_find_node(*__head, __k, __code);
00808       
00809       if (__p)
00810     {
00811       _Node* __p1 = __p->_M_next;
00812       for (; __p1; __p1 = __p1->_M_next)
00813         if (!this->_M_compare(__k, __code, __p1))
00814           break;
00815 
00816       iterator __first(__p, __head);
00817       iterator __last(__p1, __head);
00818       if (!__p1)
00819         __last._M_incr_bucket();
00820       return std::make_pair(__first, __last);
00821     }
00822       else
00823     return std::make_pair(this->end(), this->end());
00824     }
00825 
00826   template<typename _Key, typename _Value, 
00827        typename _Allocator, typename _ExtractKey, typename _Equal,
00828        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00829        bool __chc, bool __cit, bool __uk>
00830     std::pair<typename _Hashtable<_Key, _Value, _Allocator,
00831                   _ExtractKey, _Equal, _H1,
00832                   _H2, _Hash, _RehashPolicy,
00833                   __chc, __cit, __uk>::const_iterator,
00834           typename _Hashtable<_Key, _Value, _Allocator,
00835                   _ExtractKey, _Equal, _H1,
00836                   _H2, _Hash, _RehashPolicy,
00837                   __chc, __cit, __uk>::const_iterator>
00838     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00839            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00840     equal_range(const key_type& __k) const
00841     {
00842       typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
00843       std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
00844       _Node** __head = _M_buckets + __n;
00845       _Node* __p = _M_find_node(*__head, __k, __code);
00846 
00847       if (__p)
00848     {
00849       _Node* __p1 = __p->_M_next;
00850       for (; __p1; __p1 = __p1->_M_next)
00851         if (!this->_M_compare(__k, __code, __p1))
00852           break;
00853 
00854       const_iterator __first(__p, __head);
00855       const_iterator __last(__p1, __head);
00856       if (!__p1)
00857         __last._M_incr_bucket();
00858       return std::make_pair(__first, __last);
00859     }
00860       else
00861     return std::make_pair(this->end(), this->end());
00862     }
00863 
00864   // Find the node whose key compares equal to k, beginning the search
00865   // at p (usually the head of a bucket).  Return nil if no node is found.
00866   template<typename _Key, typename _Value, 
00867        typename _Allocator, typename _ExtractKey, typename _Equal,
00868        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00869        bool __chc, bool __cit, bool __uk>
00870     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey,
00871             _Equal, _H1, _H2, _Hash, _RehashPolicy,
00872             __chc, __cit, __uk>::_Node* 
00873     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00874            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00875     _M_find_node(_Node* __p, const key_type& __k,
00876         typename _Hashtable::_Hash_code_type __code) const
00877     {
00878       for (; __p; __p = __p->_M_next)
00879     if (this->_M_compare(__k, __code, __p))
00880       return __p;
00881       return false;
00882     }
00883 
00884   // Insert v in bucket n (assumes no element with its key already present).
00885   template<typename _Key, typename _Value, 
00886        typename _Allocator, typename _ExtractKey, typename _Equal,
00887        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00888        bool __chc, bool __cit, bool __uk>
00889     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00890             _H1, _H2, _Hash, _RehashPolicy,
00891             __chc, __cit, __uk>::iterator
00892     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00893            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00894     _M_insert_bucket(const value_type& __v, size_type __n,
00895              typename _Hashtable::_Hash_code_type __code)
00896     {
00897       std::pair<bool, std::size_t> __do_rehash
00898     = _M_rehash_policy._M_need_rehash(_M_bucket_count,
00899                       _M_element_count, 1);
00900 
00901       // Allocate the new node before doing the rehash so that we don't
00902       // do a rehash if the allocation throws.
00903       _Node* __new_node = _M_allocate_node(__v);
00904 
00905       __try
00906     {
00907       if (__do_rehash.first)
00908         {
00909           const key_type& __k = this->_M_extract(__v);
00910           __n = this->_M_bucket_index(__k, __code, __do_rehash.second);
00911           _M_rehash(__do_rehash.second);
00912         }
00913 
00914       __new_node->_M_next = _M_buckets[__n];
00915       this->_M_store_code(__new_node, __code);
00916       _M_buckets[__n] = __new_node;
00917       ++_M_element_count;
00918       return iterator(__new_node, _M_buckets + __n);
00919     }
00920       __catch(...)
00921     {
00922       _M_deallocate_node(__new_node);
00923       __throw_exception_again;
00924     }
00925     }
00926 
00927   // Insert v if no element with its key is already present.
00928   template<typename _Key, typename _Value, 
00929        typename _Allocator, typename _ExtractKey, typename _Equal,
00930        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00931        bool __chc, bool __cit, bool __uk>
00932     std::pair<typename _Hashtable<_Key, _Value, _Allocator,
00933                   _ExtractKey, _Equal, _H1,
00934                   _H2, _Hash, _RehashPolicy,
00935                   __chc, __cit, __uk>::iterator, bool>
00936     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00937            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00938     _M_insert(const value_type& __v, std::true_type)
00939     {
00940       const key_type& __k = this->_M_extract(__v);
00941       typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
00942       size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
00943 
00944       if (_Node* __p = _M_find_node(_M_buckets[__n], __k, __code))
00945     return std::make_pair(iterator(__p, _M_buckets + __n), false);
00946       return std::make_pair(_M_insert_bucket(__v, __n, __code), true);
00947     }
00948 
00949   // Insert v unconditionally.
00950   template<typename _Key, typename _Value, 
00951        typename _Allocator, typename _ExtractKey, typename _Equal,
00952        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00953        bool __chc, bool __cit, bool __uk>
00954     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00955             _H1, _H2, _Hash, _RehashPolicy,
00956             __chc, __cit, __uk>::iterator
00957     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00958            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00959     _M_insert(const value_type& __v, std::false_type)
00960     {
00961       std::pair<bool, std::size_t> __do_rehash
00962     = _M_rehash_policy._M_need_rehash(_M_bucket_count,
00963                       _M_element_count, 1);
00964       if (__do_rehash.first)
00965     _M_rehash(__do_rehash.second);
00966  
00967       const key_type& __k = this->_M_extract(__v);
00968       typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
00969       size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
00970 
00971       // First find the node, avoid leaking new_node if compare throws.
00972       _Node* __prev = _M_find_node(_M_buckets[__n], __k, __code);
00973       _Node* __new_node = _M_allocate_node(__v);
00974 
00975       if (__prev)
00976     {
00977       __new_node->_M_next = __prev->_M_next;
00978       __prev->_M_next = __new_node;
00979     }
00980       else
00981     {
00982       __new_node->_M_next = _M_buckets[__n];
00983       _M_buckets[__n] = __new_node;
00984     }
00985       this->_M_store_code(__new_node, __code);
00986 
00987       ++_M_element_count;
00988       return iterator(__new_node, _M_buckets + __n);
00989     }
00990 
00991   // For erase(iterator) and erase(const_iterator).
00992   template<typename _Key, typename _Value, 
00993        typename _Allocator, typename _ExtractKey, typename _Equal,
00994        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00995        bool __chc, bool __cit, bool __uk>
00996     void
00997     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00998            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00999     _M_erase_node(_Node* __p, _Node** __b)
01000     {
01001       _Node* __cur = *__b;
01002       if (__cur == __p)
01003     *__b = __cur->_M_next;
01004       else
01005     {
01006       _Node* __next = __cur->_M_next;
01007       while (__next != __p)
01008         {
01009           __cur = __next;
01010           __next = __cur->_M_next;
01011         }
01012       __cur->_M_next = __next->_M_next;
01013     }
01014 
01015       _M_deallocate_node(__p);
01016       --_M_element_count;
01017     }
01018 
01019   template<typename _Key, typename _Value, 
01020        typename _Allocator, typename _ExtractKey, typename _Equal,
01021        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
01022        bool __chc, bool __cit, bool __uk>
01023     template<typename _InputIterator>
01024       void 
01025       _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01026          _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
01027       insert(_InputIterator __first, _InputIterator __last)
01028       {
01029     size_type __n_elt = __detail::__distance_fw(__first, __last);
01030     std::pair<bool, std::size_t> __do_rehash
01031       = _M_rehash_policy._M_need_rehash(_M_bucket_count,
01032                         _M_element_count, __n_elt);
01033     if (__do_rehash.first)
01034       _M_rehash(__do_rehash.second);
01035 
01036     for (; __first != __last; ++__first)
01037       this->insert(*__first);
01038       }
01039 
01040   template<typename _Key, typename _Value, 
01041        typename _Allocator, typename _ExtractKey, typename _Equal,
01042        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
01043        bool __chc, bool __cit, bool __uk>
01044     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01045             _H1, _H2, _Hash, _RehashPolicy,
01046             __chc, __cit, __uk>::iterator
01047     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01048            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
01049     erase(const_iterator __it)
01050     {
01051       iterator __result(__it._M_cur_node, __it._M_cur_bucket);
01052       ++__result;
01053       _M_erase_node(__it._M_cur_node, __it._M_cur_bucket);
01054       return __result;
01055     }
01056 
01057   template<typename _Key, typename _Value, 
01058        typename _Allocator, typename _ExtractKey, typename _Equal,
01059        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
01060        bool __chc, bool __cit, bool __uk>
01061     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01062             _H1, _H2, _Hash, _RehashPolicy,
01063             __chc, __cit, __uk>::size_type
01064     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01065            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
01066     erase(const key_type& __k)
01067     {
01068       typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
01069       std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
01070       size_type __result = 0;
01071       
01072       _Node** __slot = _M_buckets + __n;
01073       while (*__slot && !this->_M_compare(__k, __code, *__slot))
01074     __slot = &((*__slot)->_M_next);
01075 
01076       _Node** __saved_slot = 0;
01077       while (*__slot && this->_M_compare(__k, __code, *__slot))
01078     {
01079       // _GLIBCXX_RESOLVE_LIB_DEFECTS
01080       // 526. Is it undefined if a function in the standard changes
01081       // in parameters?
01082       if (&this->_M_extract((*__slot)->_M_v) != &__k)
01083         {
01084               _Node* __p = *__slot;
01085               *__slot = __p->_M_next;
01086           _M_deallocate_node(__p);
01087           --_M_element_count;
01088           ++__result;
01089         }
01090       else
01091         {
01092           __saved_slot = __slot;
01093           __slot = &((*__slot)->_M_next);
01094         }
01095     }
01096 
01097       if (__saved_slot)
01098     {
01099       _Node* __p = *__saved_slot;
01100       *__saved_slot = __p->_M_next;
01101       _M_deallocate_node(__p);
01102       --_M_element_count;
01103       ++__result;
01104     }
01105 
01106       return __result;
01107     }
01108 
01109   // ??? This could be optimized by taking advantage of the bucket
01110   // structure, but it's not clear that it's worth doing.  It probably
01111   // wouldn't even be an optimization unless the load factor is large.
01112   template<typename _Key, typename _Value, 
01113        typename _Allocator, typename _ExtractKey, typename _Equal,
01114        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
01115        bool __chc, bool __cit, bool __uk>
01116     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01117             _H1, _H2, _Hash, _RehashPolicy,
01118             __chc, __cit, __uk>::iterator
01119     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01120            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
01121     erase(const_iterator __first, const_iterator __last)
01122     {
01123       while (__first != __last)
01124     __first = this->erase(__first);
01125       return iterator(__last._M_cur_node, __last._M_cur_bucket);
01126     }
01127 
01128   template<typename _Key, typename _Value, 
01129        typename _Allocator, typename _ExtractKey, typename _Equal,
01130        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
01131        bool __chc, bool __cit, bool __uk>
01132     void
01133     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01134            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
01135     clear()
01136     {
01137       _M_deallocate_nodes(_M_buckets, _M_bucket_count);
01138       _M_element_count = 0;
01139     }
01140  
01141   template<typename _Key, typename _Value, 
01142        typename _Allocator, typename _ExtractKey, typename _Equal,
01143        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
01144        bool __chc, bool __cit, bool __uk>
01145     void
01146     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01147            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
01148     rehash(size_type __n)
01149     {
01150       _M_rehash(std::max(_M_rehash_policy._M_next_bkt(__n),
01151              _M_rehash_policy._M_bkt_for_elements(_M_element_count
01152                                   + 1)));
01153     }
01154 
01155   template<typename _Key, typename _Value, 
01156        typename _Allocator, typename _ExtractKey, typename _Equal,
01157        typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
01158        bool __chc, bool __cit, bool __uk>
01159     void
01160     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01161            _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
01162     _M_rehash(size_type __n)
01163     {
01164       _Node** __new_array = _M_allocate_buckets(__n);
01165       __try
01166     {
01167       for (size_type __i = 0; __i < _M_bucket_count; ++__i)
01168         while (_Node* __p = _M_buckets[__i])
01169           {
01170         std::size_t __new_index = this->_M_bucket_index(__p, __n);
01171         _M_buckets[__i] = __p->_M_next;
01172         __p->_M_next = __new_array[__new_index];
01173         __new_array[__new_index] = __p;
01174           }
01175       _M_deallocate_buckets(_M_buckets, _M_bucket_count);
01176       _M_bucket_count = __n;
01177       _M_buckets = __new_array;
01178     }
01179       __catch(...)
01180     {
01181       // A failure here means that a hash function threw an exception.
01182       // We can't restore the previous state without calling the hash
01183       // function again, so the only sensible recovery is to delete
01184       // everything.
01185       _M_deallocate_nodes(__new_array, __n);
01186       _M_deallocate_buckets(__new_array, __n);
01187       _M_deallocate_nodes(_M_buckets, _M_bucket_count);
01188       _M_element_count = 0;
01189       __throw_exception_again;
01190     }
01191     }
01192 }
01193 
01194 #endif // _HASHTABLE_H