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