OSDN Git Service

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