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