libstdc++

hashtable_policy.h
Go to the documentation of this file.
1 // Internal policy header for unordered_set and unordered_map -*- C++ -*-
2
3 // Copyright (C) 2010-2013 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24
25 /** @file bits/hashtable_policy.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly.
28 * @headername{unordered_map,unordered_set}
29 */
30
31 #ifndef _HASHTABLE_POLICY_H
32 #define _HASHTABLE_POLICY_H 1
33
34 namespace std _GLIBCXX_VISIBILITY(default)
35 {
36 _GLIBCXX_BEGIN_NAMESPACE_VERSION
37
38 template<typename _Key, typename _Value, typename _Alloc,
39 typename _ExtractKey, typename _Equal,
40 typename _H1, typename _H2, typename _Hash,
41 typename _RehashPolicy, typename _Traits>
42 class _Hashtable;
43
44 _GLIBCXX_END_NAMESPACE_VERSION
45
46 namespace __detail
47 {
48 _GLIBCXX_BEGIN_NAMESPACE_VERSION
49
50 /**
51 * @defgroup hashtable-detail Base and Implementation Classes
52 * @ingroup unordered_associative_containers
53 * @{
54 */
55 template<typename _Key, typename _Value,
56 typename _ExtractKey, typename _Equal,
57 typename _H1, typename _H2, typename _Hash, typename _Traits>
58 struct _Hashtable_base;
59
60 // Helper function: return distance(first, last) for forward
61 // iterators, or 0 for input iterators.
62 template<class _Iterator>
63 inline typename std::iterator_traits<_Iterator>::difference_type
64 __distance_fw(_Iterator __first, _Iterator __last,
65 std::input_iterator_tag)
66 { return 0; }
67
68 template<class _Iterator>
69 inline typename std::iterator_traits<_Iterator>::difference_type
70 __distance_fw(_Iterator __first, _Iterator __last,
71 std::forward_iterator_tag)
72 { return std::distance(__first, __last); }
73
74 template<class _Iterator>
75 inline typename std::iterator_traits<_Iterator>::difference_type
76 __distance_fw(_Iterator __first, _Iterator __last)
77 {
78 typedef typename std::iterator_traits<_Iterator>::iterator_category _Tag;
79 return __distance_fw(__first, __last, _Tag());
80 }
81
82 // Helper type used to detect whether the hash functor is noexcept.
83 template <typename _Key, typename _Hash>
84 struct __is_noexcept_hash : std::integral_constant<bool,
85 noexcept(declval<const _Hash&>()(declval<const _Key&>()))>
86 { };
87
88 struct _Identity
89 {
90 template<typename _Tp>
91 _Tp&&
92 operator()(_Tp&& __x) const
93 { return std::forward<_Tp>(__x); }
94 };
95
96 struct _Select1st
97 {
98 template<typename _Tp>
99 auto
100 operator()(_Tp&& __x) const
101 -> decltype(std::get<0>(std::forward<_Tp>(__x)))
102 { return std::get<0>(std::forward<_Tp>(__x)); }
103 };
104
105 // Auxiliary types used for all instantiations of _Hashtable nodes
106 // and iterators.
107
108 /**
109 * struct _Hashtable_traits
110 *
111 * Important traits for hash tables.
112 *
113 * @tparam _Cache_hash_code Boolean value. True if the value of
114 * the hash function is stored along with the value. This is a
115 * time-space tradeoff. Storing it may improve lookup speed by
116 * reducing the number of times we need to call the _Equal
117 * function.
118 *
119 * @tparam _Constant_iterators Boolean value. True if iterator and
120 * const_iterator are both constant iterator types. This is true
121 * for unordered_set and unordered_multiset, false for
122 * unordered_map and unordered_multimap.
123 *
124 * @tparam _Unique_keys Boolean value. True if the return value
125 * of _Hashtable::count(k) is always at most one, false if it may
126 * be an arbitrary number. This is true for unordered_set and
127 * unordered_map, false for unordered_multiset and
128 * unordered_multimap.
129 */
130 template<bool _Cache_hash_code, bool _Constant_iterators, bool _Unique_keys>
131 struct _Hashtable_traits
132 {
133 template<bool _Cond>
134 using __bool_constant = integral_constant<bool, _Cond>;
135
136 using __hash_cached = __bool_constant<_Cache_hash_code>;
137 using __constant_iterators = __bool_constant<_Constant_iterators>;
138 using __unique_keys = __bool_constant<_Unique_keys>;
139 };
140
141 /**
142 * struct _Hash_node_base
143 *
144 * Nodes, used to wrap elements stored in the hash table. A policy
145 * template parameter of class template _Hashtable controls whether
146 * nodes also store a hash code. In some cases (e.g. strings) this
147 * may be a performance win.
148 */
149 struct _Hash_node_base
150 {
151 _Hash_node_base* _M_nxt;
152
153 _Hash_node_base() : _M_nxt() { }
154
155 _Hash_node_base(_Hash_node_base* __next) : _M_nxt(__next) { }
156 };
157
158 /**
159 * Primary template struct _Hash_node.
160 */
161 template<typename _Value, bool _Cache_hash_code>
162 struct _Hash_node;
163
164 /**
165 * Specialization for nodes with caches, struct _Hash_node.
166 *
167 * Base class is __detail::_Hash_node_base.
168 */
169 template<typename _Value>
170 struct _Hash_node<_Value, true> : _Hash_node_base
171 {
172 _Value _M_v;
173 std::size_t _M_hash_code;
174
175 template<typename... _Args>
176 _Hash_node(_Args&&... __args)
177 : _M_v(std::forward<_Args>(__args)...), _M_hash_code() { }
178
179 _Hash_node*
180 _M_next() const { return static_cast<_Hash_node*>(_M_nxt); }
181 };
182
183 /**
184 * Specialization for nodes without caches, struct _Hash_node.
185 *
186 * Base class is __detail::_Hash_node_base.
187 */
188 template<typename _Value>
189 struct _Hash_node<_Value, false> : _Hash_node_base
190 {
191 _Value _M_v;
192
193 template<typename... _Args>
194 _Hash_node(_Args&&... __args)
195 : _M_v(std::forward<_Args>(__args)...) { }
196
197 _Hash_node*
198 _M_next() const { return static_cast<_Hash_node*>(_M_nxt); }
199 };
200
201 /// Base class for node iterators.
202 template<typename _Value, bool _Cache_hash_code>
203 struct _Node_iterator_base
204 {
205 using __node_type = _Hash_node<_Value, _Cache_hash_code>;
206
207 __node_type* _M_cur;
208
209 _Node_iterator_base(__node_type* __p)
210 : _M_cur(__p) { }
211
212 void
213 _M_incr()
214 { _M_cur = _M_cur->_M_next(); }
215 };
216
217 template<typename _Value, bool _Cache_hash_code>
218 inline bool
219 operator==(const _Node_iterator_base<_Value, _Cache_hash_code>& __x,
220 const _Node_iterator_base<_Value, _Cache_hash_code >& __y)
221 { return __x._M_cur == __y._M_cur; }
222
223 template<typename _Value, bool _Cache_hash_code>
224 inline bool
225 operator!=(const _Node_iterator_base<_Value, _Cache_hash_code>& __x,
226 const _Node_iterator_base<_Value, _Cache_hash_code>& __y)
227 { return __x._M_cur != __y._M_cur; }
228
229 /// Node iterators, used to iterate through all the hashtable.
230 template<typename _Value, bool __constant_iterators, bool __cache>
231 struct _Node_iterator
232 : public _Node_iterator_base<_Value, __cache>
233 {
234 private:
235 using __base_type = _Node_iterator_base<_Value, __cache>;
236 using __node_type = typename __base_type::__node_type;
237
238 public:
239 typedef _Value value_type;
240 typedef std::ptrdiff_t difference_type;
241 typedef std::forward_iterator_tag iterator_category;
242
243 using pointer = typename std::conditional<__constant_iterators,
244 const _Value*, _Value*>::type;
245
246 using reference = typename std::conditional<__constant_iterators,
247 const _Value&, _Value&>::type;
248
249 _Node_iterator()
250 : __base_type(0) { }
251
252 explicit
253 _Node_iterator(__node_type* __p)
254 : __base_type(__p) { }
255
256 reference
257 operator*() const
258 { return this->_M_cur->_M_v; }
259
260 pointer
261 operator->() const
262 { return std::__addressof(this->_M_cur->_M_v); }
263
264 _Node_iterator&
265 operator++()
266 {
267 this->_M_incr();
268 return *this;
269 }
270
271 _Node_iterator
272 operator++(int)
273 {
274 _Node_iterator __tmp(*this);
275 this->_M_incr();
276 return __tmp;
277 }
278 };
279
280 /// Node const_iterators, used to iterate through all the hashtable.
281 template<typename _Value, bool __constant_iterators, bool __cache>
282 struct _Node_const_iterator
283 : public _Node_iterator_base<_Value, __cache>
284 {
285 private:
286 using __base_type = _Node_iterator_base<_Value, __cache>;
287 using __node_type = typename __base_type::__node_type;
288
289 public:
290 typedef _Value value_type;
291 typedef std::ptrdiff_t difference_type;
292 typedef std::forward_iterator_tag iterator_category;
293
294 typedef const _Value* pointer;
295 typedef const _Value& reference;
296
297 _Node_const_iterator()
298 : __base_type(0) { }
299
300 explicit
301 _Node_const_iterator(__node_type* __p)
302 : __base_type(__p) { }
303
304 _Node_const_iterator(const _Node_iterator<_Value, __constant_iterators,
305 __cache>& __x)
306 : __base_type(__x._M_cur) { }
307
308 reference
309 operator*() const
310 { return this->_M_cur->_M_v; }
311
312 pointer
313 operator->() const
314 { return std::__addressof(this->_M_cur->_M_v); }
315
316 _Node_const_iterator&
317 operator++()
318 {
319 this->_M_incr();
320 return *this;
321 }
322
323 _Node_const_iterator
324 operator++(int)
325 {
326 _Node_const_iterator __tmp(*this);
327 this->_M_incr();
328 return __tmp;
329 }
330 };
331
332 // Many of class template _Hashtable's template parameters are policy
333 // classes. These are defaults for the policies.
334
335 /// Default range hashing function: use division to fold a large number
336 /// into the range [0, N).
337 struct _Mod_range_hashing
338 {
339 typedef std::size_t first_argument_type;
340 typedef std::size_t second_argument_type;
341 typedef std::size_t result_type;
342
343 result_type
344 operator()(first_argument_type __num, second_argument_type __den) const
345 { return __num % __den; }
346 };
347
348 /// Default ranged hash function H. In principle it should be a
349 /// function object composed from objects of type H1 and H2 such that
350 /// h(k, N) = h2(h1(k), N), but that would mean making extra copies of
351 /// h1 and h2. So instead we'll just use a tag to tell class template
352 /// hashtable to do that composition.
353 struct _Default_ranged_hash { };
354
355 /// Default value for rehash policy. Bucket size is (usually) the
356 /// smallest prime that keeps the load factor small enough.
357 struct _Prime_rehash_policy
358 {
359 _Prime_rehash_policy(float __z = 1.0)
360 : _M_max_load_factor(__z), _M_next_resize(0) { }
361
362 float
363 max_load_factor() const noexcept
364 { return _M_max_load_factor; }
365
366 // Return a bucket size no smaller than n.
367 std::size_t
368 _M_next_bkt(std::size_t __n) const;
369
370 // Return a bucket count appropriate for n elements
371 std::size_t
372 _M_bkt_for_elements(std::size_t __n) const
373 { return __builtin_ceil(__n / (long double)_M_max_load_factor); }
374
375 // __n_bkt is current bucket count, __n_elt is current element count,
376 // and __n_ins is number of elements to be inserted. Do we need to
377 // increase bucket count? If so, return make_pair(true, n), where n
378 // is the new bucket count. If not, return make_pair(false, 0).
379 std::pair<bool, std::size_t>
380 _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt,
381 std::size_t __n_ins) const;
382
383 typedef std::size_t _State;
384
385 _State
386 _M_state() const
387 { return _M_next_resize; }
388
389 void
390 _M_reset(_State __state)
391 { _M_next_resize = __state; }
392
393 enum { _S_n_primes = sizeof(unsigned long) != 8 ? 256 : 256 + 48 };
394
395 static const std::size_t _S_growth_factor = 2;
396
397 float _M_max_load_factor;
398 mutable std::size_t _M_next_resize;
399 };
400
401 // Base classes for std::_Hashtable. We define these base classes
402 // because in some cases we want to do different things depending on
403 // the value of a policy class. In some cases the policy class
404 // affects which member functions and nested typedefs are defined;
405 // we handle that by specializing base class templates. Several of
406 // the base class templates need to access other members of class
407 // template _Hashtable, so we use a variant of the "Curiously
408 // Recurring Template Pattern" (CRTP) technique.
409
410 /**
411 * Primary class template _Map_base.
412 *
413 * If the hashtable has a value type of the form pair<T1, T2> and a
414 * key extraction policy (_ExtractKey) that returns the first part
415 * of the pair, the hashtable gets a mapped_type typedef. If it
416 * satisfies those criteria and also has unique keys, then it also
417 * gets an operator[].
418 */
419 template<typename _Key, typename _Value, typename _Alloc,
420 typename _ExtractKey, typename _Equal,
421 typename _H1, typename _H2, typename _Hash,
422 typename _RehashPolicy, typename _Traits,
423 bool _Unique_keys = _Traits::__unique_keys::value>
424 struct _Map_base { };
425
426 /// Partial specialization, __unique_keys set to false.
427 template<typename _Key, typename _Pair, typename _Alloc, typename _Equal,
428 typename _H1, typename _H2, typename _Hash,
429 typename _RehashPolicy, typename _Traits>
430 struct _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal,
431 _H1, _H2, _Hash, _RehashPolicy, _Traits, false>
432 {
433 using mapped_type = typename std::tuple_element<1, _Pair>::type;
434 };
435
436 /// Partial specialization, __unique_keys set to true.
437 template<typename _Key, typename _Pair, typename _Alloc, typename _Equal,
438 typename _H1, typename _H2, typename _Hash,
439 typename _RehashPolicy, typename _Traits>
440 struct _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal,
441 _H1, _H2, _Hash, _RehashPolicy, _Traits, true>
442 {
443 private:
444 using __hashtable_base = __detail::_Hashtable_base<_Key, _Pair,
445 _Select1st,
446 _Equal, _H1, _H2, _Hash,
447 _Traits>;
448
449 using __hashtable = _Hashtable<_Key, _Pair, _Alloc,
450 _Select1st, _Equal,
451 _H1, _H2, _Hash, _RehashPolicy, _Traits>;
452
453 using __hash_code = typename __hashtable_base::__hash_code;
454 using __node_type = typename __hashtable_base::__node_type;
455
456 public:
457 using key_type = typename __hashtable_base::key_type;
458 using iterator = typename __hashtable_base::iterator;
459 using mapped_type = typename std::tuple_element<1, _Pair>::type;
460
461 mapped_type&
462 operator[](const key_type& __k);
463
464 mapped_type&
465 operator[](key_type&& __k);
466
467 // _GLIBCXX_RESOLVE_LIB_DEFECTS
468 // DR 761. unordered_map needs an at() member function.
469 mapped_type&
470 at(const key_type& __k);
471
472 const mapped_type&
473 at(const key_type& __k) const;
474 };
475
476 template<typename _Key, typename _Pair, typename _Alloc, typename _Equal,
477 typename _H1, typename _H2, typename _Hash,
478 typename _RehashPolicy, typename _Traits>
479 typename _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal,
480 _H1, _H2, _Hash, _RehashPolicy, _Traits, true>
481 ::mapped_type&
482 _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal,
483 _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::
484 operator[](const key_type& __k)
485 {
486 __hashtable* __h = static_cast<__hashtable*>(this);
487 __hash_code __code = __h->_M_hash_code(__k);
488 std::size_t __n = __h->_M_bucket_index(__k, __code);
489 __node_type* __p = __h->_M_find_node(__n, __k, __code);
490
491 if (!__p)
492 {
493 __p = __h->_M_allocate_node(std::piecewise_construct,
494 std::tuple<const key_type&>(__k),
495 std::tuple<>());
496 return __h->_M_insert_unique_node(__n, __code, __p)->second;
497 }
498
499 return (__p->_M_v).second;
500 }
501
502 template<typename _Key, typename _Pair, typename _Alloc, typename _Equal,
503 typename _H1, typename _H2, typename _Hash,
504 typename _RehashPolicy, typename _Traits>
505 typename _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal,
506 _H1, _H2, _Hash, _RehashPolicy, _Traits, true>
507 ::mapped_type&
508 _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal,
509 _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::
510 operator[](key_type&& __k)
511 {
512 __hashtable* __h = static_cast<__hashtable*>(this);
513 __hash_code __code = __h->_M_hash_code(__k);
514 std::size_t __n = __h->_M_bucket_index(__k, __code);
515 __node_type* __p = __h->_M_find_node(__n, __k, __code);
516
517 if (!__p)
518 {
519 __p = __h->_M_allocate_node(std::piecewise_construct,
520 std::forward_as_tuple(std::move(__k)),
521 std::tuple<>());
522 return __h->_M_insert_unique_node(__n, __code, __p)->second;
523 }
524
525 return (__p->_M_v).second;
526 }
527
528 template<typename _Key, typename _Pair, typename _Alloc, typename _Equal,
529 typename _H1, typename _H2, typename _Hash,
530 typename _RehashPolicy, typename _Traits>
531 typename _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal,
532 _H1, _H2, _Hash, _RehashPolicy, _Traits, true>
533 ::mapped_type&
534 _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal,
535 _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::
536 at(const key_type& __k)
537 {
538 __hashtable* __h = static_cast<__hashtable*>(this);
539 __hash_code __code = __h->_M_hash_code(__k);
540 std::size_t __n = __h->_M_bucket_index(__k, __code);
541 __node_type* __p = __h->_M_find_node(__n, __k, __code);
542
543 if (!__p)
544 __throw_out_of_range(__N("_Map_base::at"));
545 return (__p->_M_v).second;
546 }
547
548 template<typename _Key, typename _Pair, typename _Alloc, typename _Equal,
549 typename _H1, typename _H2, typename _Hash,
550 typename _RehashPolicy, typename _Traits>
551 const typename _Map_base<_Key, _Pair, _Alloc, _Select1st,
552 _Equal, _H1, _H2, _Hash, _RehashPolicy,
553 _Traits, true>::mapped_type&
554 _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal,
555 _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::
556 at(const key_type& __k) const
557 {
558 const __hashtable* __h = static_cast<const __hashtable*>(this);
559 __hash_code __code = __h->_M_hash_code(__k);
560 std::size_t __n = __h->_M_bucket_index(__k, __code);
561 __node_type* __p = __h->_M_find_node(__n, __k, __code);
562
563 if (!__p)
564 __throw_out_of_range(__N("_Map_base::at"));
565 return (__p->_M_v).second;
566 }
567
568 /**
569 * Primary class template _Insert_base.
570 *
571 * insert member functions appropriate to all _Hashtables.
572 */
573 template<typename _Key, typename _Value, typename _Alloc,
574 typename _ExtractKey, typename _Equal,
575 typename _H1, typename _H2, typename _Hash,
576 typename _RehashPolicy, typename _Traits>
577 struct _Insert_base
578 {
579 using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
580 _Equal, _H1, _H2, _Hash,
581 _RehashPolicy, _Traits>;
582
583 using __hashtable_base = _Hashtable_base<_Key, _Value, _ExtractKey,
584 _Equal, _H1, _H2, _Hash,
585 _Traits>;
586
587 using value_type = typename __hashtable_base::value_type;
588 using iterator = typename __hashtable_base::iterator;
589 using const_iterator = typename __hashtable_base::const_iterator;
590 using size_type = typename __hashtable_base::size_type;
591
592 using __unique_keys = typename __hashtable_base::__unique_keys;
593 using __ireturn_type = typename __hashtable_base::__ireturn_type;
594 using __iconv_type = typename __hashtable_base::__iconv_type;
595
596 __hashtable&
597 _M_conjure_hashtable()
598 { return *(static_cast<__hashtable*>(this)); }
599
600 __ireturn_type
601 insert(const value_type& __v)
602 {
603 __hashtable& __h = _M_conjure_hashtable();
604 return __h._M_insert(__v, __unique_keys());
605 }
606
607 iterator
608 insert(const_iterator, const value_type& __v)
609 { return __iconv_type()(insert(__v)); }
610
611 void
612 insert(initializer_list<value_type> __l)
613 { this->insert(__l.begin(), __l.end()); }
614
615 template<typename _InputIterator>
616 void
617 insert(_InputIterator __first, _InputIterator __last);
618 };
619
620 template<typename _Key, typename _Value, typename _Alloc,
621 typename _ExtractKey, typename _Equal,
622 typename _H1, typename _H2, typename _Hash,
623 typename _RehashPolicy, typename _Traits>
624 template<typename _InputIterator>
625 void
626 _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash,
627 _RehashPolicy, _Traits>::
628 insert(_InputIterator __first, _InputIterator __last)
629 {
630 using __rehash_type = typename __hashtable::__rehash_type;
631 using __rehash_state = typename __hashtable::__rehash_state;
632 using pair_type = std::pair<bool, std::size_t>;
633
634 size_type __n_elt = __detail::__distance_fw(__first, __last);
635
636 __hashtable& __h = _M_conjure_hashtable();
637 __rehash_type& __rehash = __h._M_rehash_policy;
638 const __rehash_state& __saved_state = __rehash._M_state();
639 pair_type __do_rehash = __rehash._M_need_rehash(__h._M_bucket_count,
640 __h._M_element_count,
641 __n_elt);
642
643 if (__do_rehash.first)
644 __h._M_rehash(__do_rehash.second, __saved_state);
645
646 for (; __first != __last; ++__first)
647 this->insert(*__first);
648 }
649
650 /**
651 * Primary class template _Insert.
652 *
653 * Select insert member functions appropriate to _Hashtable policy choices.
654 */
655 template<typename _Key, typename _Value, typename _Alloc,
656 typename _ExtractKey, typename _Equal,
657 typename _H1, typename _H2, typename _Hash,
658 typename _RehashPolicy, typename _Traits,
659 bool _Constant_iterators = _Traits::__constant_iterators::value,
660 bool _Unique_keys = _Traits::__unique_keys::value>
661 struct _Insert;
662
663 /// Specialization.
664 template<typename _Key, typename _Value, typename _Alloc,
665 typename _ExtractKey, typename _Equal,
666 typename _H1, typename _H2, typename _Hash,
667 typename _RehashPolicy, typename _Traits>
668 struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash,
669 _RehashPolicy, _Traits, true, true>
670 : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
671 _H1, _H2, _Hash, _RehashPolicy, _Traits>
672 {
673 using __base_type = _Insert_base<_Key, _Value, _Alloc, _ExtractKey,
674 _Equal, _H1, _H2, _Hash,
675 _RehashPolicy, _Traits>;
676 using value_type = typename __base_type::value_type;
677 using iterator = typename __base_type::iterator;
678 using const_iterator = typename __base_type::const_iterator;
679
680 using __unique_keys = typename __base_type::__unique_keys;
681 using __hashtable = typename __base_type::__hashtable;
682
683 using __base_type::insert;
684
685 std::pair<iterator, bool>
686 insert(value_type&& __v)
687 {
688 __hashtable& __h = this->_M_conjure_hashtable();
689 return __h._M_insert(std::move(__v), __unique_keys());
690 }
691
692 iterator
693 insert(const_iterator, value_type&& __v)
694 { return insert(std::move(__v)).first; }
695 };
696
697 /// Specialization.
698 template<typename _Key, typename _Value, typename _Alloc,
699 typename _ExtractKey, typename _Equal,
700 typename _H1, typename _H2, typename _Hash,
701 typename _RehashPolicy, typename _Traits>
702 struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash,
703 _RehashPolicy, _Traits, true, false>
704 : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
705 _H1, _H2, _Hash, _RehashPolicy, _Traits>
706 {
707 using __base_type = _Insert_base<_Key, _Value, _Alloc, _ExtractKey,
708 _Equal, _H1, _H2, _Hash,
709 _RehashPolicy, _Traits>;
710 using value_type = typename __base_type::value_type;
711 using iterator = typename __base_type::iterator;
712 using const_iterator = typename __base_type::const_iterator;
713
714 using __unique_keys = typename __base_type::__unique_keys;
715 using __hashtable = typename __base_type::__hashtable;
716
717 using __base_type::insert;
718
719 iterator
720 insert(value_type&& __v)
721 {
722 __hashtable& __h = this->_M_conjure_hashtable();
723 return __h._M_insert(std::move(__v), __unique_keys());
724 }
725
726 iterator
727 insert(const_iterator, value_type&& __v)
728 { return insert(std::move(__v)); }
729 };
730
731 /// Specialization.
732 template<typename _Key, typename _Value, typename _Alloc,
733 typename _ExtractKey, typename _Equal,
734 typename _H1, typename _H2, typename _Hash,
735 typename _RehashPolicy, typename _Traits, bool _Unique_keys>
736 struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash,
737 _RehashPolicy, _Traits, false, _Unique_keys>
738 : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
739 _H1, _H2, _Hash, _RehashPolicy, _Traits>
740 {
741 using __base_type = _Insert_base<_Key, _Value, _Alloc, _ExtractKey,
742 _Equal, _H1, _H2, _Hash,
743 _RehashPolicy, _Traits>;
744 using value_type = typename __base_type::value_type;
745 using iterator = typename __base_type::iterator;
746 using const_iterator = typename __base_type::const_iterator;
747
748 using __unique_keys = typename __base_type::__unique_keys;
749 using __hashtable = typename __base_type::__hashtable;
750 using __ireturn_type = typename __base_type::__ireturn_type;
751 using __iconv_type = typename __base_type::__iconv_type;
752
753 using __base_type::insert;
754
755 template<typename _Pair>
756 using __is_cons = std::is_constructible<value_type, _Pair&&>;
757
758 template<typename _Pair>
759 using _IFcons = std::enable_if<__is_cons<_Pair>::value>;
760
761 template<typename _Pair>
762 using _IFconsp = typename _IFcons<_Pair>::type;
763
764 template<typename _Pair, typename = _IFconsp<_Pair>>
765 __ireturn_type
766 insert(_Pair&& __v)
767 {
768 __hashtable& __h = this->_M_conjure_hashtable();
769 return __h._M_emplace(__unique_keys(), std::forward<_Pair>(__v));
770 }
771
772 template<typename _Pair, typename = _IFconsp<_Pair>>
773 iterator
774 insert(const_iterator, _Pair&& __v)
775 { return __iconv_type()(insert(std::forward<_Pair>(__v))); }
776 };
777
778 /**
779 * Primary class template _Rehash_base.
780 *
781 * Give hashtable the max_load_factor functions and reserve iff the
782 * rehash policy is _Prime_rehash_policy.
783 */
784 template<typename _Key, typename _Value, typename _Alloc,
785 typename _ExtractKey, typename _Equal,
786 typename _H1, typename _H2, typename _Hash,
787 typename _RehashPolicy, typename _Traits>
788 struct _Rehash_base;
789
790 /// Specialization.
791 template<typename _Key, typename _Value, typename _Alloc,
792 typename _ExtractKey, typename _Equal,
793 typename _H1, typename _H2, typename _Hash, typename _Traits>
794 struct _Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
795 _H1, _H2, _Hash, _Prime_rehash_policy, _Traits>
796 {
797 using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
798 _Equal, _H1, _H2, _Hash,
799 _Prime_rehash_policy, _Traits>;
800
801 float
802 max_load_factor() const noexcept
803 {
804 const __hashtable* __this = static_cast<const __hashtable*>(this);
805 return __this->__rehash_policy().max_load_factor();
806 }
807
808 void
809 max_load_factor(float __z)
810 {
811 __hashtable* __this = static_cast<__hashtable*>(this);
812 __this->__rehash_policy(_Prime_rehash_policy(__z));
813 }
814
815 void
816 reserve(std::size_t __n)
817 {
818 __hashtable* __this = static_cast<__hashtable*>(this);
819 __this->rehash(__builtin_ceil(__n / max_load_factor()));
820 }
821 };
822
823 /**
824 * Primary class template _Hashtable_ebo_helper.
825 *
826 * Helper class using EBO when it is not forbidden, type is not
827 * final, and when it worth it, type is empty.
828 */
829 template<int _Nm, typename _Tp,
830 bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)>
831 struct _Hashtable_ebo_helper;
832
833 /// Specialization using EBO.
834 template<int _Nm, typename _Tp>
835 struct _Hashtable_ebo_helper<_Nm, _Tp, true>
836 : private _Tp
837 {
838 _Hashtable_ebo_helper() = default;
839
840 _Hashtable_ebo_helper(const _Tp& __tp) : _Tp(__tp)
841 { }
842
843 static const _Tp&
844 _S_cget(const _Hashtable_ebo_helper& __eboh)
845 { return static_cast<const _Tp&>(__eboh); }
846
847 static _Tp&
848 _S_get(_Hashtable_ebo_helper& __eboh)
849 { return static_cast<_Tp&>(__eboh); }
850 };
851
852 /// Specialization not using EBO.
853 template<int _Nm, typename _Tp>
854 struct _Hashtable_ebo_helper<_Nm, _Tp, false>
855 {
856 _Hashtable_ebo_helper() = default;
857
858 _Hashtable_ebo_helper(const _Tp& __tp) : _M_tp(__tp)
859 { }
860
861 static const _Tp&
862 _S_cget(const _Hashtable_ebo_helper& __eboh)
863 { return __eboh._M_tp; }
864
865 static _Tp&
866 _S_get(_Hashtable_ebo_helper& __eboh)
867 { return __eboh._M_tp; }
868
869 private:
870 _Tp _M_tp;
871 };
872
873 /**
874 * Primary class template _Local_iterator_base.
875 *
876 * Base class for local iterators, used to iterate within a bucket
877 * but not between buckets.
878 */
879 template<typename _Key, typename _Value, typename _ExtractKey,
880 typename _H1, typename _H2, typename _Hash,
881 bool __cache_hash_code>
882 struct _Local_iterator_base;
883
884 /**
885 * Primary class template _Hash_code_base.
886 *
887 * Encapsulates two policy issues that aren't quite orthogonal.
888 * (1) the difference between using a ranged hash function and using
889 * the combination of a hash function and a range-hashing function.
890 * In the former case we don't have such things as hash codes, so
891 * we have a dummy type as placeholder.
892 * (2) Whether or not we cache hash codes. Caching hash codes is
893 * meaningless if we have a ranged hash function.
894 *
895 * We also put the key extraction objects here, for convenience.
896 * Each specialization derives from one or more of the template
897 * parameters to benefit from Ebo. This is important as this type
898 * is inherited in some cases by the _Local_iterator_base type used
899 * to implement local_iterator and const_local_iterator. As with
900 * any iterator type we prefer to make it as small as possible.
901 *
902 * Primary template is unused except as a hook for specializations.
903 */
904 template<typename _Key, typename _Value, typename _ExtractKey,
905 typename _H1, typename _H2, typename _Hash,
906 bool __cache_hash_code>
907 struct _Hash_code_base;
908
909 /// Specialization: ranged hash function, no caching hash codes. H1
910 /// and H2 are provided but ignored. We define a dummy hash code type.
911 template<typename _Key, typename _Value, typename _ExtractKey,
912 typename _H1, typename _H2, typename _Hash>
913 struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, false>
914 : private _Hashtable_ebo_helper<0, _ExtractKey>,
915 private _Hashtable_ebo_helper<1, _Hash>
916 {
917 private:
918 using __ebo_extract_key = _Hashtable_ebo_helper<0, _ExtractKey>;
919 using __ebo_hash = _Hashtable_ebo_helper<1, _Hash>;
920
921 protected:
922 typedef void* __hash_code;
923 typedef _Hash_node<_Value, false> __node_type;
924
925 // We need the default constructor for the local iterators.
926 _Hash_code_base() = default;
927
928 _Hash_code_base(const _ExtractKey& __ex, const _H1&, const _H2&,
929 const _Hash& __h)
930 : __ebo_extract_key(__ex), __ebo_hash(__h) { }
931
932 __hash_code
933 _M_hash_code(const _Key& __key) const
934 { return 0; }
935
936 std::size_t
937 _M_bucket_index(const _Key& __k, __hash_code, std::size_t __n) const
938 { return _M_ranged_hash()(__k, __n); }
939
940 std::size_t
941 _M_bucket_index(const __node_type* __p, std::size_t __n) const
942 { return _M_ranged_hash()(_M_extract()(__p->_M_v), __n); }
943
944 void
945 _M_store_code(__node_type*, __hash_code) const
946 { }
947
948 void
949 _M_copy_code(__node_type*, const __node_type*) const
950 { }
951
952 void
953 _M_swap(_Hash_code_base& __x)
954 {
955 std::swap(_M_extract(), __x._M_extract());
956 std::swap(_M_ranged_hash(), __x._M_ranged_hash());
957 }
958
959 const _ExtractKey&
960 _M_extract() const { return __ebo_extract_key::_S_cget(*this); }
961
962 _ExtractKey&
963 _M_extract() { return __ebo_extract_key::_S_get(*this); }
964
965 const _Hash&
966 _M_ranged_hash() const { return __ebo_hash::_S_cget(*this); }
967
968 _Hash&
969 _M_ranged_hash() { return __ebo_hash::_S_get(*this); }
970 };
971
972 // No specialization for ranged hash function while caching hash codes.
973 // That combination is meaningless, and trying to do it is an error.
974
975 /// Specialization: ranged hash function, cache hash codes. This
976 /// combination is meaningless, so we provide only a declaration
977 /// and no definition.
978 template<typename _Key, typename _Value, typename _ExtractKey,
979 typename _H1, typename _H2, typename _Hash>
980 struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, true>;
981
982 /// Specialization: hash function and range-hashing function, no
983 /// caching of hash codes.
984 /// Provides typedef and accessor required by C++ 11.
985 template<typename _Key, typename _Value, typename _ExtractKey,
986 typename _H1, typename _H2>
987 struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
988 _Default_ranged_hash, false>
989 : private _Hashtable_ebo_helper<0, _ExtractKey>,
990 private _Hashtable_ebo_helper<1, _H1>,
991 private _Hashtable_ebo_helper<2, _H2>
992 {
993 private:
994 using __ebo_extract_key = _Hashtable_ebo_helper<0, _ExtractKey>;
995 using __ebo_h1 = _Hashtable_ebo_helper<1, _H1>;
996 using __ebo_h2 = _Hashtable_ebo_helper<2, _H2>;
997
998 public:
999 typedef _H1 hasher;
1000
1001 hasher
1002 hash_function() const
1003 { return _M_h1(); }
1004
1005 protected:
1006 typedef std::size_t __hash_code;
1007 typedef _Hash_node<_Value, false> __node_type;
1008
1009 // We need the default constructor for the local iterators.
1010 _Hash_code_base() = default;
1011
1012 _Hash_code_base(const _ExtractKey& __ex,
1013 const _H1& __h1, const _H2& __h2,
1014 const _Default_ranged_hash&)
1015 : __ebo_extract_key(__ex), __ebo_h1(__h1), __ebo_h2(__h2) { }
1016
1017 __hash_code
1018 _M_hash_code(const _Key& __k) const
1019 { return _M_h1()(__k); }
1020
1021 std::size_t
1022 _M_bucket_index(const _Key&, __hash_code __c, std::size_t __n) const
1023 { return _M_h2()(__c, __n); }
1024
1025 std::size_t
1026 _M_bucket_index(const __node_type* __p,
1027 std::size_t __n) const
1028 { return _M_h2()(_M_h1()(_M_extract()(__p->_M_v)), __n); }
1029
1030 void
1031 _M_store_code(__node_type*, __hash_code) const
1032 { }
1033
1034 void
1035 _M_copy_code(__node_type*, const __node_type*) const
1036 { }
1037
1038 void
1039 _M_swap(_Hash_code_base& __x)
1040 {
1041 std::swap(_M_extract(), __x._M_extract());
1042 std::swap(_M_h1(), __x._M_h1());
1043 std::swap(_M_h2(), __x._M_h2());
1044 }
1045
1046 const _ExtractKey&
1047 _M_extract() const { return __ebo_extract_key::_S_cget(*this); }
1048
1049 _ExtractKey&
1050 _M_extract() { return __ebo_extract_key::_S_get(*this); }
1051
1052 const _H1&
1053 _M_h1() const { return __ebo_h1::_S_cget(*this); }
1054
1055 _H1&
1056 _M_h1() { return __ebo_h1::_S_get(*this); }
1057
1058 const _H2&
1059 _M_h2() const { return __ebo_h2::_S_cget(*this); }
1060
1061 _H2&
1062 _M_h2() { return __ebo_h2::_S_get(*this); }
1063 };
1064
1065 /// Specialization: hash function and range-hashing function,
1066 /// caching hash codes. H is provided but ignored. Provides
1067 /// typedef and accessor required by C++ 11.
1068 template<typename _Key, typename _Value, typename _ExtractKey,
1069 typename _H1, typename _H2>
1070 struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2,
1071 _Default_ranged_hash, true>
1072 : private _Hashtable_ebo_helper<0, _ExtractKey>,
1073 private _Hashtable_ebo_helper<1, _H1>,
1074 private _Hashtable_ebo_helper<2, _H2>
1075 {
1076 private:
1077 // Gives access to _M_h2() to the local iterator implementation.
1078 friend struct _Local_iterator_base<_Key, _Value, _ExtractKey, _H1, _H2,
1079 _Default_ranged_hash, true>;
1080
1081 using __ebo_extract_key = _Hashtable_ebo_helper<0, _ExtractKey>;
1082 using __ebo_h1 = _Hashtable_ebo_helper<1, _H1>;
1083 using __ebo_h2 = _Hashtable_ebo_helper<2, _H2>;
1084
1085 public:
1086 typedef _H1 hasher;
1087
1088 hasher
1089 hash_function() const
1090 { return _M_h1(); }
1091
1092 protected:
1093 typedef std::size_t __hash_code;
1094 typedef _Hash_node<_Value, true> __node_type;
1095
1096 _Hash_code_base(const _ExtractKey& __ex,
1097 const _H1& __h1, const _H2& __h2,
1098 const _Default_ranged_hash&)
1099 : __ebo_extract_key(__ex), __ebo_h1(__h1), __ebo_h2(__h2) { }
1100
1101 __hash_code
1102 _M_hash_code(const _Key& __k) const
1103 { return _M_h1()(__k); }
1104
1105 std::size_t
1106 _M_bucket_index(const _Key&, __hash_code __c,
1107 std::size_t __n) const
1108 { return _M_h2()(__c, __n); }
1109
1110 std::size_t
1111 _M_bucket_index(const __node_type* __p, std::size_t __n) const
1112 { return _M_h2()(__p->_M_hash_code, __n); }
1113
1114 void
1115 _M_store_code(__node_type* __n, __hash_code __c) const
1116 { __n->_M_hash_code = __c; }
1117
1118 void
1119 _M_copy_code(__node_type* __to, const __node_type* __from) const
1120 { __to->_M_hash_code = __from->_M_hash_code; }
1121
1122 void
1123 _M_swap(_Hash_code_base& __x)
1124 {
1125 std::swap(_M_extract(), __x._M_extract());
1126 std::swap(_M_h1(), __x._M_h1());
1127 std::swap(_M_h2(), __x._M_h2());
1128 }
1129
1130 const _ExtractKey&
1131 _M_extract() const { return __ebo_extract_key::_S_cget(*this); }
1132
1133 _ExtractKey&
1134 _M_extract() { return __ebo_extract_key::_S_get(*this); }
1135
1136 const _H1&
1137 _M_h1() const { return __ebo_h1::_S_cget(*this); }
1138
1139 _H1&
1140 _M_h1() { return __ebo_h1::_S_get(*this); }
1141
1142 const _H2&
1143 _M_h2() const { return __ebo_h2::_S_cget(*this); }
1144
1145 _H2&
1146 _M_h2() { return __ebo_h2::_S_get(*this); }
1147 };
1148
1149 /**
1150 * Primary class template _Equal_helper.
1151 *
1152 */
1153 template <typename _Key, typename _Value, typename _ExtractKey,
1154 typename _Equal, typename _HashCodeType,
1155 bool __cache_hash_code>
1156 struct _Equal_helper;
1157
1158 /// Specialization.
1159 template<typename _Key, typename _Value, typename _ExtractKey,
1160 typename _Equal, typename _HashCodeType>
1161 struct _Equal_helper<_Key, _Value, _ExtractKey, _Equal, _HashCodeType, true>
1162 {
1163 static bool
1164 _S_equals(const _Equal& __eq, const _ExtractKey& __extract,
1165 const _Key& __k, _HashCodeType __c, _Hash_node<_Value, true>* __n)
1166 { return __c == __n->_M_hash_code && __eq(__k, __extract(__n->_M_v)); }
1167 };
1168
1169 /// Specialization.
1170 template<typename _Key, typename _Value, typename _ExtractKey,
1171 typename _Equal, typename _HashCodeType>
1172 struct _Equal_helper<_Key, _Value, _ExtractKey, _Equal, _HashCodeType, false>
1173 {
1174 static bool
1175 _S_equals(const _Equal& __eq, const _ExtractKey& __extract,
1176 const _Key& __k, _HashCodeType, _Hash_node<_Value, false>* __n)
1177 { return __eq(__k, __extract(__n->_M_v)); }
1178 };
1179
1180
1181 /// Specialization.
1182 template<typename _Key, typename _Value, typename _ExtractKey,
1183 typename _H1, typename _H2, typename _Hash>
1184 struct _Local_iterator_base<_Key, _Value, _ExtractKey,
1185 _H1, _H2, _Hash, true>
1186 : private _Hashtable_ebo_helper<0, _H2>
1187 {
1188 protected:
1189 using __base_type = _Hashtable_ebo_helper<0, _H2>;
1190 using __hash_code_base = _Hash_code_base<_Key, _Value, _ExtractKey,
1191 _H1, _H2, _Hash, true>;
1192
1193 public:
1194 _Local_iterator_base() = default;
1195 _Local_iterator_base(const __hash_code_base& __base,
1196 _Hash_node<_Value, true>* __p,
1197 std::size_t __bkt, std::size_t __bkt_count)
1198 : __base_type(__base._M_h2()),
1199 _M_cur(__p), _M_bucket(__bkt), _M_bucket_count(__bkt_count) { }
1200
1201 void
1202 _M_incr()
1203 {
1204 _M_cur = _M_cur->_M_next();
1205 if (_M_cur)
1206 {
1207 std::size_t __bkt
1208 = __base_type::_S_get(*this)(_M_cur->_M_hash_code,
1209 _M_bucket_count);
1210 if (__bkt != _M_bucket)
1211 _M_cur = nullptr;
1212 }
1213 }
1214
1215 _Hash_node<_Value, true>* _M_cur;
1216 std::size_t _M_bucket;
1217 std::size_t _M_bucket_count;
1218 };
1219
1220 /// Specialization.
1221 template<typename _Key, typename _Value, typename _ExtractKey,
1222 typename _H1, typename _H2, typename _Hash>
1223 struct _Local_iterator_base<_Key, _Value, _ExtractKey,
1224 _H1, _H2, _Hash, false>
1225 : private _Hash_code_base<_Key, _Value, _ExtractKey,
1226 _H1, _H2, _Hash, false>
1227 {
1228 protected:
1229 using __hash_code_base = _Hash_code_base<_Key, _Value, _ExtractKey,
1230 _H1, _H2, _Hash, false>;
1231
1232 public:
1233 _Local_iterator_base() = default;
1234 _Local_iterator_base(const __hash_code_base& __base,
1235 _Hash_node<_Value, false>* __p,
1236 std::size_t __bkt, std::size_t __bkt_count)
1237 : __hash_code_base(__base),
1238 _M_cur(__p), _M_bucket(__bkt), _M_bucket_count(__bkt_count) { }
1239
1240 void
1241 _M_incr()
1242 {
1243 _M_cur = _M_cur->_M_next();
1244 if (_M_cur)
1245 {
1246 std::size_t __bkt = this->_M_bucket_index(_M_cur, _M_bucket_count);
1247 if (__bkt != _M_bucket)
1248 _M_cur = nullptr;
1249 }
1250 }
1251
1252 _Hash_node<_Value, false>* _M_cur;
1253 std::size_t _M_bucket;
1254 std::size_t _M_bucket_count;
1255 };
1256
1257 template<typename _Key, typename _Value, typename _ExtractKey,
1258 typename _H1, typename _H2, typename _Hash, bool __cache>
1259 inline bool
1260 operator==(const _Local_iterator_base<_Key, _Value, _ExtractKey,
1261 _H1, _H2, _Hash, __cache>& __x,
1262 const _Local_iterator_base<_Key, _Value, _ExtractKey,
1263 _H1, _H2, _Hash, __cache>& __y)
1264 { return __x._M_cur == __y._M_cur; }
1265
1266 template<typename _Key, typename _Value, typename _ExtractKey,
1267 typename _H1, typename _H2, typename _Hash, bool __cache>
1268 inline bool
1269 operator!=(const _Local_iterator_base<_Key, _Value, _ExtractKey,
1270 _H1, _H2, _Hash, __cache>& __x,
1271 const _Local_iterator_base<_Key, _Value, _ExtractKey,
1272 _H1, _H2, _Hash, __cache>& __y)
1273 { return __x._M_cur != __y._M_cur; }
1274
1275 /// local iterators
1276 template<typename _Key, typename _Value, typename _ExtractKey,
1277 typename _H1, typename _H2, typename _Hash,
1278 bool __constant_iterators, bool __cache>
1279 struct _Local_iterator
1280 : public _Local_iterator_base<_Key, _Value, _ExtractKey,
1281 _H1, _H2, _Hash, __cache>
1282 {
1283 private:
1284 using __base_type = _Local_iterator_base<_Key, _Value, _ExtractKey,
1285 _H1, _H2, _Hash, __cache>;
1286 using __hash_code_base = typename __base_type::__hash_code_base;
1287 public:
1288 typedef _Value value_type;
1289 typedef typename std::conditional<__constant_iterators,
1290 const _Value*, _Value*>::type
1291 pointer;
1292 typedef typename std::conditional<__constant_iterators,
1293 const _Value&, _Value&>::type
1294 reference;
1295 typedef std::ptrdiff_t difference_type;
1296 typedef std::forward_iterator_tag iterator_category;
1297
1298 _Local_iterator() = default;
1299
1300 _Local_iterator(const __hash_code_base& __base,
1301 _Hash_node<_Value, __cache>* __p,
1302 std::size_t __bkt, std::size_t __bkt_count)
1303 : __base_type(__base, __p, __bkt, __bkt_count)
1304 { }
1305
1306 reference
1307 operator*() const
1308 { return this->_M_cur->_M_v; }
1309
1310 pointer
1311 operator->() const
1312 { return std::__addressof(this->_M_cur->_M_v); }
1313
1314 _Local_iterator&
1315 operator++()
1316 {
1317 this->_M_incr();
1318 return *this;
1319 }
1320
1321 _Local_iterator
1322 operator++(int)
1323 {
1324 _Local_iterator __tmp(*this);
1325 this->_M_incr();
1326 return __tmp;
1327 }
1328 };
1329
1330 /// local const_iterators
1331 template<typename _Key, typename _Value, typename _ExtractKey,
1332 typename _H1, typename _H2, typename _Hash,
1333 bool __constant_iterators, bool __cache>
1334 struct _Local_const_iterator
1335 : public _Local_iterator_base<_Key, _Value, _ExtractKey,
1336 _H1, _H2, _Hash, __cache>
1337 {
1338 private:
1339 using __base_type = _Local_iterator_base<_Key, _Value, _ExtractKey,
1340 _H1, _H2, _Hash, __cache>;
1341 using __hash_code_base = typename __base_type::__hash_code_base;
1342
1343 public:
1344 typedef _Value value_type;
1345 typedef const _Value* pointer;
1346 typedef const _Value& reference;
1347 typedef std::ptrdiff_t difference_type;
1348 typedef std::forward_iterator_tag iterator_category;
1349
1350 _Local_const_iterator() = default;
1351
1352 _Local_const_iterator(const __hash_code_base& __base,
1353 _Hash_node<_Value, __cache>* __p,
1354 std::size_t __bkt, std::size_t __bkt_count)
1355 : __base_type(__base, __p, __bkt, __bkt_count)
1356 { }
1357
1358 _Local_const_iterator(const _Local_iterator<_Key, _Value, _ExtractKey,
1359 _H1, _H2, _Hash,
1360 __constant_iterators,
1361 __cache>& __x)
1362 : __base_type(__x)
1363 { }
1364
1365 reference
1366 operator*() const
1367 { return this->_M_cur->_M_v; }
1368
1369 pointer
1370 operator->() const
1371 { return std::__addressof(this->_M_cur->_M_v); }
1372
1373 _Local_const_iterator&
1374 operator++()
1375 {
1376 this->_M_incr();
1377 return *this;
1378 }
1379
1380 _Local_const_iterator
1381 operator++(int)
1382 {
1383 _Local_const_iterator __tmp(*this);
1384 this->_M_incr();
1385 return __tmp;
1386 }
1387 };
1388
1389 /**
1390 * Primary class template _Hashtable_base.
1391 *
1392 * Helper class adding management of _Equal functor to
1393 * _Hash_code_base type.
1394 *
1395 * Base class templates are:
1396 * - __detail::_Hash_code_base
1397 * - __detail::_Hashtable_ebo_helper
1398 */
1399 template<typename _Key, typename _Value,
1400 typename _ExtractKey, typename _Equal,
1401 typename _H1, typename _H2, typename _Hash, typename _Traits>
1402 struct _Hashtable_base
1403 : public _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash,
1404 _Traits::__hash_cached::value>,
1405 private _Hashtable_ebo_helper<0, _Equal>
1406 {
1407 public:
1408 typedef _Key key_type;
1409 typedef _Value value_type;
1410 typedef _Equal key_equal;
1411 typedef std::size_t size_type;
1412 typedef std::ptrdiff_t difference_type;
1413
1414 using __traits_type = _Traits;
1415 using __hash_cached = typename __traits_type::__hash_cached;
1416 using __constant_iterators = typename __traits_type::__constant_iterators;
1417 using __unique_keys = typename __traits_type::__unique_keys;
1418
1419 using __hash_code_base = _Hash_code_base<_Key, _Value, _ExtractKey,
1420 _H1, _H2, _Hash,
1421 __hash_cached::value>;
1422
1423 using __hash_code = typename __hash_code_base::__hash_code;
1424 using __node_type = typename __hash_code_base::__node_type;
1425
1426 using iterator = __detail::_Node_iterator<value_type,
1427 __constant_iterators::value,
1428 __hash_cached::value>;
1429
1430 using const_iterator = __detail::_Node_const_iterator<value_type,
1431 __constant_iterators::value,
1432 __hash_cached::value>;
1433
1434 using local_iterator = __detail::_Local_iterator<key_type, value_type,
1435 _ExtractKey, _H1, _H2, _Hash,
1436 __constant_iterators::value,
1437 __hash_cached::value>;
1438
1439 using const_local_iterator = __detail::_Local_const_iterator<key_type,
1440 value_type,
1441 _ExtractKey, _H1, _H2, _Hash,
1442 __constant_iterators::value,
1443 __hash_cached::value>;
1444
1445 using __ireturn_type = typename std::conditional<__unique_keys::value,
1446 std::pair<iterator, bool>,
1447 iterator>::type;
1448
1449 using __iconv_type = typename std::conditional<__unique_keys::value,
1450 _Select1st, _Identity
1451 >::type;
1452 private:
1453 using _EqualEBO = _Hashtable_ebo_helper<0, _Equal>;
1454 using _EqualHelper = _Equal_helper<_Key, _Value, _ExtractKey, _Equal,
1455 __hash_code, __hash_cached::value>;
1456
1457 protected:
1458 using __node_base = __detail::_Hash_node_base;
1459 using __bucket_type = __node_base*;
1460
1461 _Hashtable_base(const _ExtractKey& __ex, const _H1& __h1, const _H2& __h2,
1462 const _Hash& __hash, const _Equal& __eq)
1463 : __hash_code_base(__ex, __h1, __h2, __hash), _EqualEBO(__eq)
1464 { }
1465
1466 bool
1467 _M_equals(const _Key& __k, __hash_code __c, __node_type* __n) const
1468 {
1469 return _EqualHelper::_S_equals(_M_eq(), this->_M_extract(),
1470 __k, __c, __n);
1471 }
1472
1473 void
1474 _M_swap(_Hashtable_base& __x)
1475 {
1476 __hash_code_base::_M_swap(__x);
1477 std::swap(_M_eq(), __x._M_eq());
1478 }
1479
1480 const _Equal&
1481 _M_eq() const { return _EqualEBO::_S_cget(*this); }
1482
1483 _Equal&
1484 _M_eq() { return _EqualEBO::_S_get(*this); }
1485 };
1486
1487 /**
1488 * struct _Equality_base.
1489 *
1490 * Common types and functions for class _Equality.
1491 */
1492 struct _Equality_base
1493 {
1494 protected:
1495 template<typename _Uiterator>
1496 static bool
1497 _S_is_permutation(_Uiterator, _Uiterator, _Uiterator);
1498 };
1499
1500 // See std::is_permutation in N3068.
1501 template<typename _Uiterator>
1502 bool
1503 _Equality_base::
1504 _S_is_permutation(_Uiterator __first1, _Uiterator __last1,
1505 _Uiterator __first2)
1506 {
1507 for (; __first1 != __last1; ++__first1, ++__first2)
1508 if (!(*__first1 == *__first2))
1509 break;
1510
1511 if (__first1 == __last1)
1512 return true;
1513
1514 _Uiterator __last2 = __first2;
1515 std::advance(__last2, std::distance(__first1, __last1));
1516
1517 for (_Uiterator __it1 = __first1; __it1 != __last1; ++__it1)
1518 {
1519 _Uiterator __tmp = __first1;
1520 while (__tmp != __it1 && !bool(*__tmp == *__it1))
1521 ++__tmp;
1522
1523 // We've seen this one before.
1524 if (__tmp != __it1)
1525 continue;
1526
1527 std::ptrdiff_t __n2 = 0;
1528 for (__tmp = __first2; __tmp != __last2; ++__tmp)
1529 if (*__tmp == *__it1)
1530 ++__n2;
1531
1532 if (!__n2)
1533 return false;
1534
1535 std::ptrdiff_t __n1 = 0;
1536 for (__tmp = __it1; __tmp != __last1; ++__tmp)
1537 if (*__tmp == *__it1)
1538 ++__n1;
1539
1540 if (__n1 != __n2)
1541 return false;
1542 }
1543 return true;
1544 }
1545
1546 /**
1547 * Primary class template _Equality.
1548 *
1549 * This is for implementing equality comparison for unordered
1550 * containers, per N3068, by John Lakos and Pablo Halpern.
1551 * Algorithmically, we follow closely the reference implementations
1552 * therein.
1553 */
1554 template<typename _Key, typename _Value, typename _Alloc,
1555 typename _ExtractKey, typename _Equal,
1556 typename _H1, typename _H2, typename _Hash,
1557 typename _RehashPolicy, typename _Traits,
1558 bool _Unique_keys = _Traits::__unique_keys::value>
1559 struct _Equality;
1560
1561 /// Specialization.
1562 template<typename _Key, typename _Value, typename _Alloc,
1563 typename _ExtractKey, typename _Equal,
1564 typename _H1, typename _H2, typename _Hash,
1565 typename _RehashPolicy, typename _Traits>
1566 struct _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1567 _H1, _H2, _Hash, _RehashPolicy, _Traits, true>
1568 {
1569 using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1570 _H1, _H2, _Hash, _RehashPolicy, _Traits>;
1571
1572 bool
1573 _M_equal(const __hashtable&) const;
1574 };
1575
1576 template<typename _Key, typename _Value, typename _Alloc,
1577 typename _ExtractKey, typename _Equal,
1578 typename _H1, typename _H2, typename _Hash,
1579 typename _RehashPolicy, typename _Traits>
1580 bool
1581 _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1582 _H1, _H2, _Hash, _RehashPolicy, _Traits, true>::
1583 _M_equal(const __hashtable& __other) const
1584 {
1585 const __hashtable* __this = static_cast<const __hashtable*>(this);
1586
1587 if (__this->size() != __other.size())
1588 return false;
1589
1590 for (auto __itx = __this->begin(); __itx != __this->end(); ++__itx)
1591 {
1592 const auto __ity = __other.find(_ExtractKey()(*__itx));
1593 if (__ity == __other.end() || !bool(*__ity == *__itx))
1594 return false;
1595 }
1596 return true;
1597 }
1598
1599 /// Specialization.
1600 template<typename _Key, typename _Value, typename _Alloc,
1601 typename _ExtractKey, typename _Equal,
1602 typename _H1, typename _H2, typename _Hash,
1603 typename _RehashPolicy, typename _Traits>
1604 struct _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1605 _H1, _H2, _Hash, _RehashPolicy, _Traits, false>
1606 : public _Equality_base
1607 {
1608 using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1609 _H1, _H2, _Hash, _RehashPolicy, _Traits>;
1610
1611 bool
1612 _M_equal(const __hashtable&) const;
1613 };
1614
1615 template<typename _Key, typename _Value, typename _Alloc,
1616 typename _ExtractKey, typename _Equal,
1617 typename _H1, typename _H2, typename _Hash,
1618 typename _RehashPolicy, typename _Traits>
1619 bool
1620 _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1621 _H1, _H2, _Hash, _RehashPolicy, _Traits, false>::
1622 _M_equal(const __hashtable& __other) const
1623 {
1624 const __hashtable* __this = static_cast<const __hashtable*>(this);
1625
1626 if (__this->size() != __other.size())
1627 return false;
1628
1629 for (auto __itx = __this->begin(); __itx != __this->end();)
1630 {
1631 const auto __xrange = __this->equal_range(_ExtractKey()(*__itx));
1632 const auto __yrange = __other.equal_range(_ExtractKey()(*__itx));
1633
1634 if (std::distance(__xrange.first, __xrange.second)
1635 != std::distance(__yrange.first, __yrange.second))
1636 return false;
1637
1638 if (!_S_is_permutation(__xrange.first, __xrange.second,
1639 __yrange.first))
1640 return false;
1641
1642 __itx = __xrange.second;
1643 }
1644 return true;
1645 }
1646
1647 /**
1648 * This type is to combine a _Hash_node_base instance with an allocator
1649 * instance through inheritance to benefit from EBO when possible.
1650 */
1651 template<typename _NodeAlloc>
1652 struct _Before_begin : public _NodeAlloc
1653 {
1654 _Hash_node_base _M_node;
1655
1656 _Before_begin(const _Before_begin&) = default;
1657 _Before_begin(_Before_begin&&) = default;
1658
1659 template<typename _Alloc>
1660 _Before_begin(_Alloc&& __a)
1661 : _NodeAlloc(std::forward<_Alloc>(__a))
1662 { }
1663 };
1664
1665 //@} hashtable-detail
1666 _GLIBCXX_END_NAMESPACE_VERSION
1667 } // namespace __detail
1668 } // namespace std
1669
1670 #endif // _HASHTABLE_POLICY_H