OSDN Git Service

2007-10-17 Paolo Carlini <pcarlini@suse.de>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / tr1_impl / hashtable
1 // Internal header for TR1 unordered_set and unordered_map -*- C++ -*-
2
3 // Copyright (C) 2007 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
9 // any later version.
10
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING.  If not, write to the Free
18 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
19 // USA.
20
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction.  Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License.  This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
29
30 /** @file tr1_impl/hashtable
31  *  This is an internal header file, included by other library headers.
32  *  You should not attempt to use it directly.
33  */
34
35 // This header file defines std::tr1::hashtable, which is used to
36 // implement std::tr1::unordered_set, std::tr1::unordered_map, 
37 // std::tr1::unordered_multiset, and std::tr1::unordered_multimap.
38 // hashtable has many template parameters, partly to accommodate
39 // the differences between those four classes and partly to 
40 // accommodate policy choices that go beyond TR1 specifications.
41
42 // Class template hashtable attempts to encapsulate all reasonable
43 // variation among hash tables that use chaining.  It does not handle
44 // open addressing.
45
46 // References: 
47 // M. Austern, "A Proposal to Add Hash Tables to the Standard
48 //    Library (revision 4)," WG21 Document N1456=03-0039, 2003.
49 // D. E. Knuth, The Art of Computer Programming, v. 3, Sorting and Searching.
50 // A. Tavori and V. Dreizin, "Policy-Based Data Structures", 2004.
51 // http://gcc.gnu.org/onlinedocs/libstdc++/ext/pb_ds/index.html
52
53 #include <tr1_impl/hashtable_policy.h>
54
55 namespace std
56
57 _GLIBCXX_BEGIN_NAMESPACE_TR1
58
59   // Class template _Hashtable, class definition.
60   
61   // Meaning of class template _Hashtable's template parameters
62   
63   // _Key and _Value: arbitrary CopyConstructible types.
64   
65   // _Allocator: an allocator type ([lib.allocator.requirements]) whose
66   // value type is Value.  As a conforming extension, we allow for
67   // value type != Value.
68
69   // _ExtractKey: function object that takes a object of type Value
70   // and returns a value of type _Key.
71   
72   // _Equal: function object that takes two objects of type k and returns
73   // a bool-like value that is true if the two objects are considered equal.
74   
75   // _H1: the hash function.  A unary function object with argument type
76   // Key and result type size_t.  Return values should be distributed
77   // over the entire range [0, numeric_limits<size_t>:::max()].
78   
79   // _H2: the range-hashing function (in the terminology of Tavori and
80   // Dreizin).  A binary function object whose argument types and result
81   // type are all size_t.  Given arguments r and N, the return value is
82   // in the range [0, N).
83   
84   // _Hash: the ranged hash function (Tavori and Dreizin). A binary function
85   // whose argument types are _Key and size_t and whose result type is
86   // size_t.  Given arguments k and N, the return value is in the range
87   // [0, N).  Default: hash(k, N) = h2(h1(k), N).  If _Hash is anything other
88   // than the default, _H1 and _H2 are ignored.
89   
90   // _RehashPolicy: Policy class with three members, all of which govern
91   // the bucket count. _M_next_bkt(n) returns a bucket count no smaller
92   // than n.  _M_bkt_for_elements(n) returns a bucket count appropriate
93   // for an element count of n.  _M_need_rehash(n_bkt, n_elt, n_ins)
94   // determines whether, if the current bucket count is n_bkt and the
95   // current element count is n_elt, we need to increase the bucket
96   // count.  If so, returns make_pair(true, n), where n is the new
97   // bucket count.  If not, returns make_pair(false, <anything>).
98   
99   // ??? Right now it is hard-wired that the number of buckets never
100   // shrinks.  Should we allow _RehashPolicy to change that?
101   
102   // __cache_hash_code: bool.  true if we store the value of the hash
103   // function along with the value.  This is a time-space tradeoff.
104   // Storing it may improve lookup speed by reducing the number of times
105   // we need to call the Equal function.
106   
107   // __constant_iterators: bool.  true if iterator and const_iterator are
108   // both constant iterator types.  This is true for unordered_set and
109   // unordered_multiset, false for unordered_map and unordered_multimap.
110   
111   // __unique_keys: bool.  true if the return value of _Hashtable::count(k)
112   // is always at most one, false if it may be an arbitrary number.  This
113   // true for unordered_set and unordered_map, false for unordered_multiset
114   // and unordered_multimap.
115   
116   template<typename _Key, typename _Value, typename _Allocator,
117            typename _ExtractKey, typename _Equal,
118            typename _H1, typename _H2, typename _Hash, 
119            typename _RehashPolicy,
120            bool __cache_hash_code,
121            bool __constant_iterators,
122            bool __unique_keys>
123     class _Hashtable
124     : public __detail::_Rehash_base<_RehashPolicy,
125                                     _Hashtable<_Key, _Value, _Allocator,
126                                                _ExtractKey,
127                                                _Equal, _H1, _H2, _Hash,
128                                                _RehashPolicy,
129                                                __cache_hash_code,
130                                                __constant_iterators,
131                                                __unique_keys> >,
132       public __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
133                                        _H1, _H2, _Hash, __cache_hash_code>,
134       public __detail::_Map_base<_Key, _Value, _ExtractKey, __unique_keys,
135                                  _Hashtable<_Key, _Value, _Allocator,
136                                             _ExtractKey,
137                                             _Equal, _H1, _H2, _Hash,
138                                             _RehashPolicy,
139                                             __cache_hash_code,
140                                             __constant_iterators,
141                                             __unique_keys> >
142     {
143     public:
144       typedef _Allocator                                  allocator_type;
145       typedef _Value                                      value_type;
146       typedef _Key                                        key_type;
147       typedef _Equal                                      key_equal;
148       // mapped_type, if present, comes from _Map_base.
149       // hasher, if present, comes from _Hash_code_base.
150       typedef typename _Allocator::difference_type        difference_type;
151       typedef typename _Allocator::size_type              size_type;
152       typedef typename _Allocator::reference              reference;
153       typedef typename _Allocator::const_reference        const_reference;
154       
155       typedef __detail::_Node_iterator<value_type, __constant_iterators,
156                                        __cache_hash_code>
157                                                           local_iterator;
158       typedef __detail::_Node_const_iterator<value_type,
159                                              __constant_iterators,
160                                              __cache_hash_code>
161                                                           const_local_iterator;
162
163       typedef __detail::_Hashtable_iterator<value_type, __constant_iterators,
164                                             __cache_hash_code>
165                                                           iterator;
166       typedef __detail::_Hashtable_const_iterator<value_type,
167                                                   __constant_iterators,
168                                                   __cache_hash_code>
169                                                           const_iterator;
170
171       template<typename _Key2, typename _Pair, typename _Hashtable>
172         friend struct __detail::_Map_base;
173
174     private:
175       typedef __detail::_Hash_node<_Value, __cache_hash_code> _Node;
176       typedef typename _Allocator::template rebind<_Node>::other
177                                                         _Node_allocator_type;
178       typedef typename _Allocator::template rebind<_Node*>::other
179                                                         _Bucket_allocator_type;
180
181       typedef typename _Allocator::template rebind<_Value>::other
182                                                         _Value_allocator_type;
183
184       _Node_allocator_type   _M_node_allocator;
185       _Node**                _M_buckets;
186       size_type              _M_bucket_count;
187       size_type              _M_element_count;
188       _RehashPolicy          _M_rehash_policy;
189       
190       _Node*
191       _M_allocate_node(const value_type& __v);
192   
193       void
194       _M_deallocate_node(_Node* __n);
195   
196       void
197       _M_deallocate_nodes(_Node**, size_type);
198
199       _Node**
200       _M_allocate_buckets(size_type __n);
201   
202       void
203       _M_deallocate_buckets(_Node**, size_type __n);
204
205     public:                         
206       // Constructor, destructor, assignment, swap
207       _Hashtable(size_type __bucket_hint,
208                  const _H1&, const _H2&, const _Hash&,
209                  const _Equal&, const _ExtractKey&,
210                  const allocator_type&);
211   
212       template<typename _InputIterator>
213         _Hashtable(_InputIterator __first, _InputIterator __last,
214                    size_type __bucket_hint,
215                    const _H1&, const _H2&, const _Hash&, 
216                    const _Equal&, const _ExtractKey&,
217                    const allocator_type&);
218   
219       _Hashtable(const _Hashtable&);
220       
221       _Hashtable&
222       operator=(const _Hashtable&);
223   
224       ~_Hashtable();
225
226       void swap(_Hashtable&);
227
228       // Basic container operations
229       iterator
230       begin()
231       {
232         iterator __i(_M_buckets);
233         if (!__i._M_cur_node)
234           __i._M_incr_bucket();
235         return __i;
236       }
237
238       const_iterator
239       begin() const
240       {
241         const_iterator __i(_M_buckets);
242         if (!__i._M_cur_node)
243           __i._M_incr_bucket();
244         return __i;
245       }
246
247       iterator
248       end()
249       { return iterator(_M_buckets + _M_bucket_count); }
250
251       const_iterator
252       end() const
253       { return const_iterator(_M_buckets + _M_bucket_count); }
254
255 #ifdef _GLIBCXX_INCLUDE_AS_CXX0X
256       const_iterator
257       cbegin() const
258       {
259         const_iterator __i(_M_buckets);
260         if (!__i._M_cur_node)
261           __i._M_incr_bucket();
262         return __i;
263       }
264
265       const_iterator
266       cend() const
267       { return const_iterator(_M_buckets + _M_bucket_count); }
268 #endif
269
270       size_type
271       size() const
272       { return _M_element_count; }
273   
274       bool
275       empty() const
276       { return size() == 0; }
277
278       allocator_type
279       get_allocator() const
280       { return allocator_type(_M_node_allocator); }
281
282       _Value_allocator_type
283       _M_get_Value_allocator() const
284       { return _Value_allocator_type(_M_node_allocator); }
285
286       size_type
287       max_size() const
288       { return _M_get_Value_allocator().max_size(); }
289
290       // Observers
291       key_equal
292       key_eq() const
293       { return this->_M_eq; }
294
295       // hash_function, if present, comes from _Hash_code_base.
296
297       // Bucket operations
298       size_type
299       bucket_count() const
300       { return _M_bucket_count; }
301   
302       size_type
303       max_bucket_count() const
304       { return max_size(); }
305   
306       size_type
307       bucket_size(size_type __n) const
308       { return std::distance(begin(__n), end(__n)); }
309   
310       size_type
311       bucket(const key_type& __k) const
312       { 
313         return this->_M_bucket_index(__k, this->_M_hash_code(__k),
314                                      bucket_count());
315       }
316
317       local_iterator
318       begin(size_type __n)
319       { return local_iterator(_M_buckets[__n]); }
320   
321       local_iterator
322       end(size_type)
323       { return local_iterator(0); }
324   
325       const_local_iterator
326       begin(size_type __n) const
327       { return const_local_iterator(_M_buckets[__n]); }
328   
329       const_local_iterator
330       end(size_type) const
331       { return const_local_iterator(0); }
332
333       float
334       load_factor() const
335       { 
336         return static_cast<float>(size()) / static_cast<float>(bucket_count());
337       }
338
339       // max_load_factor, if present, comes from _Rehash_base.
340
341       // Generalization of max_load_factor.  Extension, not found in TR1.  Only
342       // useful if _RehashPolicy is something other than the default.
343       const _RehashPolicy&
344       __rehash_policy() const
345       { return _M_rehash_policy; }
346       
347       void 
348       __rehash_policy(const _RehashPolicy&);
349
350       // Lookup.
351       iterator
352       find(const key_type& __k);
353
354       const_iterator
355       find(const key_type& __k) const;
356
357       size_type
358       count(const key_type& __k) const;
359
360       std::pair<iterator, iterator>
361       equal_range(const key_type& __k);
362
363       std::pair<const_iterator, const_iterator>
364       equal_range(const key_type& __k) const;
365
366     private:                    // Find, insert and erase helper functions
367       // ??? This dispatching is a workaround for the fact that we don't
368       // have partial specialization of member templates; it would be
369       // better to just specialize insert on __unique_keys.  There may be a
370       // cleaner workaround.
371       typedef typename __gnu_cxx::__conditional_type<__unique_keys,
372                             std::pair<iterator, bool>, iterator>::__type
373         _Insert_Return_Type;
374
375       typedef typename __gnu_cxx::__conditional_type<__unique_keys,
376                                           std::_Select1st<_Insert_Return_Type>,
377                                           std::_Identity<_Insert_Return_Type>
378                                    >::__type
379         _Insert_Conv_Type;
380
381       _Node*
382       _M_find_node(_Node*, const key_type&,
383                    typename _Hashtable::_Hash_code_type) const;
384
385       iterator
386       _M_insert_bucket(const value_type&, size_type,
387                        typename _Hashtable::_Hash_code_type);
388
389       std::pair<iterator, bool>
390       _M_insert(const value_type&, std::_GLIBCXX_TR1 true_type);
391
392       iterator
393       _M_insert(const value_type&, std::_GLIBCXX_TR1 false_type);
394
395       void
396       _M_erase_node(_Node*, _Node**);
397
398     public:                             
399       // Insert and erase
400       _Insert_Return_Type
401       insert(const value_type& __v) 
402       { return _M_insert(__v, std::_GLIBCXX_TR1 integral_constant<bool,
403                          __unique_keys>()); }
404
405       iterator
406       insert(iterator, const value_type& __v)
407       { return iterator(_Insert_Conv_Type()(this->insert(__v))); }
408
409       const_iterator
410       insert(const_iterator, const value_type& __v)
411       { return const_iterator(_Insert_Conv_Type()(this->insert(__v))); }
412
413       template<typename _InputIterator>
414         void
415         insert(_InputIterator __first, _InputIterator __last);
416
417       iterator
418       erase(iterator);
419
420       const_iterator
421       erase(const_iterator);
422
423       size_type
424       erase(const key_type&);
425
426       iterator
427       erase(iterator, iterator);
428
429       const_iterator
430       erase(const_iterator, const_iterator);
431
432       void
433       clear();
434
435       // Set number of buckets to be appropriate for container of n element.
436       void rehash(size_type __n);
437       
438     private:
439       // Unconditionally change size of bucket array to n.
440       void _M_rehash(size_type __n);
441     };
442
443
444   // Definitions of class template _Hashtable's out-of-line member functions.
445   template<typename _Key, typename _Value, 
446            typename _Allocator, typename _ExtractKey, typename _Equal,
447            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
448            bool __chc, bool __cit, bool __uk>
449     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
450                         _H1, _H2, _Hash, _RehashPolicy,
451                         __chc, __cit, __uk>::_Node*
452     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
453                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
454     _M_allocate_node(const value_type& __v)
455     {
456       _Node* __n = _M_node_allocator.allocate(1);
457       try
458         {
459           _M_get_Value_allocator().construct(&__n->_M_v, __v);
460           __n->_M_next = 0;
461           return __n;
462         }
463       catch(...)
464         {
465           _M_node_allocator.deallocate(__n, 1);
466           __throw_exception_again;
467         }
468     }
469
470   template<typename _Key, typename _Value, 
471            typename _Allocator, typename _ExtractKey, typename _Equal,
472            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
473            bool __chc, bool __cit, bool __uk>
474     void
475     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
476                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
477     _M_deallocate_node(_Node* __n)
478     {
479       _M_get_Value_allocator().destroy(&__n->_M_v);
480       _M_node_allocator.deallocate(__n, 1);
481     }
482
483   template<typename _Key, typename _Value, 
484            typename _Allocator, typename _ExtractKey, typename _Equal,
485            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
486            bool __chc, bool __cit, bool __uk>
487     void
488     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
489                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
490     _M_deallocate_nodes(_Node** __array, size_type __n)
491     {
492       for (size_type __i = 0; __i < __n; ++__i)
493         {
494           _Node* __p = __array[__i];
495           while (__p)
496             {
497               _Node* __tmp = __p;
498               __p = __p->_M_next;
499               _M_deallocate_node(__tmp);
500             }
501           __array[__i] = 0;
502         }
503     }
504
505   template<typename _Key, typename _Value, 
506            typename _Allocator, typename _ExtractKey, typename _Equal,
507            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
508            bool __chc, bool __cit, bool __uk>
509     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
510                         _H1, _H2, _Hash, _RehashPolicy,
511                         __chc, __cit, __uk>::_Node**
512     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
513                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
514     _M_allocate_buckets(size_type __n)
515     {
516       _Bucket_allocator_type __alloc(_M_node_allocator);
517
518       // We allocate one extra bucket to hold a sentinel, an arbitrary
519       // non-null pointer.  Iterator increment relies on this.
520       _Node** __p = __alloc.allocate(__n + 1);
521       std::fill(__p, __p + __n, (_Node*) 0);
522       __p[__n] = reinterpret_cast<_Node*>(0x1000);
523       return __p;
524     }
525
526   template<typename _Key, typename _Value, 
527            typename _Allocator, typename _ExtractKey, typename _Equal,
528            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
529            bool __chc, bool __cit, bool __uk>
530     void
531     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
532                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
533     _M_deallocate_buckets(_Node** __p, size_type __n)
534     {
535       _Bucket_allocator_type __alloc(_M_node_allocator);
536       __alloc.deallocate(__p, __n + 1);
537     }
538
539   template<typename _Key, typename _Value, 
540            typename _Allocator, typename _ExtractKey, typename _Equal,
541            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
542            bool __chc, bool __cit, bool __uk>
543     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
544                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
545     _Hashtable(size_type __bucket_hint,
546                const _H1& __h1, const _H2& __h2, const _Hash& __h,
547                const _Equal& __eq, const _ExtractKey& __exk,
548                const allocator_type& __a)
549     : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(),
550       __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
551                                 _H1, _H2, _Hash, __chc>(__exk, __eq,
552                                                         __h1, __h2, __h),
553       __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(),
554       _M_node_allocator(__a),
555       _M_bucket_count(0),
556       _M_element_count(0),
557       _M_rehash_policy()
558     {
559       _M_bucket_count = _M_rehash_policy._M_next_bkt(__bucket_hint);
560       _M_buckets = _M_allocate_buckets(_M_bucket_count);
561     }
562
563   template<typename _Key, typename _Value, 
564            typename _Allocator, typename _ExtractKey, typename _Equal,
565            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
566            bool __chc, bool __cit, bool __uk>
567     template<typename _InputIterator>
568       _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
569                  _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
570       _Hashtable(_InputIterator __f, _InputIterator __l,
571                  size_type __bucket_hint,
572                  const _H1& __h1, const _H2& __h2, const _Hash& __h,
573                  const _Equal& __eq, const _ExtractKey& __exk,
574                  const allocator_type& __a)
575       : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(),
576         __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
577                                   _H1, _H2, _Hash, __chc>(__exk, __eq,
578                                                           __h1, __h2, __h),
579         __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(),
580         _M_node_allocator(__a),
581         _M_bucket_count(0),
582         _M_element_count(0),
583         _M_rehash_policy()
584       {
585         _M_bucket_count = std::max(_M_rehash_policy._M_next_bkt(__bucket_hint),
586                                    _M_rehash_policy.
587                                    _M_bkt_for_elements(__detail::
588                                                        __distance_fw(__f,
589                                                                      __l)));
590         _M_buckets = _M_allocate_buckets(_M_bucket_count);
591         try
592           {
593             for (; __f != __l; ++__f)
594               this->insert(*__f);
595           }
596         catch(...)
597           {
598             clear();
599             _M_deallocate_buckets(_M_buckets, _M_bucket_count);
600             __throw_exception_again;
601           }
602       }
603   
604   template<typename _Key, typename _Value, 
605            typename _Allocator, typename _ExtractKey, typename _Equal,
606            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
607            bool __chc, bool __cit, bool __uk>
608     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
609                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
610     _Hashtable(const _Hashtable& __ht)
611     : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(__ht),
612       __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
613                                 _H1, _H2, _Hash, __chc>(__ht),
614       __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(__ht),
615       _M_node_allocator(__ht._M_node_allocator),
616       _M_bucket_count(__ht._M_bucket_count),
617       _M_element_count(__ht._M_element_count),
618       _M_rehash_policy(__ht._M_rehash_policy)
619     {
620       _M_buckets = _M_allocate_buckets(_M_bucket_count);
621       try
622         {
623           for (size_type __i = 0; __i < __ht._M_bucket_count; ++__i)
624             {
625               _Node* __n = __ht._M_buckets[__i];
626               _Node** __tail = _M_buckets + __i;
627               while (__n)
628                 {
629                   *__tail = _M_allocate_node(__n->_M_v);
630                   this->_M_copy_code(*__tail, __n);
631                   __tail = &((*__tail)->_M_next);
632                   __n = __n->_M_next;
633                 }
634             }
635         }
636       catch(...)
637         {
638           clear();
639           _M_deallocate_buckets(_M_buckets, _M_bucket_count);
640           __throw_exception_again;
641         }
642     }
643
644   template<typename _Key, typename _Value, 
645            typename _Allocator, typename _ExtractKey, typename _Equal,
646            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
647            bool __chc, bool __cit, bool __uk>
648     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
649                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>&
650     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
651                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
652     operator=(const _Hashtable& __ht)
653     {
654       _Hashtable __tmp(__ht);
655       this->swap(__tmp);
656       return *this;
657     }
658
659   template<typename _Key, typename _Value, 
660            typename _Allocator, typename _ExtractKey, typename _Equal,
661            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
662            bool __chc, bool __cit, bool __uk>
663     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
664                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
665     ~_Hashtable()
666     {
667       clear();
668       _M_deallocate_buckets(_M_buckets, _M_bucket_count);
669     }
670
671   template<typename _Key, typename _Value, 
672            typename _Allocator, typename _ExtractKey, typename _Equal,
673            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
674            bool __chc, bool __cit, bool __uk>
675     void
676     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
677                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
678     swap(_Hashtable& __x)
679     {
680       // The only base class with member variables is hash_code_base.  We
681       // define _Hash_code_base::_M_swap because different specializations
682       // have different members.
683       __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
684         _H1, _H2, _Hash, __chc>::_M_swap(__x);
685
686       // _GLIBCXX_RESOLVE_LIB_DEFECTS
687       // 431. Swapping containers with unequal allocators.
688       std::__alloc_swap<_Node_allocator_type>::_S_do_it(_M_node_allocator,
689                                                         __x._M_node_allocator);
690
691       std::swap(_M_rehash_policy, __x._M_rehash_policy);
692       std::swap(_M_buckets, __x._M_buckets);
693       std::swap(_M_bucket_count, __x._M_bucket_count);
694       std::swap(_M_element_count, __x._M_element_count);
695     }
696
697   template<typename _Key, typename _Value, 
698            typename _Allocator, typename _ExtractKey, typename _Equal,
699            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
700            bool __chc, bool __cit, bool __uk>
701     void
702     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
703                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
704     __rehash_policy(const _RehashPolicy& __pol)
705     {
706       _M_rehash_policy = __pol;
707       size_type __n_bkt = __pol._M_bkt_for_elements(_M_element_count);
708       if (__n_bkt > _M_bucket_count)
709         _M_rehash(__n_bkt);
710     }
711
712   template<typename _Key, typename _Value, 
713            typename _Allocator, typename _ExtractKey, typename _Equal,
714            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
715            bool __chc, bool __cit, bool __uk>
716     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
717                         _H1, _H2, _Hash, _RehashPolicy,
718                         __chc, __cit, __uk>::iterator
719     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
720                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
721     find(const key_type& __k)
722     {
723       typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
724       std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
725       _Node* __p = _M_find_node(_M_buckets[__n], __k, __code);
726       return __p ? iterator(__p, _M_buckets + __n) : this->end();
727     }
728
729   template<typename _Key, typename _Value, 
730            typename _Allocator, typename _ExtractKey, typename _Equal,
731            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
732            bool __chc, bool __cit, bool __uk>
733     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
734                         _H1, _H2, _Hash, _RehashPolicy,
735                         __chc, __cit, __uk>::const_iterator
736     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
737                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
738     find(const key_type& __k) const
739     {
740       typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
741       std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
742       _Node* __p = _M_find_node(_M_buckets[__n], __k, __code);
743       return __p ? const_iterator(__p, _M_buckets + __n) : this->end();
744     }
745
746   template<typename _Key, typename _Value, 
747            typename _Allocator, typename _ExtractKey, typename _Equal,
748            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
749            bool __chc, bool __cit, bool __uk>
750     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
751                         _H1, _H2, _Hash, _RehashPolicy,
752                         __chc, __cit, __uk>::size_type
753     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
754                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
755     count(const key_type& __k) const
756     {
757       typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
758       std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
759       std::size_t __result = 0;
760       for (_Node* __p = _M_buckets[__n]; __p; __p = __p->_M_next)
761         if (this->_M_compare(__k, __code, __p))
762           ++__result;
763       return __result;
764     }
765
766   template<typename _Key, typename _Value, 
767            typename _Allocator, typename _ExtractKey, typename _Equal,
768            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
769            bool __chc, bool __cit, bool __uk>
770     std::pair<typename _Hashtable<_Key, _Value, _Allocator,
771                                   _ExtractKey, _Equal, _H1,
772                                   _H2, _Hash, _RehashPolicy,
773                                   __chc, __cit, __uk>::iterator,
774               typename _Hashtable<_Key, _Value, _Allocator,
775                                   _ExtractKey, _Equal, _H1,
776                                   _H2, _Hash, _RehashPolicy,
777                                   __chc, __cit, __uk>::iterator>
778     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
779                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
780     equal_range(const key_type& __k)
781     {
782       typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
783       std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
784       _Node** __head = _M_buckets + __n;
785       _Node* __p = _M_find_node(*__head, __k, __code);
786       
787       if (__p)
788         {
789           _Node* __p1 = __p->_M_next;
790           for (; __p1; __p1 = __p1->_M_next)
791             if (!this->_M_compare(__k, __code, __p1))
792               break;
793
794           iterator __first(__p, __head);
795           iterator __last(__p1, __head);
796           if (!__p1)
797             __last._M_incr_bucket();
798           return std::make_pair(__first, __last);
799         }
800       else
801         return std::make_pair(this->end(), this->end());
802     }
803
804   template<typename _Key, typename _Value, 
805            typename _Allocator, typename _ExtractKey, typename _Equal,
806            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
807            bool __chc, bool __cit, bool __uk>
808     std::pair<typename _Hashtable<_Key, _Value, _Allocator,
809                                   _ExtractKey, _Equal, _H1,
810                                   _H2, _Hash, _RehashPolicy,
811                                   __chc, __cit, __uk>::const_iterator,
812               typename _Hashtable<_Key, _Value, _Allocator,
813                                   _ExtractKey, _Equal, _H1,
814                                   _H2, _Hash, _RehashPolicy,
815                                   __chc, __cit, __uk>::const_iterator>
816     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
817                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
818     equal_range(const key_type& __k) const
819     {
820       typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
821       std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
822       _Node** __head = _M_buckets + __n;
823       _Node* __p = _M_find_node(*__head, __k, __code);
824
825       if (__p)
826         {
827           _Node* __p1 = __p->_M_next;
828           for (; __p1; __p1 = __p1->_M_next)
829             if (!this->_M_compare(__k, __code, __p1))
830               break;
831
832           const_iterator __first(__p, __head);
833           const_iterator __last(__p1, __head);
834           if (!__p1)
835             __last._M_incr_bucket();
836           return std::make_pair(__first, __last);
837         }
838       else
839         return std::make_pair(this->end(), this->end());
840     }
841
842   // Find the node whose key compares equal to k, beginning the search
843   // at p (usually the head of a bucket).  Return nil if no node is found.
844   template<typename _Key, typename _Value, 
845            typename _Allocator, typename _ExtractKey, typename _Equal,
846            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
847            bool __chc, bool __cit, bool __uk>
848     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey,
849                         _Equal, _H1, _H2, _Hash, _RehashPolicy,
850                         __chc, __cit, __uk>::_Node* 
851     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
852                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
853     _M_find_node(_Node* __p, const key_type& __k,
854                 typename _Hashtable::_Hash_code_type __code) const
855     {
856       for (; __p; __p = __p->_M_next)
857         if (this->_M_compare(__k, __code, __p))
858           return __p;
859       return false;
860     }
861
862   // Insert v in bucket n (assumes no element with its key already present).
863   template<typename _Key, typename _Value, 
864            typename _Allocator, typename _ExtractKey, typename _Equal,
865            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
866            bool __chc, bool __cit, bool __uk>
867     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
868                         _H1, _H2, _Hash, _RehashPolicy,
869                         __chc, __cit, __uk>::iterator
870     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
871                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
872     _M_insert_bucket(const value_type& __v, size_type __n,
873                     typename _Hashtable::_Hash_code_type __code)
874     {
875       std::pair<bool, std::size_t> __do_rehash
876         = _M_rehash_policy._M_need_rehash(_M_bucket_count,
877                                           _M_element_count, 1);
878
879       // Allocate the new node before doing the rehash so that we don't
880       // do a rehash if the allocation throws.
881       _Node* __new_node = _M_allocate_node(__v);
882
883       try
884         {
885           if (__do_rehash.first)
886             {
887               const key_type& __k = this->_M_extract(__v);
888               __n = this->_M_bucket_index(__k, __code, __do_rehash.second);
889               _M_rehash(__do_rehash.second);
890             }
891
892           __new_node->_M_next = _M_buckets[__n];
893           this->_M_store_code(__new_node, __code);
894           _M_buckets[__n] = __new_node;
895           ++_M_element_count;
896           return iterator(__new_node, _M_buckets + __n);
897         }
898       catch(...)
899         {
900           _M_deallocate_node(__new_node);
901           __throw_exception_again;
902         }
903     }
904
905   // Insert v if no element with its key is already present.
906   template<typename _Key, typename _Value, 
907            typename _Allocator, typename _ExtractKey, typename _Equal,
908            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
909            bool __chc, bool __cit, bool __uk>
910     std::pair<typename _Hashtable<_Key, _Value, _Allocator,
911                                   _ExtractKey, _Equal, _H1,
912                                   _H2, _Hash, _RehashPolicy,
913                                   __chc, __cit, __uk>::iterator, bool>
914     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
915                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
916     _M_insert(const value_type& __v, std::_GLIBCXX_TR1 true_type)
917     {
918       const key_type& __k = this->_M_extract(__v);
919       typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
920       size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
921
922       if (_Node* __p = _M_find_node(_M_buckets[__n], __k, __code))
923         return std::make_pair(iterator(__p, _M_buckets + __n), false);
924       return std::make_pair(_M_insert_bucket(__v, __n, __code), true);
925     }
926   
927   // Insert v unconditionally.
928   template<typename _Key, typename _Value, 
929            typename _Allocator, typename _ExtractKey, typename _Equal,
930            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
931            bool __chc, bool __cit, bool __uk>
932     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
933                         _H1, _H2, _Hash, _RehashPolicy,
934                         __chc, __cit, __uk>::iterator
935     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
936                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
937     _M_insert(const value_type& __v, std::_GLIBCXX_TR1 false_type)
938     {
939       std::pair<bool, std::size_t> __do_rehash
940         = _M_rehash_policy._M_need_rehash(_M_bucket_count,
941                                           _M_element_count, 1);
942       if (__do_rehash.first)
943         _M_rehash(__do_rehash.second);
944  
945       const key_type& __k = this->_M_extract(__v);
946       typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
947       size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
948
949       // First find the node, avoid leaking new_node if compare throws.
950       _Node* __prev = _M_find_node(_M_buckets[__n], __k, __code);
951       _Node* __new_node = _M_allocate_node(__v);
952
953       if (__prev)
954         {
955           __new_node->_M_next = __prev->_M_next;
956           __prev->_M_next = __new_node;
957         }
958       else
959         {
960           __new_node->_M_next = _M_buckets[__n];
961           _M_buckets[__n] = __new_node;
962         }
963       this->_M_store_code(__new_node, __code);
964
965       ++_M_element_count;
966       return iterator(__new_node, _M_buckets + __n);
967     }
968
969   // For erase(iterator) and erase(const_iterator).
970   template<typename _Key, typename _Value, 
971            typename _Allocator, typename _ExtractKey, typename _Equal,
972            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
973            bool __chc, bool __cit, bool __uk>
974     void
975     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
976                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
977     _M_erase_node(_Node* __p, _Node** __b)
978     {
979       _Node* __cur = *__b;
980       if (__cur == __p)
981         *__b = __cur->_M_next;
982       else
983         {
984           _Node* __next = __cur->_M_next;
985           while (__next != __p)
986             {
987               __cur = __next;
988               __next = __cur->_M_next;
989             }
990           __cur->_M_next = __next->_M_next;
991         }
992
993       _M_deallocate_node(__p);
994       --_M_element_count;
995     }
996
997   template<typename _Key, typename _Value, 
998            typename _Allocator, typename _ExtractKey, typename _Equal,
999            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1000            bool __chc, bool __cit, bool __uk>
1001     template<typename _InputIterator>
1002       void 
1003       _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
1004                  _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
1005       insert(_InputIterator __first, _InputIterator __last)
1006       {
1007         size_type __n_elt = __detail::__distance_fw(__first, __last);
1008         std::pair<bool, std::size_t> __do_rehash
1009           = _M_rehash_policy._M_need_rehash(_M_bucket_count,
1010                                             _M_element_count, __n_elt);
1011         if (__do_rehash.first)
1012           _M_rehash(__do_rehash.second);
1013
1014         for (; __first != __last; ++__first)
1015           this->insert(*__first);
1016       }
1017
1018   template<typename _Key, typename _Value, 
1019            typename _Allocator, typename _ExtractKey, typename _Equal,
1020            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1021            bool __chc, bool __cit, bool __uk>
1022     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
1023                         _H1, _H2, _Hash, _RehashPolicy,
1024                         __chc, __cit, __uk>::iterator
1025     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
1026                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
1027     erase(iterator __it)
1028     {
1029       iterator __result = __it;
1030       ++__result;
1031       _M_erase_node(__it._M_cur_node, __it._M_cur_bucket);
1032       return __result;
1033     }
1034
1035   template<typename _Key, typename _Value, 
1036            typename _Allocator, typename _ExtractKey, typename _Equal,
1037            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1038            bool __chc, bool __cit, bool __uk>
1039     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
1040                         _H1, _H2, _Hash, _RehashPolicy,
1041                         __chc, __cit, __uk>::const_iterator
1042     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
1043                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
1044     erase(const_iterator __it)
1045     {
1046       const_iterator __result = __it;
1047       ++__result;
1048       _M_erase_node(__it._M_cur_node, __it._M_cur_bucket);
1049       return __result;
1050     }
1051
1052   template<typename _Key, typename _Value, 
1053            typename _Allocator, typename _ExtractKey, typename _Equal,
1054            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1055            bool __chc, bool __cit, bool __uk>
1056     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
1057                         _H1, _H2, _Hash, _RehashPolicy,
1058                         __chc, __cit, __uk>::size_type
1059     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
1060                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
1061     erase(const key_type& __k)
1062     {
1063       typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
1064       std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
1065       size_type __result = 0;
1066       
1067       _Node** __slot = _M_buckets + __n;
1068       while (*__slot && !this->_M_compare(__k, __code, *__slot))
1069         __slot = &((*__slot)->_M_next);
1070
1071       _Node** __saved_slot = 0;
1072       while (*__slot && this->_M_compare(__k, __code, *__slot))
1073         {
1074           // _GLIBCXX_RESOLVE_LIB_DEFECTS
1075           // 526. Is it undefined if a function in the standard changes
1076           // in parameters?
1077           if (&this->_M_extract((*__slot)->_M_v) != &__k)
1078             {
1079               _Node* __p = *__slot;
1080               *__slot = __p->_M_next;
1081               _M_deallocate_node(__p);
1082               --_M_element_count;
1083               ++__result;
1084             }
1085           else
1086             {
1087               __saved_slot = __slot;
1088               __slot = &((*__slot)->_M_next);
1089             }
1090         }
1091
1092       if (__saved_slot)
1093         {
1094           _Node* __p = *__saved_slot;
1095           *__saved_slot = __p->_M_next;
1096           _M_deallocate_node(__p);
1097           --_M_element_count;
1098           ++__result;
1099         }
1100
1101       return __result;
1102     }
1103
1104   // ??? This could be optimized by taking advantage of the bucket
1105   // structure, but it's not clear that it's worth doing.  It probably
1106   // wouldn't even be an optimization unless the load factor is large.
1107   template<typename _Key, typename _Value, 
1108            typename _Allocator, typename _ExtractKey, typename _Equal,
1109            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1110            bool __chc, bool __cit, bool __uk>
1111     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
1112                         _H1, _H2, _Hash, _RehashPolicy,
1113                         __chc, __cit, __uk>::iterator
1114     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
1115                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
1116     erase(iterator __first, iterator __last)
1117     {
1118       while (__first != __last)
1119         __first = this->erase(__first);
1120       return __last;
1121     }
1122   
1123   template<typename _Key, typename _Value, 
1124            typename _Allocator, typename _ExtractKey, typename _Equal,
1125            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1126            bool __chc, bool __cit, bool __uk>
1127     typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
1128                         _H1, _H2, _Hash, _RehashPolicy,
1129                         __chc, __cit, __uk>::const_iterator
1130     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
1131                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
1132     erase(const_iterator __first, const_iterator __last)
1133     {
1134       while (__first != __last)
1135         __first = this->erase(__first);
1136       return __last;
1137     }
1138
1139   template<typename _Key, typename _Value, 
1140            typename _Allocator, typename _ExtractKey, typename _Equal,
1141            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1142            bool __chc, bool __cit, bool __uk>
1143     void
1144     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
1145                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
1146     clear()
1147     {
1148       _M_deallocate_nodes(_M_buckets, _M_bucket_count);
1149       _M_element_count = 0;
1150     }
1151  
1152   template<typename _Key, typename _Value, 
1153            typename _Allocator, typename _ExtractKey, typename _Equal,
1154            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1155            bool __chc, bool __cit, bool __uk>
1156     void
1157     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
1158                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
1159     rehash(size_type __n)
1160     {
1161       _M_rehash(std::max(_M_rehash_policy._M_next_bkt(__n),
1162                          _M_rehash_policy._M_bkt_for_elements(_M_element_count
1163                                                               + 1)));
1164     }
1165
1166   template<typename _Key, typename _Value, 
1167            typename _Allocator, typename _ExtractKey, typename _Equal,
1168            typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
1169            bool __chc, bool __cit, bool __uk>
1170     void
1171     _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
1172                _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
1173     _M_rehash(size_type __n)
1174     {
1175       _Node** __new_array = _M_allocate_buckets(__n);
1176       try
1177         {
1178           for (size_type __i = 0; __i < _M_bucket_count; ++__i)
1179             while (_Node* __p = _M_buckets[__i])
1180               {
1181                 std::size_t __new_index = this->_M_bucket_index(__p, __n);
1182                 _M_buckets[__i] = __p->_M_next;
1183                 __p->_M_next = __new_array[__new_index];
1184                 __new_array[__new_index] = __p;
1185               }
1186           _M_deallocate_buckets(_M_buckets, _M_bucket_count);
1187           _M_bucket_count = __n;
1188           _M_buckets = __new_array;
1189         }
1190       catch(...)
1191         {
1192           // A failure here means that a hash function threw an exception.
1193           // We can't restore the previous state without calling the hash
1194           // function again, so the only sensible recovery is to delete
1195           // everything.
1196           _M_deallocate_nodes(__new_array, __n);
1197           _M_deallocate_buckets(__new_array, __n);
1198           _M_deallocate_nodes(_M_buckets, _M_bucket_count);
1199           _M_element_count = 0;
1200           __throw_exception_again;
1201         }
1202     }
1203
1204 _GLIBCXX_END_NAMESPACE_TR1
1205 }