xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/include/bits/hashtable_policy.h (revision 81fc95a5293ee307c688a350a3feb4734aaddbb4)
1e4b17023SJohn Marino // Internal policy header for unordered_set and unordered_map -*- C++ -*-
2e4b17023SJohn Marino 
3e4b17023SJohn Marino // Copyright (C) 2010, 2011, 2012 Free Software Foundation, Inc.
4e4b17023SJohn Marino //
5e4b17023SJohn Marino // This file is part of the GNU ISO C++ Library.  This library is free
6e4b17023SJohn Marino // software; you can redistribute it and/or modify it under the
7e4b17023SJohn Marino // terms of the GNU General Public License as published by the
8e4b17023SJohn Marino // Free Software Foundation; either version 3, or (at your option)
9e4b17023SJohn Marino // any later version.
10e4b17023SJohn Marino 
11e4b17023SJohn Marino // This library is distributed in the hope that it will be useful,
12e4b17023SJohn Marino // but WITHOUT ANY WARRANTY; without even the implied warranty of
13e4b17023SJohn Marino // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14e4b17023SJohn Marino // GNU General Public License for more details.
15e4b17023SJohn Marino 
16e4b17023SJohn Marino // Under Section 7 of GPL version 3, you are granted additional
17e4b17023SJohn Marino // permissions described in the GCC Runtime Library Exception, version
18e4b17023SJohn Marino // 3.1, as published by the Free Software Foundation.
19e4b17023SJohn Marino 
20e4b17023SJohn Marino // You should have received a copy of the GNU General Public License and
21e4b17023SJohn Marino // a copy of the GCC Runtime Library Exception along with this program;
22e4b17023SJohn Marino // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23e4b17023SJohn Marino // <http://www.gnu.org/licenses/>.
24e4b17023SJohn Marino 
25e4b17023SJohn Marino /** @file bits/hashtable_policy.h
26e4b17023SJohn Marino  *  This is an internal header file, included by other library headers.
27e4b17023SJohn Marino  *  Do not attempt to use it directly.
28e4b17023SJohn Marino  *  @headername{unordered_map,unordered_set}
29e4b17023SJohn Marino  */
30e4b17023SJohn Marino 
31e4b17023SJohn Marino #ifndef _HASHTABLE_POLICY_H
32e4b17023SJohn Marino #define _HASHTABLE_POLICY_H 1
33e4b17023SJohn Marino 
_GLIBCXX_VISIBILITY(default)34e4b17023SJohn Marino namespace std _GLIBCXX_VISIBILITY(default)
35e4b17023SJohn Marino {
36e4b17023SJohn Marino namespace __detail
37e4b17023SJohn Marino {
38e4b17023SJohn Marino _GLIBCXX_BEGIN_NAMESPACE_VERSION
39e4b17023SJohn Marino 
40e4b17023SJohn Marino   // Helper function: return distance(first, last) for forward
41e4b17023SJohn Marino   // iterators, or 0 for input iterators.
42e4b17023SJohn Marino   template<class _Iterator>
43e4b17023SJohn Marino     inline typename std::iterator_traits<_Iterator>::difference_type
44e4b17023SJohn Marino     __distance_fw(_Iterator __first, _Iterator __last,
45e4b17023SJohn Marino 		  std::input_iterator_tag)
46e4b17023SJohn Marino     { return 0; }
47e4b17023SJohn Marino 
48e4b17023SJohn Marino   template<class _Iterator>
49e4b17023SJohn Marino     inline typename std::iterator_traits<_Iterator>::difference_type
50e4b17023SJohn Marino     __distance_fw(_Iterator __first, _Iterator __last,
51e4b17023SJohn Marino 		  std::forward_iterator_tag)
52e4b17023SJohn Marino     { return std::distance(__first, __last); }
53e4b17023SJohn Marino 
54e4b17023SJohn Marino   template<class _Iterator>
55e4b17023SJohn Marino     inline typename std::iterator_traits<_Iterator>::difference_type
56e4b17023SJohn Marino     __distance_fw(_Iterator __first, _Iterator __last)
57e4b17023SJohn Marino     {
58e4b17023SJohn Marino       typedef typename std::iterator_traits<_Iterator>::iterator_category _Tag;
59e4b17023SJohn Marino       return __distance_fw(__first, __last, _Tag());
60e4b17023SJohn Marino     }
61e4b17023SJohn Marino 
62*5ce9237cSJohn Marino   // Helper type used to detect whether the hash functor is noexcept.
63e4b17023SJohn Marino   template <typename _Key, typename _Hash>
64e4b17023SJohn Marino     struct __is_noexcept_hash : std::integral_constant<bool,
65e4b17023SJohn Marino 	noexcept(declval<const _Hash&>()(declval<const _Key&>()))>
66e4b17023SJohn Marino     {};
67e4b17023SJohn Marino 
68e4b17023SJohn Marino   // Auxiliary types used for all instantiations of _Hashtable: nodes
69e4b17023SJohn Marino   // and iterators.
70e4b17023SJohn Marino 
71e4b17023SJohn Marino   // Nodes, used to wrap elements stored in the hash table.  A policy
72e4b17023SJohn Marino   // template parameter of class template _Hashtable controls whether
73e4b17023SJohn Marino   // nodes also store a hash code. In some cases (e.g. strings) this
74e4b17023SJohn Marino   // may be a performance win.
75e4b17023SJohn Marino   struct _Hash_node_base
76e4b17023SJohn Marino   {
77e4b17023SJohn Marino     _Hash_node_base* _M_nxt;
78e4b17023SJohn Marino 
79e4b17023SJohn Marino     _Hash_node_base()
80e4b17023SJohn Marino       : _M_nxt() { }
81e4b17023SJohn Marino     _Hash_node_base(_Hash_node_base* __next)
82e4b17023SJohn Marino       : _M_nxt(__next) { }
83e4b17023SJohn Marino   };
84e4b17023SJohn Marino 
85e4b17023SJohn Marino   template<typename _Value, bool __cache_hash_code>
86e4b17023SJohn Marino     struct _Hash_node;
87e4b17023SJohn Marino 
88e4b17023SJohn Marino   template<typename _Value>
89e4b17023SJohn Marino     struct _Hash_node<_Value, true> : _Hash_node_base
90e4b17023SJohn Marino     {
91e4b17023SJohn Marino       _Value       _M_v;
92e4b17023SJohn Marino       std::size_t  _M_hash_code;
93e4b17023SJohn Marino 
94e4b17023SJohn Marino       template<typename... _Args>
95e4b17023SJohn Marino 	_Hash_node(_Args&&... __args)
96e4b17023SJohn Marino 	: _M_v(std::forward<_Args>(__args)...), _M_hash_code() { }
97e4b17023SJohn Marino 
98e4b17023SJohn Marino       _Hash_node* _M_next() const
99e4b17023SJohn Marino       { return static_cast<_Hash_node*>(_M_nxt); }
100e4b17023SJohn Marino     };
101e4b17023SJohn Marino 
102e4b17023SJohn Marino   template<typename _Value>
103e4b17023SJohn Marino     struct _Hash_node<_Value, false> : _Hash_node_base
104e4b17023SJohn Marino     {
105e4b17023SJohn Marino       _Value       _M_v;
106e4b17023SJohn Marino 
107e4b17023SJohn Marino       template<typename... _Args>
108e4b17023SJohn Marino 	_Hash_node(_Args&&... __args)
109e4b17023SJohn Marino 	: _M_v(std::forward<_Args>(__args)...) { }
110e4b17023SJohn Marino 
111e4b17023SJohn Marino       _Hash_node* _M_next() const
112e4b17023SJohn Marino       { return static_cast<_Hash_node*>(_M_nxt); }
113e4b17023SJohn Marino     };
114e4b17023SJohn Marino 
115e4b17023SJohn Marino   // Node iterators, used to iterate through all the hashtable.
116e4b17023SJohn Marino   template<typename _Value, bool __cache>
117e4b17023SJohn Marino     struct _Node_iterator_base
118e4b17023SJohn Marino     {
119e4b17023SJohn Marino       _Node_iterator_base(_Hash_node<_Value, __cache>* __p)
120e4b17023SJohn Marino       : _M_cur(__p) { }
121e4b17023SJohn Marino 
122e4b17023SJohn Marino       void
123e4b17023SJohn Marino       _M_incr()
124e4b17023SJohn Marino       { _M_cur = _M_cur->_M_next(); }
125e4b17023SJohn Marino 
126e4b17023SJohn Marino       _Hash_node<_Value, __cache>*  _M_cur;
127e4b17023SJohn Marino     };
128e4b17023SJohn Marino 
129e4b17023SJohn Marino   template<typename _Value, bool __cache>
130e4b17023SJohn Marino     inline bool
131e4b17023SJohn Marino     operator==(const _Node_iterator_base<_Value, __cache>& __x,
132e4b17023SJohn Marino 	       const _Node_iterator_base<_Value, __cache>& __y)
133e4b17023SJohn Marino     { return __x._M_cur == __y._M_cur; }
134e4b17023SJohn Marino 
135e4b17023SJohn Marino   template<typename _Value, bool __cache>
136e4b17023SJohn Marino     inline bool
137e4b17023SJohn Marino     operator!=(const _Node_iterator_base<_Value, __cache>& __x,
138e4b17023SJohn Marino 	       const _Node_iterator_base<_Value, __cache>& __y)
139e4b17023SJohn Marino     { return __x._M_cur != __y._M_cur; }
140e4b17023SJohn Marino 
141e4b17023SJohn Marino   template<typename _Value, bool __constant_iterators, bool __cache>
142e4b17023SJohn Marino     struct _Node_iterator
143e4b17023SJohn Marino     : public _Node_iterator_base<_Value, __cache>
144e4b17023SJohn Marino     {
145e4b17023SJohn Marino       typedef _Value                                   value_type;
146e4b17023SJohn Marino       typedef typename std::conditional<__constant_iterators,
147e4b17023SJohn Marino 					const _Value*, _Value*>::type
148e4b17023SJohn Marino 						       pointer;
149e4b17023SJohn Marino       typedef typename std::conditional<__constant_iterators,
150e4b17023SJohn Marino 					const _Value&, _Value&>::type
151e4b17023SJohn Marino 						       reference;
152e4b17023SJohn Marino       typedef std::ptrdiff_t                           difference_type;
153e4b17023SJohn Marino       typedef std::forward_iterator_tag                iterator_category;
154e4b17023SJohn Marino 
155e4b17023SJohn Marino       _Node_iterator()
156e4b17023SJohn Marino       : _Node_iterator_base<_Value, __cache>(0) { }
157e4b17023SJohn Marino 
158e4b17023SJohn Marino       explicit
159e4b17023SJohn Marino       _Node_iterator(_Hash_node<_Value, __cache>* __p)
160e4b17023SJohn Marino       : _Node_iterator_base<_Value, __cache>(__p) { }
161e4b17023SJohn Marino 
162e4b17023SJohn Marino       reference
163e4b17023SJohn Marino       operator*() const
164e4b17023SJohn Marino       { return this->_M_cur->_M_v; }
165e4b17023SJohn Marino 
166e4b17023SJohn Marino       pointer
167e4b17023SJohn Marino       operator->() const
168e4b17023SJohn Marino       { return std::__addressof(this->_M_cur->_M_v); }
169e4b17023SJohn Marino 
170e4b17023SJohn Marino       _Node_iterator&
171e4b17023SJohn Marino       operator++()
172e4b17023SJohn Marino       {
173e4b17023SJohn Marino 	this->_M_incr();
174e4b17023SJohn Marino 	return *this;
175e4b17023SJohn Marino       }
176e4b17023SJohn Marino 
177e4b17023SJohn Marino       _Node_iterator
178e4b17023SJohn Marino       operator++(int)
179e4b17023SJohn Marino       {
180e4b17023SJohn Marino 	_Node_iterator __tmp(*this);
181e4b17023SJohn Marino 	this->_M_incr();
182e4b17023SJohn Marino 	return __tmp;
183e4b17023SJohn Marino       }
184e4b17023SJohn Marino     };
185e4b17023SJohn Marino 
186e4b17023SJohn Marino   template<typename _Value, bool __constant_iterators, bool __cache>
187e4b17023SJohn Marino     struct _Node_const_iterator
188e4b17023SJohn Marino     : public _Node_iterator_base<_Value, __cache>
189e4b17023SJohn Marino     {
190e4b17023SJohn Marino       typedef _Value                                   value_type;
191e4b17023SJohn Marino       typedef const _Value*                            pointer;
192e4b17023SJohn Marino       typedef const _Value&                            reference;
193e4b17023SJohn Marino       typedef std::ptrdiff_t                           difference_type;
194e4b17023SJohn Marino       typedef std::forward_iterator_tag                iterator_category;
195e4b17023SJohn Marino 
196e4b17023SJohn Marino       _Node_const_iterator()
197e4b17023SJohn Marino       : _Node_iterator_base<_Value, __cache>(0) { }
198e4b17023SJohn Marino 
199e4b17023SJohn Marino       explicit
200e4b17023SJohn Marino       _Node_const_iterator(_Hash_node<_Value, __cache>* __p)
201e4b17023SJohn Marino       : _Node_iterator_base<_Value, __cache>(__p) { }
202e4b17023SJohn Marino 
203e4b17023SJohn Marino       _Node_const_iterator(const _Node_iterator<_Value, __constant_iterators,
204e4b17023SJohn Marino 			   __cache>& __x)
205e4b17023SJohn Marino       : _Node_iterator_base<_Value, __cache>(__x._M_cur) { }
206e4b17023SJohn Marino 
207e4b17023SJohn Marino       reference
208e4b17023SJohn Marino       operator*() const
209e4b17023SJohn Marino       { return this->_M_cur->_M_v; }
210e4b17023SJohn Marino 
211e4b17023SJohn Marino       pointer
212e4b17023SJohn Marino       operator->() const
213e4b17023SJohn Marino       { return std::__addressof(this->_M_cur->_M_v); }
214e4b17023SJohn Marino 
215e4b17023SJohn Marino       _Node_const_iterator&
216e4b17023SJohn Marino       operator++()
217e4b17023SJohn Marino       {
218e4b17023SJohn Marino 	this->_M_incr();
219e4b17023SJohn Marino 	return *this;
220e4b17023SJohn Marino       }
221e4b17023SJohn Marino 
222e4b17023SJohn Marino       _Node_const_iterator
223e4b17023SJohn Marino       operator++(int)
224e4b17023SJohn Marino       {
225e4b17023SJohn Marino 	_Node_const_iterator __tmp(*this);
226e4b17023SJohn Marino 	this->_M_incr();
227e4b17023SJohn Marino 	return __tmp;
228e4b17023SJohn Marino       }
229e4b17023SJohn Marino     };
230e4b17023SJohn Marino 
231e4b17023SJohn Marino   // Many of class template _Hashtable's template parameters are policy
232e4b17023SJohn Marino   // classes.  These are defaults for the policies.
233e4b17023SJohn Marino 
234e4b17023SJohn Marino   // Default range hashing function: use division to fold a large number
235e4b17023SJohn Marino   // into the range [0, N).
236e4b17023SJohn Marino   struct _Mod_range_hashing
237e4b17023SJohn Marino   {
238e4b17023SJohn Marino     typedef std::size_t first_argument_type;
239e4b17023SJohn Marino     typedef std::size_t second_argument_type;
240e4b17023SJohn Marino     typedef std::size_t result_type;
241e4b17023SJohn Marino 
242e4b17023SJohn Marino     result_type
243e4b17023SJohn Marino     operator()(first_argument_type __num, second_argument_type __den) const
244e4b17023SJohn Marino     { return __num % __den; }
245e4b17023SJohn Marino   };
246e4b17023SJohn Marino 
247e4b17023SJohn Marino   // Default ranged hash function H.  In principle it should be a
248e4b17023SJohn Marino   // function object composed from objects of type H1 and H2 such that
249e4b17023SJohn Marino   // h(k, N) = h2(h1(k), N), but that would mean making extra copies of
250e4b17023SJohn Marino   // h1 and h2.  So instead we'll just use a tag to tell class template
251e4b17023SJohn Marino   // hashtable to do that composition.
252e4b17023SJohn Marino   struct _Default_ranged_hash { };
253e4b17023SJohn Marino 
254e4b17023SJohn Marino   // Default value for rehash policy.  Bucket size is (usually) the
255e4b17023SJohn Marino   // smallest prime that keeps the load factor small enough.
256e4b17023SJohn Marino   struct _Prime_rehash_policy
257e4b17023SJohn Marino   {
258e4b17023SJohn Marino     _Prime_rehash_policy(float __z = 1.0)
259e4b17023SJohn Marino     : _M_max_load_factor(__z), _M_prev_resize(0), _M_next_resize(0) { }
260e4b17023SJohn Marino 
261e4b17023SJohn Marino     float
262e4b17023SJohn Marino     max_load_factor() const noexcept
263e4b17023SJohn Marino     { return _M_max_load_factor; }
264e4b17023SJohn Marino 
265e4b17023SJohn Marino     // Return a bucket size no smaller than n.
266e4b17023SJohn Marino     std::size_t
267e4b17023SJohn Marino     _M_next_bkt(std::size_t __n) const;
268e4b17023SJohn Marino 
269e4b17023SJohn Marino     // Return a bucket count appropriate for n elements
270e4b17023SJohn Marino     std::size_t
271e4b17023SJohn Marino     _M_bkt_for_elements(std::size_t __n) const;
272e4b17023SJohn Marino 
273e4b17023SJohn Marino     // __n_bkt is current bucket count, __n_elt is current element count,
274e4b17023SJohn Marino     // and __n_ins is number of elements to be inserted.  Do we need to
275e4b17023SJohn Marino     // increase bucket count?  If so, return make_pair(true, n), where n
276e4b17023SJohn Marino     // is the new bucket count.  If not, return make_pair(false, 0).
277e4b17023SJohn Marino     std::pair<bool, std::size_t>
278e4b17023SJohn Marino     _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt,
279e4b17023SJohn Marino 		   std::size_t __n_ins) const;
280e4b17023SJohn Marino 
281e4b17023SJohn Marino     typedef std::pair<std::size_t, std::size_t> _State;
282e4b17023SJohn Marino 
283e4b17023SJohn Marino     _State
284e4b17023SJohn Marino     _M_state() const
285e4b17023SJohn Marino     { return std::make_pair(_M_prev_resize, _M_next_resize); }
286e4b17023SJohn Marino 
287e4b17023SJohn Marino     void
288e4b17023SJohn Marino     _M_reset(const _State& __state)
289e4b17023SJohn Marino     {
290e4b17023SJohn Marino       _M_prev_resize = __state.first;
291e4b17023SJohn Marino       _M_next_resize = __state.second;
292e4b17023SJohn Marino     }
293e4b17023SJohn Marino 
294e4b17023SJohn Marino     enum { _S_n_primes = sizeof(unsigned long) != 8 ? 256 : 256 + 48 };
295e4b17023SJohn Marino 
296e4b17023SJohn Marino     static const std::size_t _S_growth_factor = 2;
297e4b17023SJohn Marino 
298e4b17023SJohn Marino     float                _M_max_load_factor;
299e4b17023SJohn Marino     mutable std::size_t  _M_prev_resize;
300e4b17023SJohn Marino     mutable std::size_t  _M_next_resize;
301e4b17023SJohn Marino   };
302e4b17023SJohn Marino 
303e4b17023SJohn Marino   extern const unsigned long __prime_list[];
304e4b17023SJohn Marino 
305e4b17023SJohn Marino   // XXX This is a hack.  There's no good reason for any of
306e4b17023SJohn Marino   // _Prime_rehash_policy's member functions to be inline.
307e4b17023SJohn Marino 
308e4b17023SJohn Marino   // Return a prime no smaller than n.
309e4b17023SJohn Marino   inline std::size_t
310e4b17023SJohn Marino   _Prime_rehash_policy::
311e4b17023SJohn Marino   _M_next_bkt(std::size_t __n) const
312e4b17023SJohn Marino   {
313e4b17023SJohn Marino     // Optimize lookups involving the first elements of __prime_list.
314e4b17023SJohn Marino     // (useful to speed-up, eg, constructors)
315e4b17023SJohn Marino     static const unsigned char __fast_bkt[12]
316e4b17023SJohn Marino       = { 2, 2, 2, 3, 5, 5, 7, 7, 11, 11, 11, 11 };
317e4b17023SJohn Marino 
318e4b17023SJohn Marino     const std::size_t __grown_n = __n * _S_growth_factor;
319e4b17023SJohn Marino     if (__grown_n <= 11)
320e4b17023SJohn Marino       {
321e4b17023SJohn Marino 	_M_prev_resize = 0;
322e4b17023SJohn Marino 	_M_next_resize
323e4b17023SJohn Marino 	  = __builtin_ceil(__fast_bkt[__grown_n]
324e4b17023SJohn Marino 			   * (long double)_M_max_load_factor);
325e4b17023SJohn Marino 	return __fast_bkt[__grown_n];
326e4b17023SJohn Marino       }
327e4b17023SJohn Marino 
328e4b17023SJohn Marino     const unsigned long* __next_bkt
329e4b17023SJohn Marino       = std::lower_bound(__prime_list + 5, __prime_list + _S_n_primes,
330e4b17023SJohn Marino 			 __grown_n);
331e4b17023SJohn Marino     const unsigned long* __prev_bkt
332e4b17023SJohn Marino       = std::lower_bound(__prime_list + 1, __next_bkt, __n / _S_growth_factor);
333e4b17023SJohn Marino 
334e4b17023SJohn Marino     _M_prev_resize
335e4b17023SJohn Marino       = __builtin_floor(*(__prev_bkt - 1) * (long double)_M_max_load_factor);
336e4b17023SJohn Marino     _M_next_resize
337e4b17023SJohn Marino       = __builtin_ceil(*__next_bkt * (long double)_M_max_load_factor);
338e4b17023SJohn Marino     return *__next_bkt;
339e4b17023SJohn Marino   }
340e4b17023SJohn Marino 
341e4b17023SJohn Marino   // Return the smallest prime p such that alpha p >= n, where alpha
342e4b17023SJohn Marino   // is the load factor.
343e4b17023SJohn Marino   inline std::size_t
344e4b17023SJohn Marino   _Prime_rehash_policy::
345e4b17023SJohn Marino   _M_bkt_for_elements(std::size_t __n) const
346e4b17023SJohn Marino   { return _M_next_bkt(__builtin_ceil(__n / (long double)_M_max_load_factor)); }
347e4b17023SJohn Marino 
348e4b17023SJohn Marino   // Finds the smallest prime p such that alpha p > __n_elt + __n_ins.
349e4b17023SJohn Marino   // If p > __n_bkt, return make_pair(true, p); otherwise return
350e4b17023SJohn Marino   // make_pair(false, 0).  In principle this isn't very different from
351e4b17023SJohn Marino   // _M_bkt_for_elements.
352e4b17023SJohn Marino 
353e4b17023SJohn Marino   // The only tricky part is that we're caching the element count at
354e4b17023SJohn Marino   // which we need to rehash, so we don't have to do a floating-point
355e4b17023SJohn Marino   // multiply for every insertion.
356e4b17023SJohn Marino 
357e4b17023SJohn Marino   inline std::pair<bool, std::size_t>
358e4b17023SJohn Marino   _Prime_rehash_policy::
359e4b17023SJohn Marino   _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt,
360e4b17023SJohn Marino 		 std::size_t __n_ins) const
361e4b17023SJohn Marino   {
362e4b17023SJohn Marino     if (__n_elt + __n_ins >= _M_next_resize)
363e4b17023SJohn Marino       {
364e4b17023SJohn Marino 	long double __min_bkts = (__n_elt + __n_ins)
365e4b17023SJohn Marino 				 / (long double)_M_max_load_factor;
366e4b17023SJohn Marino 	if (__min_bkts >= __n_bkt)
367e4b17023SJohn Marino 	  return std::make_pair(true,
368e4b17023SJohn Marino 				_M_next_bkt(__builtin_floor(__min_bkts) + 1));
369e4b17023SJohn Marino 	else
370e4b17023SJohn Marino 	  {
371e4b17023SJohn Marino 	    _M_next_resize
372e4b17023SJohn Marino 	      = __builtin_floor(__n_bkt * (long double)_M_max_load_factor);
373e4b17023SJohn Marino 	    return std::make_pair(false, 0);
374e4b17023SJohn Marino 	  }
375e4b17023SJohn Marino       }
376e4b17023SJohn Marino     else if (__n_elt + __n_ins < _M_prev_resize)
377e4b17023SJohn Marino       {
378e4b17023SJohn Marino 	long double __min_bkts = (__n_elt + __n_ins)
379e4b17023SJohn Marino 				 / (long double)_M_max_load_factor;
380e4b17023SJohn Marino 	return std::make_pair(true,
381e4b17023SJohn Marino 			      _M_next_bkt(__builtin_floor(__min_bkts) + 1));
382e4b17023SJohn Marino       }
383e4b17023SJohn Marino     else
384e4b17023SJohn Marino       return std::make_pair(false, 0);
385e4b17023SJohn Marino   }
386e4b17023SJohn Marino 
387e4b17023SJohn Marino   // Base classes for std::_Hashtable.  We define these base classes
388e4b17023SJohn Marino   // because in some cases we want to do different things depending
389e4b17023SJohn Marino   // on the value of a policy class.  In some cases the policy class
390e4b17023SJohn Marino   // affects which member functions and nested typedefs are defined;
391e4b17023SJohn Marino   // we handle that by specializing base class templates.  Several of
392e4b17023SJohn Marino   // the base class templates need to access other members of class
393e4b17023SJohn Marino   // template _Hashtable, so we use the "curiously recurring template
394e4b17023SJohn Marino   // pattern" for them.
395e4b17023SJohn Marino 
396e4b17023SJohn Marino   // class template _Map_base.  If the hashtable has a value type of
397e4b17023SJohn Marino   // the form pair<T1, T2> and a key extraction policy that returns the
398e4b17023SJohn Marino   // first part of the pair, the hashtable gets a mapped_type typedef.
399e4b17023SJohn Marino   // If it satisfies those criteria and also has unique keys, then it
400e4b17023SJohn Marino   // also gets an operator[].
401e4b17023SJohn Marino   template<typename _Key, typename _Value, typename _Ex, bool __unique,
402e4b17023SJohn Marino 	   typename _Hashtable>
403e4b17023SJohn Marino     struct _Map_base { };
404e4b17023SJohn Marino 
405e4b17023SJohn Marino   template<typename _Key, typename _Pair, typename _Hashtable>
406e4b17023SJohn Marino     struct _Map_base<_Key, _Pair, std::_Select1st<_Pair>, false, _Hashtable>
407e4b17023SJohn Marino     {
408e4b17023SJohn Marino       typedef typename _Pair::second_type mapped_type;
409e4b17023SJohn Marino     };
410e4b17023SJohn Marino 
411e4b17023SJohn Marino   template<typename _Key, typename _Pair, typename _Hashtable>
412e4b17023SJohn Marino     struct _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>
413e4b17023SJohn Marino     {
414e4b17023SJohn Marino       typedef typename _Pair::second_type mapped_type;
415e4b17023SJohn Marino 
416e4b17023SJohn Marino       mapped_type&
417e4b17023SJohn Marino       operator[](const _Key& __k);
418e4b17023SJohn Marino 
419e4b17023SJohn Marino       mapped_type&
420e4b17023SJohn Marino       operator[](_Key&& __k);
421e4b17023SJohn Marino 
422e4b17023SJohn Marino       // _GLIBCXX_RESOLVE_LIB_DEFECTS
423e4b17023SJohn Marino       // DR 761. unordered_map needs an at() member function.
424e4b17023SJohn Marino       mapped_type&
425e4b17023SJohn Marino       at(const _Key& __k);
426e4b17023SJohn Marino 
427e4b17023SJohn Marino       const mapped_type&
428e4b17023SJohn Marino       at(const _Key& __k) const;
429e4b17023SJohn Marino     };
430e4b17023SJohn Marino 
431e4b17023SJohn Marino   template<typename _Key, typename _Pair, typename _Hashtable>
432e4b17023SJohn Marino     typename _Map_base<_Key, _Pair, std::_Select1st<_Pair>,
433e4b17023SJohn Marino 		       true, _Hashtable>::mapped_type&
434e4b17023SJohn Marino     _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::
435e4b17023SJohn Marino     operator[](const _Key& __k)
436e4b17023SJohn Marino     {
437e4b17023SJohn Marino       _Hashtable* __h = static_cast<_Hashtable*>(this);
438e4b17023SJohn Marino       typename _Hashtable::_Hash_code_type __code = __h->_M_hash_code(__k);
439e4b17023SJohn Marino       std::size_t __n = __h->_M_bucket_index(__k, __code);
440e4b17023SJohn Marino 
441e4b17023SJohn Marino       typename _Hashtable::_Node* __p = __h->_M_find_node(__n, __k, __code);
442e4b17023SJohn Marino       if (!__p)
443e4b17023SJohn Marino 	return __h->_M_insert_bucket(std::make_pair(__k, mapped_type()),
444e4b17023SJohn Marino 				     __n, __code)->second;
445e4b17023SJohn Marino       return (__p->_M_v).second;
446e4b17023SJohn Marino     }
447e4b17023SJohn Marino 
448e4b17023SJohn Marino   template<typename _Key, typename _Pair, typename _Hashtable>
449e4b17023SJohn Marino     typename _Map_base<_Key, _Pair, std::_Select1st<_Pair>,
450e4b17023SJohn Marino 		       true, _Hashtable>::mapped_type&
451e4b17023SJohn Marino     _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::
452e4b17023SJohn Marino     operator[](_Key&& __k)
453e4b17023SJohn Marino     {
454e4b17023SJohn Marino       _Hashtable* __h = static_cast<_Hashtable*>(this);
455e4b17023SJohn Marino       typename _Hashtable::_Hash_code_type __code = __h->_M_hash_code(__k);
456e4b17023SJohn Marino       std::size_t __n = __h->_M_bucket_index(__k, __code);
457e4b17023SJohn Marino 
458e4b17023SJohn Marino       typename _Hashtable::_Node* __p = __h->_M_find_node(__n, __k, __code);
459e4b17023SJohn Marino       if (!__p)
460e4b17023SJohn Marino 	return __h->_M_insert_bucket(std::make_pair(std::move(__k),
461e4b17023SJohn Marino 						    mapped_type()),
462e4b17023SJohn Marino 				     __n, __code)->second;
463e4b17023SJohn Marino       return (__p->_M_v).second;
464e4b17023SJohn Marino     }
465e4b17023SJohn Marino 
466e4b17023SJohn Marino   template<typename _Key, typename _Pair, typename _Hashtable>
467e4b17023SJohn Marino     typename _Map_base<_Key, _Pair, std::_Select1st<_Pair>,
468e4b17023SJohn Marino 		       true, _Hashtable>::mapped_type&
469e4b17023SJohn Marino     _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::
470e4b17023SJohn Marino     at(const _Key& __k)
471e4b17023SJohn Marino     {
472e4b17023SJohn Marino       _Hashtable* __h = static_cast<_Hashtable*>(this);
473e4b17023SJohn Marino       typename _Hashtable::_Hash_code_type __code = __h->_M_hash_code(__k);
474e4b17023SJohn Marino       std::size_t __n = __h->_M_bucket_index(__k, __code);
475e4b17023SJohn Marino 
476e4b17023SJohn Marino       typename _Hashtable::_Node* __p = __h->_M_find_node(__n, __k, __code);
477e4b17023SJohn Marino       if (!__p)
478e4b17023SJohn Marino 	__throw_out_of_range(__N("_Map_base::at"));
479e4b17023SJohn Marino       return (__p->_M_v).second;
480e4b17023SJohn Marino     }
481e4b17023SJohn Marino 
482e4b17023SJohn Marino   template<typename _Key, typename _Pair, typename _Hashtable>
483e4b17023SJohn Marino     const typename _Map_base<_Key, _Pair, std::_Select1st<_Pair>,
484e4b17023SJohn Marino 			     true, _Hashtable>::mapped_type&
485e4b17023SJohn Marino     _Map_base<_Key, _Pair, std::_Select1st<_Pair>, true, _Hashtable>::
486e4b17023SJohn Marino     at(const _Key& __k) const
487e4b17023SJohn Marino     {
488e4b17023SJohn Marino       const _Hashtable* __h = static_cast<const _Hashtable*>(this);
489e4b17023SJohn Marino       typename _Hashtable::_Hash_code_type __code = __h->_M_hash_code(__k);
490e4b17023SJohn Marino       std::size_t __n = __h->_M_bucket_index(__k, __code);
491e4b17023SJohn Marino 
492e4b17023SJohn Marino       typename _Hashtable::_Node* __p = __h->_M_find_node(__n, __k, __code);
493e4b17023SJohn Marino       if (!__p)
494e4b17023SJohn Marino 	__throw_out_of_range(__N("_Map_base::at"));
495e4b17023SJohn Marino       return (__p->_M_v).second;
496e4b17023SJohn Marino     }
497e4b17023SJohn Marino 
498e4b17023SJohn Marino   // class template _Rehash_base.  Give hashtable the max_load_factor
499e4b17023SJohn Marino   // functions and reserve iff the rehash policy is _Prime_rehash_policy.
500e4b17023SJohn Marino   template<typename _RehashPolicy, typename _Hashtable>
501e4b17023SJohn Marino     struct _Rehash_base { };
502e4b17023SJohn Marino 
503e4b17023SJohn Marino   template<typename _Hashtable>
504e4b17023SJohn Marino     struct _Rehash_base<_Prime_rehash_policy, _Hashtable>
505e4b17023SJohn Marino     {
506e4b17023SJohn Marino       float
507e4b17023SJohn Marino       max_load_factor() const noexcept
508e4b17023SJohn Marino       {
509e4b17023SJohn Marino 	const _Hashtable* __this = static_cast<const _Hashtable*>(this);
510e4b17023SJohn Marino 	return __this->__rehash_policy().max_load_factor();
511e4b17023SJohn Marino       }
512e4b17023SJohn Marino 
513e4b17023SJohn Marino       void
514e4b17023SJohn Marino       max_load_factor(float __z)
515e4b17023SJohn Marino       {
516e4b17023SJohn Marino 	_Hashtable* __this = static_cast<_Hashtable*>(this);
517e4b17023SJohn Marino 	__this->__rehash_policy(_Prime_rehash_policy(__z));
518e4b17023SJohn Marino       }
519e4b17023SJohn Marino 
520e4b17023SJohn Marino       void
521e4b17023SJohn Marino       reserve(std::size_t __n)
522e4b17023SJohn Marino       {
523e4b17023SJohn Marino 	_Hashtable* __this = static_cast<_Hashtable*>(this);
524e4b17023SJohn Marino 	__this->rehash(__builtin_ceil(__n / max_load_factor()));
525e4b17023SJohn Marino       }
526e4b17023SJohn Marino     };
527e4b17023SJohn Marino 
528e4b17023SJohn Marino   // Helper class using EBO when it is not forbidden, type is not final,
529e4b17023SJohn Marino   // and when it worth it, type is empty.
530e4b17023SJohn Marino   template<int _Nm, typename _Tp,
531e4b17023SJohn Marino 	   bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)>
532e4b17023SJohn Marino     struct _Hashtable_ebo_helper;
533e4b17023SJohn Marino 
534e4b17023SJohn Marino   // Specialization using EBO.
535e4b17023SJohn Marino   template<int _Nm, typename _Tp>
536e4b17023SJohn Marino     struct _Hashtable_ebo_helper<_Nm, _Tp, true>
537e4b17023SJohn Marino     // See PR53067.
538e4b17023SJohn Marino     : public _Tp
539e4b17023SJohn Marino     {
540e4b17023SJohn Marino       _Hashtable_ebo_helper() = default;
541e4b17023SJohn Marino       _Hashtable_ebo_helper(const _Tp& __tp) : _Tp(__tp)
542e4b17023SJohn Marino       { }
543e4b17023SJohn Marino 
544e4b17023SJohn Marino       static const _Tp&
545e4b17023SJohn Marino       _S_cget(const _Hashtable_ebo_helper& __eboh)
546e4b17023SJohn Marino       { return static_cast<const _Tp&>(__eboh); }
547e4b17023SJohn Marino 
548e4b17023SJohn Marino       static _Tp&
549e4b17023SJohn Marino       _S_get(_Hashtable_ebo_helper& __eboh)
550e4b17023SJohn Marino       { return static_cast<_Tp&>(__eboh); }
551e4b17023SJohn Marino     };
552e4b17023SJohn Marino 
553e4b17023SJohn Marino   // Specialization not using EBO.
554e4b17023SJohn Marino   template<int _Nm, typename _Tp>
555e4b17023SJohn Marino     struct _Hashtable_ebo_helper<_Nm, _Tp, false>
556e4b17023SJohn Marino     {
557e4b17023SJohn Marino       _Hashtable_ebo_helper() = default;
558e4b17023SJohn Marino       _Hashtable_ebo_helper(const _Tp& __tp) : _M_tp(__tp)
559e4b17023SJohn Marino       { }
560e4b17023SJohn Marino 
561e4b17023SJohn Marino       static const _Tp&
562e4b17023SJohn Marino       _S_cget(const _Hashtable_ebo_helper& __eboh)
563e4b17023SJohn Marino       { return __eboh._M_tp; }
564e4b17023SJohn Marino 
565e4b17023SJohn Marino       static _Tp&
566e4b17023SJohn Marino       _S_get(_Hashtable_ebo_helper& __eboh)
567e4b17023SJohn Marino       { return __eboh._M_tp; }
568e4b17023SJohn Marino 
569e4b17023SJohn Marino     private:
570e4b17023SJohn Marino       _Tp _M_tp;
571e4b17023SJohn Marino     };
572e4b17023SJohn Marino 
573e4b17023SJohn Marino   // Class template _Hash_code_base.  Encapsulates two policy issues that
574e4b17023SJohn Marino   // aren't quite orthogonal.
575e4b17023SJohn Marino   //   (1) the difference between using a ranged hash function and using
576e4b17023SJohn Marino   //       the combination of a hash function and a range-hashing function.
577e4b17023SJohn Marino   //       In the former case we don't have such things as hash codes, so
578e4b17023SJohn Marino   //       we have a dummy type as placeholder.
579e4b17023SJohn Marino   //   (2) Whether or not we cache hash codes.  Caching hash codes is
580e4b17023SJohn Marino   //       meaningless if we have a ranged hash function.
581e4b17023SJohn Marino   // We also put the key extraction objects here, for convenience.
582e4b17023SJohn Marino   //
583e4b17023SJohn Marino   // Each specialization derives from one or more of the template parameters to
584e4b17023SJohn Marino   // benefit from Ebo. This is important as this type is inherited in some cases
585e4b17023SJohn Marino   // by the _Local_iterator_base type used to implement local_iterator and
586e4b17023SJohn Marino   // const_local_iterator. As with any iterator type we prefer to make it as
587e4b17023SJohn Marino   // small as possible.
588e4b17023SJohn Marino 
589e4b17023SJohn Marino   // Primary template: unused except as a hook for specializations.
590e4b17023SJohn Marino   template<typename _Key, typename _Value, typename _ExtractKey,
591e4b17023SJohn Marino 	   typename _H1, typename _H2, typename _Hash,
592e4b17023SJohn Marino 	   bool __cache_hash_code>
593e4b17023SJohn Marino     struct _Hash_code_base;
594e4b17023SJohn Marino 
595e4b17023SJohn Marino   // Specialization: ranged hash function, no caching hash codes.  H1
596e4b17023SJohn Marino   // and H2 are provided but ignored.  We define a dummy hash code type.
597e4b17023SJohn Marino   template<typename _Key, typename _Value, typename _ExtractKey,
598e4b17023SJohn Marino 	   typename _H1, typename _H2, typename _Hash>
599e4b17023SJohn Marino     struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, false>
600e4b17023SJohn Marino     // See PR53067.
601e4b17023SJohn Marino     : public  _Hashtable_ebo_helper<0, _ExtractKey>,
602e4b17023SJohn Marino       public  _Hashtable_ebo_helper<1, _Hash>
603e4b17023SJohn Marino     {
604e4b17023SJohn Marino     private:
605e4b17023SJohn Marino       typedef _Hashtable_ebo_helper<0, _ExtractKey> _EboExtractKey;
606e4b17023SJohn Marino       typedef _Hashtable_ebo_helper<1, _Hash> _EboHash;
607e4b17023SJohn Marino 
608e4b17023SJohn Marino     protected:
609e4b17023SJohn Marino       // We need the default constructor for the local iterators.
610e4b17023SJohn Marino       _Hash_code_base() = default;
611e4b17023SJohn Marino       _Hash_code_base(const _ExtractKey& __ex,
612e4b17023SJohn Marino 		      const _H1&, const _H2&, const _Hash& __h)
613e4b17023SJohn Marino 	: _EboExtractKey(__ex), _EboHash(__h) { }
614e4b17023SJohn Marino 
615e4b17023SJohn Marino       typedef void* _Hash_code_type;
616e4b17023SJohn Marino 
617e4b17023SJohn Marino       _Hash_code_type
618e4b17023SJohn Marino       _M_hash_code(const _Key& __key) const
619e4b17023SJohn Marino       { return 0; }
620e4b17023SJohn Marino 
621e4b17023SJohn Marino       std::size_t
622e4b17023SJohn Marino       _M_bucket_index(const _Key& __k, _Hash_code_type,
623e4b17023SJohn Marino 		      std::size_t __n) const
624e4b17023SJohn Marino       { return _M_ranged_hash()(__k, __n); }
625e4b17023SJohn Marino 
626e4b17023SJohn Marino       std::size_t
627e4b17023SJohn Marino       _M_bucket_index(const _Hash_node<_Value, false>* __p,
628e4b17023SJohn Marino 		      std::size_t __n) const
629e4b17023SJohn Marino       { return _M_ranged_hash()(_M_extract()(__p->_M_v), __n); }
630e4b17023SJohn Marino 
631e4b17023SJohn Marino       void
632e4b17023SJohn Marino       _M_store_code(_Hash_node<_Value, false>*, _Hash_code_type) const
633e4b17023SJohn Marino       { }
634e4b17023SJohn Marino 
635e4b17023SJohn Marino       void
636e4b17023SJohn Marino       _M_copy_code(_Hash_node<_Value, false>*,
637e4b17023SJohn Marino 		   const _Hash_node<_Value, false>*) const
638e4b17023SJohn Marino       { }
639e4b17023SJohn Marino 
640e4b17023SJohn Marino       void
641e4b17023SJohn Marino       _M_swap(_Hash_code_base& __x)
642e4b17023SJohn Marino       {
643e4b17023SJohn Marino 	std::swap(_M_extract(), __x._M_extract());
644e4b17023SJohn Marino 	std::swap(_M_ranged_hash(), __x._M_ranged_hash());
645e4b17023SJohn Marino       }
646e4b17023SJohn Marino 
647e4b17023SJohn Marino     protected:
648e4b17023SJohn Marino       const _ExtractKey&
649e4b17023SJohn Marino       _M_extract() const { return _EboExtractKey::_S_cget(*this); }
650e4b17023SJohn Marino       _ExtractKey&
651e4b17023SJohn Marino       _M_extract() { return _EboExtractKey::_S_get(*this); }
652e4b17023SJohn Marino       const _Hash&
653e4b17023SJohn Marino       _M_ranged_hash() const { return _EboHash::_S_cget(*this); }
654e4b17023SJohn Marino       _Hash&
655e4b17023SJohn Marino       _M_ranged_hash() { return _EboHash::_S_get(*this); }
656e4b17023SJohn Marino     };
657e4b17023SJohn Marino 
658e4b17023SJohn Marino   // No specialization for ranged hash function while caching hash codes.
659e4b17023SJohn Marino   // That combination is meaningless, and trying to do it is an error.
660e4b17023SJohn Marino 
661e4b17023SJohn Marino   // Specialization: ranged hash function, cache hash codes.  This
662e4b17023SJohn Marino   // combination is meaningless, so we provide only a declaration
663e4b17023SJohn Marino   // and no definition.
664e4b17023SJohn Marino   template<typename _Key, typename _Value, typename _ExtractKey,
665e4b17023SJohn Marino 	   typename _H1, typename _H2, typename _Hash>
666e4b17023SJohn Marino     struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, true>;
667e4b17023SJohn Marino 
668e4b17023SJohn Marino   // Specialization: hash function and range-hashing function, no
669e4b17023SJohn Marino   // caching of hash codes.
670e4b17023SJohn Marino   // Provides typedef and accessor required by TR1.
671e4b17023SJohn Marino   template<typename _Key, typename _Value, typename _ExtractKey,
672e4b17023SJohn Marino 	   typename _H1, typename _H2>
673e4b17023SJohn Marino     struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
674e4b17023SJohn Marino 			   _Default_ranged_hash, false>
675e4b17023SJohn Marino     // See PR53067.
676e4b17023SJohn Marino     : public  _Hashtable_ebo_helper<0, _ExtractKey>,
677e4b17023SJohn Marino       public  _Hashtable_ebo_helper<1, _H1>,
678e4b17023SJohn Marino       public  _Hashtable_ebo_helper<2, _H2>
679e4b17023SJohn Marino     {
680e4b17023SJohn Marino     private:
681e4b17023SJohn Marino       typedef _Hashtable_ebo_helper<0, _ExtractKey> _EboExtractKey;
682e4b17023SJohn Marino       typedef _Hashtable_ebo_helper<1, _H1> _EboH1;
683e4b17023SJohn Marino       typedef _Hashtable_ebo_helper<2, _H2> _EboH2;
684e4b17023SJohn Marino 
685e4b17023SJohn Marino     public:
686e4b17023SJohn Marino       typedef _H1 hasher;
687e4b17023SJohn Marino 
688e4b17023SJohn Marino       hasher
689e4b17023SJohn Marino       hash_function() const
690e4b17023SJohn Marino       { return _M_h1(); }
691e4b17023SJohn Marino 
692e4b17023SJohn Marino     protected:
693e4b17023SJohn Marino       // We need the default constructor for the local iterators.
694e4b17023SJohn Marino       _Hash_code_base() = default;
695e4b17023SJohn Marino       _Hash_code_base(const _ExtractKey& __ex,
696e4b17023SJohn Marino 		      const _H1& __h1, const _H2& __h2,
697e4b17023SJohn Marino 		      const _Default_ranged_hash&)
698e4b17023SJohn Marino       : _EboExtractKey(__ex), _EboH1(__h1), _EboH2(__h2) { }
699e4b17023SJohn Marino 
700e4b17023SJohn Marino       typedef std::size_t _Hash_code_type;
701e4b17023SJohn Marino 
702e4b17023SJohn Marino       _Hash_code_type
703e4b17023SJohn Marino       _M_hash_code(const _Key& __k) const
704e4b17023SJohn Marino       { return _M_h1()(__k); }
705e4b17023SJohn Marino 
706e4b17023SJohn Marino       std::size_t
707e4b17023SJohn Marino       _M_bucket_index(const _Key&, _Hash_code_type __c,
708e4b17023SJohn Marino 		      std::size_t __n) const
709e4b17023SJohn Marino       { return _M_h2()(__c, __n); }
710e4b17023SJohn Marino 
711e4b17023SJohn Marino       std::size_t
712e4b17023SJohn Marino       _M_bucket_index(const _Hash_node<_Value, false>* __p,
713e4b17023SJohn Marino 		      std::size_t __n) const
714e4b17023SJohn Marino       { return _M_h2()(_M_h1()(_M_extract()(__p->_M_v)), __n); }
715e4b17023SJohn Marino 
716e4b17023SJohn Marino       void
717e4b17023SJohn Marino       _M_store_code(_Hash_node<_Value, false>*, _Hash_code_type) const
718e4b17023SJohn Marino       { }
719e4b17023SJohn Marino 
720e4b17023SJohn Marino       void
721e4b17023SJohn Marino       _M_copy_code(_Hash_node<_Value, false>*,
722e4b17023SJohn Marino 		   const _Hash_node<_Value, false>*) const
723e4b17023SJohn Marino       { }
724e4b17023SJohn Marino 
725e4b17023SJohn Marino       void
726e4b17023SJohn Marino       _M_swap(_Hash_code_base& __x)
727e4b17023SJohn Marino       {
728e4b17023SJohn Marino 	std::swap(_M_extract(), __x._M_extract());
729e4b17023SJohn Marino 	std::swap(_M_h1(), __x._M_h1());
730e4b17023SJohn Marino 	std::swap(_M_h2(), __x._M_h2());
731e4b17023SJohn Marino       }
732e4b17023SJohn Marino 
733e4b17023SJohn Marino     protected:
734e4b17023SJohn Marino       const _ExtractKey&
735e4b17023SJohn Marino       _M_extract() const { return _EboExtractKey::_S_cget(*this); }
736e4b17023SJohn Marino       _ExtractKey&
737e4b17023SJohn Marino       _M_extract() { return _EboExtractKey::_S_get(*this); }
738e4b17023SJohn Marino       const _H1&
739e4b17023SJohn Marino       _M_h1() const { return _EboH1::_S_cget(*this); }
740e4b17023SJohn Marino       _H1&
741e4b17023SJohn Marino       _M_h1() { return _EboH1::_S_get(*this); }
742e4b17023SJohn Marino       const _H2&
743e4b17023SJohn Marino       _M_h2() const { return _EboH2::_S_cget(*this); }
744e4b17023SJohn Marino       _H2&
745e4b17023SJohn Marino       _M_h2() { return _EboH2::_S_get(*this); }
746e4b17023SJohn Marino     };
747e4b17023SJohn Marino 
748e4b17023SJohn Marino   // Specialization: hash function and range-hashing function,
749e4b17023SJohn Marino   // caching hash codes.  H is provided but ignored.  Provides
750e4b17023SJohn Marino   // typedef and accessor required by TR1.
751e4b17023SJohn Marino   template<typename _Key, typename _Value, typename _ExtractKey,
752e4b17023SJohn Marino 	   typename _H1, typename _H2>
753e4b17023SJohn Marino     struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
754e4b17023SJohn Marino 			   _Default_ranged_hash, true>
755e4b17023SJohn Marino     // See PR53067.
756e4b17023SJohn Marino     : public  _Hashtable_ebo_helper<0, _ExtractKey>,
757e4b17023SJohn Marino       public  _Hashtable_ebo_helper<1, _H1>,
758e4b17023SJohn Marino       public  _Hashtable_ebo_helper<2, _H2>
759e4b17023SJohn Marino     {
760e4b17023SJohn Marino     private:
761e4b17023SJohn Marino       typedef _Hashtable_ebo_helper<0, _ExtractKey> _EboExtractKey;
762e4b17023SJohn Marino       typedef _Hashtable_ebo_helper<1, _H1> _EboH1;
763e4b17023SJohn Marino       typedef _Hashtable_ebo_helper<2, _H2> _EboH2;
764e4b17023SJohn Marino 
765e4b17023SJohn Marino     public:
766e4b17023SJohn Marino       typedef _H1 hasher;
767e4b17023SJohn Marino 
768e4b17023SJohn Marino       hasher
769e4b17023SJohn Marino       hash_function() const
770e4b17023SJohn Marino       { return _M_h1(); }
771e4b17023SJohn Marino 
772e4b17023SJohn Marino     protected:
773e4b17023SJohn Marino       _Hash_code_base(const _ExtractKey& __ex,
774e4b17023SJohn Marino 		      const _H1& __h1, const _H2& __h2,
775e4b17023SJohn Marino 		      const _Default_ranged_hash&)
776e4b17023SJohn Marino       : _EboExtractKey(__ex), _EboH1(__h1), _EboH2(__h2) { }
777e4b17023SJohn Marino 
778e4b17023SJohn Marino       typedef std::size_t _Hash_code_type;
779e4b17023SJohn Marino 
780e4b17023SJohn Marino       _Hash_code_type
781e4b17023SJohn Marino       _M_hash_code(const _Key& __k) const
782e4b17023SJohn Marino       { return _M_h1()(__k); }
783e4b17023SJohn Marino 
784e4b17023SJohn Marino       std::size_t
785e4b17023SJohn Marino       _M_bucket_index(const _Key&, _Hash_code_type __c,
786e4b17023SJohn Marino 		      std::size_t __n) const
787e4b17023SJohn Marino       { return _M_h2()(__c, __n); }
788e4b17023SJohn Marino 
789e4b17023SJohn Marino       std::size_t
790e4b17023SJohn Marino       _M_bucket_index(const _Hash_node<_Value, true>* __p,
791e4b17023SJohn Marino 		      std::size_t __n) const
792e4b17023SJohn Marino       { return _M_h2()(__p->_M_hash_code, __n); }
793e4b17023SJohn Marino 
794e4b17023SJohn Marino       void
795e4b17023SJohn Marino       _M_store_code(_Hash_node<_Value, true>* __n, _Hash_code_type __c) const
796e4b17023SJohn Marino       { __n->_M_hash_code = __c; }
797e4b17023SJohn Marino 
798e4b17023SJohn Marino       void
799e4b17023SJohn Marino       _M_copy_code(_Hash_node<_Value, true>* __to,
800e4b17023SJohn Marino 		   const _Hash_node<_Value, true>* __from) const
801e4b17023SJohn Marino       { __to->_M_hash_code = __from->_M_hash_code; }
802e4b17023SJohn Marino 
803e4b17023SJohn Marino       void
804e4b17023SJohn Marino       _M_swap(_Hash_code_base& __x)
805e4b17023SJohn Marino       {
806e4b17023SJohn Marino 	std::swap(_M_extract(), __x._M_extract());
807e4b17023SJohn Marino 	std::swap(_M_h1(), __x._M_h1());
808e4b17023SJohn Marino 	std::swap(_M_h2(), __x._M_h2());
809e4b17023SJohn Marino       }
810e4b17023SJohn Marino 
811e4b17023SJohn Marino     protected:
812e4b17023SJohn Marino       const _ExtractKey&
813e4b17023SJohn Marino       _M_extract() const { return _EboExtractKey::_S_cget(*this); }
814e4b17023SJohn Marino       _ExtractKey&
815e4b17023SJohn Marino       _M_extract() { return _EboExtractKey::_S_get(*this); }
816e4b17023SJohn Marino       const _H1&
817e4b17023SJohn Marino       _M_h1() const { return _EboH1::_S_cget(*this); }
818e4b17023SJohn Marino       _H1&
819e4b17023SJohn Marino       _M_h1() { return _EboH1::_S_get(*this); }
820e4b17023SJohn Marino       const _H2&
821e4b17023SJohn Marino       _M_h2() const { return _EboH2::_S_cget(*this); }
822e4b17023SJohn Marino       _H2&
823e4b17023SJohn Marino       _M_h2() { return _EboH2::_S_get(*this); }
824e4b17023SJohn Marino     };
825e4b17023SJohn Marino 
826e4b17023SJohn Marino   template <typename _Key, typename _Value, typename _ExtractKey,
827e4b17023SJohn Marino 	    typename _Equal, typename _HashCodeType,
828e4b17023SJohn Marino 	    bool __cache_hash_code>
829e4b17023SJohn Marino   struct _Equal_helper;
830e4b17023SJohn Marino 
831e4b17023SJohn Marino   template<typename _Key, typename _Value, typename _ExtractKey,
832e4b17023SJohn Marino 	   typename _Equal, typename _HashCodeType>
833e4b17023SJohn Marino   struct _Equal_helper<_Key, _Value, _ExtractKey, _Equal, _HashCodeType, true>
834e4b17023SJohn Marino   {
835e4b17023SJohn Marino     static bool
836e4b17023SJohn Marino     _S_equals(const _Equal& __eq, const _ExtractKey& __extract,
837e4b17023SJohn Marino 	      const _Key& __k, _HashCodeType __c,
838e4b17023SJohn Marino 	      _Hash_node<_Value, true>* __n)
839e4b17023SJohn Marino     { return __c == __n->_M_hash_code
840e4b17023SJohn Marino 	     && __eq(__k, __extract(__n->_M_v)); }
841e4b17023SJohn Marino   };
842e4b17023SJohn Marino 
843e4b17023SJohn Marino   template<typename _Key, typename _Value, typename _ExtractKey,
844e4b17023SJohn Marino 	   typename _Equal, typename _HashCodeType>
845e4b17023SJohn Marino   struct _Equal_helper<_Key, _Value, _ExtractKey, _Equal, _HashCodeType, false>
846e4b17023SJohn Marino   {
847e4b17023SJohn Marino     static bool
848e4b17023SJohn Marino     _S_equals(const _Equal& __eq, const _ExtractKey& __extract,
849e4b17023SJohn Marino 	      const _Key& __k, _HashCodeType,
850e4b17023SJohn Marino 	      _Hash_node<_Value, false>* __n)
851e4b17023SJohn Marino     { return __eq(__k, __extract(__n->_M_v)); }
852e4b17023SJohn Marino   };
853e4b17023SJohn Marino 
854e4b17023SJohn Marino   // Helper class adding management of _Equal functor to _Hash_code_base
855e4b17023SJohn Marino   // type.
856e4b17023SJohn Marino   template<typename _Key, typename _Value,
857e4b17023SJohn Marino 	   typename _ExtractKey, typename _Equal,
858e4b17023SJohn Marino 	   typename _H1, typename _H2, typename _Hash,
859e4b17023SJohn Marino 	   bool __cache_hash_code>
860e4b17023SJohn Marino   struct _Hashtable_base
861e4b17023SJohn Marino   // See PR53067.
862e4b17023SJohn Marino   : public  _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash,
863e4b17023SJohn Marino 			    __cache_hash_code>,
864e4b17023SJohn Marino     public _Hashtable_ebo_helper<0, _Equal>
865e4b17023SJohn Marino   {
866e4b17023SJohn Marino   private:
867e4b17023SJohn Marino     typedef _Hashtable_ebo_helper<0, _Equal> _EboEqual;
868e4b17023SJohn Marino 
869e4b17023SJohn Marino   protected:
870e4b17023SJohn Marino     typedef _Hash_code_base<_Key, _Value, _ExtractKey,
871e4b17023SJohn Marino 			    _H1, _H2, _Hash, __cache_hash_code> _HCBase;
872e4b17023SJohn Marino     typedef typename _HCBase::_Hash_code_type _Hash_code_type;
873e4b17023SJohn Marino 
874e4b17023SJohn Marino     _Hashtable_base(const _ExtractKey& __ex,
875e4b17023SJohn Marino 		    const _H1& __h1, const _H2& __h2,
876e4b17023SJohn Marino 		    const _Hash& __hash, const _Equal& __eq)
877e4b17023SJohn Marino       : _HCBase(__ex, __h1, __h2, __hash), _EboEqual(__eq) { }
878e4b17023SJohn Marino 
879e4b17023SJohn Marino     bool
880e4b17023SJohn Marino     _M_equals(const _Key& __k, _Hash_code_type __c,
881e4b17023SJohn Marino 	      _Hash_node<_Value, __cache_hash_code>* __n) const
882e4b17023SJohn Marino     {
883e4b17023SJohn Marino       typedef _Equal_helper<_Key, _Value, _ExtractKey,
884e4b17023SJohn Marino 			   _Equal, _Hash_code_type,
885e4b17023SJohn Marino 			   __cache_hash_code> _EqualHelper;
886e4b17023SJohn Marino       return _EqualHelper::_S_equals(_M_eq(), this->_M_extract(),
887e4b17023SJohn Marino 				     __k, __c, __n);
888e4b17023SJohn Marino     }
889e4b17023SJohn Marino 
890e4b17023SJohn Marino     void
891e4b17023SJohn Marino     _M_swap(_Hashtable_base& __x)
892e4b17023SJohn Marino     {
893e4b17023SJohn Marino       _HCBase::_M_swap(__x);
894e4b17023SJohn Marino       std::swap(_M_eq(), __x._M_eq());
895e4b17023SJohn Marino     }
896e4b17023SJohn Marino 
897e4b17023SJohn Marino   protected:
898e4b17023SJohn Marino     const _Equal&
899e4b17023SJohn Marino     _M_eq() const { return _EboEqual::_S_cget(*this); }
900e4b17023SJohn Marino     _Equal&
901e4b17023SJohn Marino     _M_eq() { return _EboEqual::_S_get(*this); }
902e4b17023SJohn Marino   };
903e4b17023SJohn Marino 
904e4b17023SJohn Marino   // Local iterators, used to iterate within a bucket but not between
905e4b17023SJohn Marino   // buckets.
906e4b17023SJohn Marino   template<typename _Key, typename _Value, typename _ExtractKey,
907e4b17023SJohn Marino 	   typename _H1, typename _H2, typename _Hash,
908e4b17023SJohn Marino 	   bool __cache_hash_code>
909e4b17023SJohn Marino     struct _Local_iterator_base;
910e4b17023SJohn Marino 
911e4b17023SJohn Marino   template<typename _Key, typename _Value, typename _ExtractKey,
912e4b17023SJohn Marino 	   typename _H1, typename _H2, typename _Hash>
913e4b17023SJohn Marino     struct _Local_iterator_base<_Key, _Value, _ExtractKey,
914e4b17023SJohn Marino 				_H1, _H2, _Hash, true>
915e4b17023SJohn Marino     // See PR53067.
916e4b17023SJohn Marino     : public _H2
917e4b17023SJohn Marino     {
918e4b17023SJohn Marino       _Local_iterator_base() = default;
919e4b17023SJohn Marino       _Local_iterator_base(_Hash_node<_Value, true>* __p,
920e4b17023SJohn Marino 			   std::size_t __bkt, std::size_t __bkt_count)
921e4b17023SJohn Marino       : _M_cur(__p), _M_bucket(__bkt), _M_bucket_count(__bkt_count) { }
922e4b17023SJohn Marino 
923e4b17023SJohn Marino       void
924e4b17023SJohn Marino       _M_incr()
925e4b17023SJohn Marino       {
926e4b17023SJohn Marino 	_M_cur = _M_cur->_M_next();
927e4b17023SJohn Marino 	if (_M_cur)
928e4b17023SJohn Marino 	  {
929e4b17023SJohn Marino 	    std::size_t __bkt = _M_h2()(_M_cur->_M_hash_code, _M_bucket_count);
930e4b17023SJohn Marino 	    if (__bkt != _M_bucket)
931e4b17023SJohn Marino 	      _M_cur = nullptr;
932e4b17023SJohn Marino 	  }
933e4b17023SJohn Marino       }
934e4b17023SJohn Marino 
935e4b17023SJohn Marino       const _H2& _M_h2() const
936e4b17023SJohn Marino       { return *this; }
937e4b17023SJohn Marino 
938e4b17023SJohn Marino       _Hash_node<_Value, true>*  _M_cur;
939e4b17023SJohn Marino       std::size_t _M_bucket;
940e4b17023SJohn Marino       std::size_t _M_bucket_count;
941e4b17023SJohn Marino     };
942e4b17023SJohn Marino 
943e4b17023SJohn Marino   template<typename _Key, typename _Value, typename _ExtractKey,
944e4b17023SJohn Marino 	   typename _H1, typename _H2, typename _Hash>
945e4b17023SJohn Marino     struct _Local_iterator_base<_Key, _Value, _ExtractKey,
946e4b17023SJohn Marino 				_H1, _H2, _Hash, false>
947e4b17023SJohn Marino     // See PR53067.
948e4b17023SJohn Marino     : public _Hash_code_base<_Key, _Value, _ExtractKey,
949e4b17023SJohn Marino 			     _H1, _H2, _Hash, false>
950e4b17023SJohn Marino     {
951e4b17023SJohn Marino       _Local_iterator_base() = default;
952e4b17023SJohn Marino       _Local_iterator_base(_Hash_node<_Value, false>* __p,
953e4b17023SJohn Marino 			   std::size_t __bkt, std::size_t __bkt_count)
954e4b17023SJohn Marino       : _M_cur(__p), _M_bucket(__bkt), _M_bucket_count(__bkt_count) { }
955e4b17023SJohn Marino 
956e4b17023SJohn Marino       void
957e4b17023SJohn Marino       _M_incr()
958e4b17023SJohn Marino       {
959e4b17023SJohn Marino 	_M_cur = _M_cur->_M_next();
960e4b17023SJohn Marino 	if (_M_cur)
961e4b17023SJohn Marino 	  {
962e4b17023SJohn Marino 	    std::size_t __bkt = this->_M_bucket_index(_M_cur, _M_bucket_count);
963e4b17023SJohn Marino 	    if (__bkt != _M_bucket)
964e4b17023SJohn Marino 	      _M_cur = nullptr;
965e4b17023SJohn Marino 	  }
966e4b17023SJohn Marino       }
967e4b17023SJohn Marino 
968e4b17023SJohn Marino       _Hash_node<_Value, false>*  _M_cur;
969e4b17023SJohn Marino       std::size_t _M_bucket;
970e4b17023SJohn Marino       std::size_t _M_bucket_count;
971e4b17023SJohn Marino     };
972e4b17023SJohn Marino 
973e4b17023SJohn Marino   template<typename _Key, typename _Value, typename _ExtractKey,
974e4b17023SJohn Marino 	   typename _H1, typename _H2, typename _Hash, bool __cache>
975e4b17023SJohn Marino     inline bool
976e4b17023SJohn Marino     operator==(const _Local_iterator_base<_Key, _Value, _ExtractKey,
977e4b17023SJohn Marino 					  _H1, _H2, _Hash, __cache>& __x,
978e4b17023SJohn Marino 	       const _Local_iterator_base<_Key, _Value, _ExtractKey,
979e4b17023SJohn Marino 					  _H1, _H2, _Hash, __cache>& __y)
980e4b17023SJohn Marino     { return __x._M_cur == __y._M_cur; }
981e4b17023SJohn Marino 
982e4b17023SJohn Marino   template<typename _Key, typename _Value, typename _ExtractKey,
983e4b17023SJohn Marino 	   typename _H1, typename _H2, typename _Hash, bool __cache>
984e4b17023SJohn Marino     inline bool
985e4b17023SJohn Marino     operator!=(const _Local_iterator_base<_Key, _Value, _ExtractKey,
986e4b17023SJohn Marino 					  _H1, _H2, _Hash, __cache>& __x,
987e4b17023SJohn Marino 	       const _Local_iterator_base<_Key, _Value, _ExtractKey,
988e4b17023SJohn Marino 					  _H1, _H2, _Hash, __cache>& __y)
989e4b17023SJohn Marino     { return __x._M_cur != __y._M_cur; }
990e4b17023SJohn Marino 
991e4b17023SJohn Marino   template<typename _Key, typename _Value, typename _ExtractKey,
992e4b17023SJohn Marino 	   typename _H1, typename _H2, typename _Hash,
993e4b17023SJohn Marino 	   bool __constant_iterators, bool __cache>
994e4b17023SJohn Marino     struct _Local_iterator
995e4b17023SJohn Marino     : public _Local_iterator_base<_Key, _Value, _ExtractKey,
996e4b17023SJohn Marino 				  _H1, _H2, _Hash, __cache>
997e4b17023SJohn Marino     {
998e4b17023SJohn Marino       typedef _Value                                   value_type;
999e4b17023SJohn Marino       typedef typename std::conditional<__constant_iterators,
1000e4b17023SJohn Marino 					const _Value*, _Value*>::type
1001e4b17023SJohn Marino 						       pointer;
1002e4b17023SJohn Marino       typedef typename std::conditional<__constant_iterators,
1003e4b17023SJohn Marino 					const _Value&, _Value&>::type
1004e4b17023SJohn Marino 						       reference;
1005e4b17023SJohn Marino       typedef std::ptrdiff_t                           difference_type;
1006e4b17023SJohn Marino       typedef std::forward_iterator_tag                iterator_category;
1007e4b17023SJohn Marino 
1008e4b17023SJohn Marino       _Local_iterator() = default;
1009e4b17023SJohn Marino 
1010e4b17023SJohn Marino       explicit
1011e4b17023SJohn Marino       _Local_iterator(_Hash_node<_Value, __cache>* __p,
1012e4b17023SJohn Marino 		      std::size_t __bkt, std::size_t __bkt_count)
1013e4b17023SJohn Marino       : _Local_iterator_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash,
1014e4b17023SJohn Marino 			     __cache>(__p, __bkt, __bkt_count)
1015e4b17023SJohn Marino       { }
1016e4b17023SJohn Marino 
1017e4b17023SJohn Marino       reference
1018e4b17023SJohn Marino       operator*() const
1019e4b17023SJohn Marino       { return this->_M_cur->_M_v; }
1020e4b17023SJohn Marino 
1021e4b17023SJohn Marino       pointer
1022e4b17023SJohn Marino       operator->() const
1023e4b17023SJohn Marino       { return std::__addressof(this->_M_cur->_M_v); }
1024e4b17023SJohn Marino 
1025e4b17023SJohn Marino       _Local_iterator&
1026e4b17023SJohn Marino       operator++()
1027e4b17023SJohn Marino       {
1028e4b17023SJohn Marino 	this->_M_incr();
1029e4b17023SJohn Marino 	return *this;
1030e4b17023SJohn Marino       }
1031e4b17023SJohn Marino 
1032e4b17023SJohn Marino       _Local_iterator
1033e4b17023SJohn Marino       operator++(int)
1034e4b17023SJohn Marino       {
1035e4b17023SJohn Marino 	_Local_iterator __tmp(*this);
1036e4b17023SJohn Marino 	this->_M_incr();
1037e4b17023SJohn Marino 	return __tmp;
1038e4b17023SJohn Marino       }
1039e4b17023SJohn Marino     };
1040e4b17023SJohn Marino 
1041e4b17023SJohn Marino   template<typename _Key, typename _Value, typename _ExtractKey,
1042e4b17023SJohn Marino 	   typename _H1, typename _H2, typename _Hash,
1043e4b17023SJohn Marino 	   bool __constant_iterators, bool __cache>
1044e4b17023SJohn Marino     struct _Local_const_iterator
1045e4b17023SJohn Marino     : public _Local_iterator_base<_Key, _Value, _ExtractKey,
1046e4b17023SJohn Marino 				  _H1, _H2, _Hash, __cache>
1047e4b17023SJohn Marino     {
1048e4b17023SJohn Marino       typedef _Value                                   value_type;
1049e4b17023SJohn Marino       typedef const _Value*                            pointer;
1050e4b17023SJohn Marino       typedef const _Value&                            reference;
1051e4b17023SJohn Marino       typedef std::ptrdiff_t                           difference_type;
1052e4b17023SJohn Marino       typedef std::forward_iterator_tag                iterator_category;
1053e4b17023SJohn Marino 
1054e4b17023SJohn Marino       _Local_const_iterator() = default;
1055e4b17023SJohn Marino 
1056e4b17023SJohn Marino       explicit
1057e4b17023SJohn Marino       _Local_const_iterator(_Hash_node<_Value, __cache>* __p,
1058e4b17023SJohn Marino 			    std::size_t __bkt, std::size_t __bkt_count)
1059e4b17023SJohn Marino       : _Local_iterator_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash,
1060e4b17023SJohn Marino 			     __cache>(__p, __bkt, __bkt_count)
1061e4b17023SJohn Marino       { }
1062e4b17023SJohn Marino 
1063e4b17023SJohn Marino       _Local_const_iterator(const _Local_iterator<_Key, _Value, _ExtractKey,
1064e4b17023SJohn Marino 						  _H1, _H2, _Hash,
1065e4b17023SJohn Marino 						  __constant_iterators,
1066e4b17023SJohn Marino 						  __cache>& __x)
1067e4b17023SJohn Marino       : _Local_iterator_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash,
1068e4b17023SJohn Marino 			     __cache>(__x._M_cur, __x._M_bucket,
1069e4b17023SJohn Marino 				      __x._M_bucket_count)
1070e4b17023SJohn Marino       { }
1071e4b17023SJohn Marino 
1072e4b17023SJohn Marino       reference
1073e4b17023SJohn Marino       operator*() const
1074e4b17023SJohn Marino       { return this->_M_cur->_M_v; }
1075e4b17023SJohn Marino 
1076e4b17023SJohn Marino       pointer
1077e4b17023SJohn Marino       operator->() const
1078e4b17023SJohn Marino       { return std::__addressof(this->_M_cur->_M_v); }
1079e4b17023SJohn Marino 
1080e4b17023SJohn Marino       _Local_const_iterator&
1081e4b17023SJohn Marino       operator++()
1082e4b17023SJohn Marino       {
1083e4b17023SJohn Marino 	this->_M_incr();
1084e4b17023SJohn Marino 	return *this;
1085e4b17023SJohn Marino       }
1086e4b17023SJohn Marino 
1087e4b17023SJohn Marino       _Local_const_iterator
1088e4b17023SJohn Marino       operator++(int)
1089e4b17023SJohn Marino       {
1090e4b17023SJohn Marino 	_Local_const_iterator __tmp(*this);
1091e4b17023SJohn Marino 	this->_M_incr();
1092e4b17023SJohn Marino 	return __tmp;
1093e4b17023SJohn Marino       }
1094e4b17023SJohn Marino     };
1095e4b17023SJohn Marino 
1096e4b17023SJohn Marino 
1097e4b17023SJohn Marino   // Class template _Equality_base.  This is for implementing equality
1098e4b17023SJohn Marino   // comparison for unordered containers, per N3068, by John Lakos and
1099e4b17023SJohn Marino   // Pablo Halpern.  Algorithmically, we follow closely the reference
1100e4b17023SJohn Marino   // implementations therein.
1101e4b17023SJohn Marino   template<typename _ExtractKey, bool __unique_keys,
1102e4b17023SJohn Marino 	   typename _Hashtable>
1103e4b17023SJohn Marino     struct _Equality_base;
1104e4b17023SJohn Marino 
1105e4b17023SJohn Marino   template<typename _ExtractKey, typename _Hashtable>
1106e4b17023SJohn Marino     struct _Equality_base<_ExtractKey, true, _Hashtable>
1107e4b17023SJohn Marino     {
1108e4b17023SJohn Marino       bool _M_equal(const _Hashtable&) const;
1109e4b17023SJohn Marino     };
1110e4b17023SJohn Marino 
1111e4b17023SJohn Marino   template<typename _ExtractKey, typename _Hashtable>
1112e4b17023SJohn Marino     bool
1113e4b17023SJohn Marino     _Equality_base<_ExtractKey, true, _Hashtable>::
1114e4b17023SJohn Marino     _M_equal(const _Hashtable& __other) const
1115e4b17023SJohn Marino     {
1116e4b17023SJohn Marino       const _Hashtable* __this = static_cast<const _Hashtable*>(this);
1117e4b17023SJohn Marino 
1118e4b17023SJohn Marino       if (__this->size() != __other.size())
1119e4b17023SJohn Marino 	return false;
1120e4b17023SJohn Marino 
1121e4b17023SJohn Marino       for (auto __itx = __this->begin(); __itx != __this->end(); ++__itx)
1122e4b17023SJohn Marino 	{
1123e4b17023SJohn Marino 	  const auto __ity = __other.find(_ExtractKey()(*__itx));
1124e4b17023SJohn Marino 	  if (__ity == __other.end() || !bool(*__ity == *__itx))
1125e4b17023SJohn Marino 	    return false;
1126e4b17023SJohn Marino 	}
1127e4b17023SJohn Marino       return true;
1128e4b17023SJohn Marino     }
1129e4b17023SJohn Marino 
1130e4b17023SJohn Marino   template<typename _ExtractKey, typename _Hashtable>
1131e4b17023SJohn Marino     struct _Equality_base<_ExtractKey, false, _Hashtable>
1132e4b17023SJohn Marino     {
1133e4b17023SJohn Marino       bool _M_equal(const _Hashtable&) const;
1134e4b17023SJohn Marino 
1135e4b17023SJohn Marino     private:
1136e4b17023SJohn Marino       template<typename _Uiterator>
1137e4b17023SJohn Marino 	static bool
1138e4b17023SJohn Marino 	_S_is_permutation(_Uiterator, _Uiterator, _Uiterator);
1139e4b17023SJohn Marino     };
1140e4b17023SJohn Marino 
1141e4b17023SJohn Marino   // See std::is_permutation in N3068.
1142e4b17023SJohn Marino   template<typename _ExtractKey, typename _Hashtable>
1143e4b17023SJohn Marino     template<typename _Uiterator>
1144e4b17023SJohn Marino       bool
1145e4b17023SJohn Marino       _Equality_base<_ExtractKey, false, _Hashtable>::
1146e4b17023SJohn Marino       _S_is_permutation(_Uiterator __first1, _Uiterator __last1,
1147e4b17023SJohn Marino 			_Uiterator __first2)
1148e4b17023SJohn Marino       {
1149e4b17023SJohn Marino 	for (; __first1 != __last1; ++__first1, ++__first2)
1150e4b17023SJohn Marino 	  if (!(*__first1 == *__first2))
1151e4b17023SJohn Marino 	    break;
1152e4b17023SJohn Marino 
1153e4b17023SJohn Marino 	if (__first1 == __last1)
1154e4b17023SJohn Marino 	  return true;
1155e4b17023SJohn Marino 
1156e4b17023SJohn Marino 	_Uiterator __last2 = __first2;
1157e4b17023SJohn Marino 	std::advance(__last2, std::distance(__first1, __last1));
1158e4b17023SJohn Marino 
1159e4b17023SJohn Marino 	for (_Uiterator __it1 = __first1; __it1 != __last1; ++__it1)
1160e4b17023SJohn Marino 	  {
1161e4b17023SJohn Marino 	    _Uiterator __tmp =  __first1;
1162e4b17023SJohn Marino 	    while (__tmp != __it1 && !bool(*__tmp == *__it1))
1163e4b17023SJohn Marino 	      ++__tmp;
1164e4b17023SJohn Marino 
1165e4b17023SJohn Marino 	    // We've seen this one before.
1166e4b17023SJohn Marino 	    if (__tmp != __it1)
1167e4b17023SJohn Marino 	      continue;
1168e4b17023SJohn Marino 
1169e4b17023SJohn Marino 	    std::ptrdiff_t __n2 = 0;
1170e4b17023SJohn Marino 	    for (__tmp = __first2; __tmp != __last2; ++__tmp)
1171e4b17023SJohn Marino 	      if (*__tmp == *__it1)
1172e4b17023SJohn Marino 		++__n2;
1173e4b17023SJohn Marino 
1174e4b17023SJohn Marino 	    if (!__n2)
1175e4b17023SJohn Marino 	      return false;
1176e4b17023SJohn Marino 
1177e4b17023SJohn Marino 	    std::ptrdiff_t __n1 = 0;
1178e4b17023SJohn Marino 	    for (__tmp = __it1; __tmp != __last1; ++__tmp)
1179e4b17023SJohn Marino 	      if (*__tmp == *__it1)
1180e4b17023SJohn Marino 		++__n1;
1181e4b17023SJohn Marino 
1182e4b17023SJohn Marino 	    if (__n1 != __n2)
1183e4b17023SJohn Marino 	      return false;
1184e4b17023SJohn Marino 	  }
1185e4b17023SJohn Marino 	return true;
1186e4b17023SJohn Marino       }
1187e4b17023SJohn Marino 
1188e4b17023SJohn Marino   template<typename _ExtractKey, typename _Hashtable>
1189e4b17023SJohn Marino     bool
1190e4b17023SJohn Marino     _Equality_base<_ExtractKey, false, _Hashtable>::
1191e4b17023SJohn Marino     _M_equal(const _Hashtable& __other) const
1192e4b17023SJohn Marino     {
1193e4b17023SJohn Marino       const _Hashtable* __this = static_cast<const _Hashtable*>(this);
1194e4b17023SJohn Marino 
1195e4b17023SJohn Marino       if (__this->size() != __other.size())
1196e4b17023SJohn Marino 	return false;
1197e4b17023SJohn Marino 
1198e4b17023SJohn Marino       for (auto __itx = __this->begin(); __itx != __this->end();)
1199e4b17023SJohn Marino 	{
1200e4b17023SJohn Marino 	  const auto __xrange = __this->equal_range(_ExtractKey()(*__itx));
1201e4b17023SJohn Marino 	  const auto __yrange = __other.equal_range(_ExtractKey()(*__itx));
1202e4b17023SJohn Marino 
1203e4b17023SJohn Marino 	  if (std::distance(__xrange.first, __xrange.second)
1204e4b17023SJohn Marino 	      != std::distance(__yrange.first, __yrange.second))
1205e4b17023SJohn Marino 	    return false;
1206e4b17023SJohn Marino 
1207e4b17023SJohn Marino 	  if (!_S_is_permutation(__xrange.first,
1208e4b17023SJohn Marino 				 __xrange.second,
1209e4b17023SJohn Marino 				 __yrange.first))
1210e4b17023SJohn Marino 	    return false;
1211e4b17023SJohn Marino 
1212e4b17023SJohn Marino 	  __itx = __xrange.second;
1213e4b17023SJohn Marino 	}
1214e4b17023SJohn Marino       return true;
1215e4b17023SJohn Marino     }
1216e4b17023SJohn Marino 
1217e4b17023SJohn Marino _GLIBCXX_END_NAMESPACE_VERSION
1218e4b17023SJohn Marino } // namespace __detail
1219e4b17023SJohn Marino } // namespace std
1220e4b17023SJohn Marino 
1221e4b17023SJohn Marino #endif // _HASHTABLE_POLICY_H
1222