33#pragma GCC system_header
37#if __cplusplus > 201402L
41namespace std _GLIBCXX_VISIBILITY(default)
43_GLIBCXX_BEGIN_NAMESPACE_VERSION
46 template<
typename _Tp,
typename _Hash>
49 __is_fast_hash<_Hash>,
51 __is_nothrow_invocable<const _Hash&, const _Tp&>>>;
56 template<
typename _Equal,
typename _Hash,
typename _Allocator>
57 using _Hashtable_enable_default_ctor
58 = _Enable_default_constructor<__and_<is_default_constructible<_Equal>,
59 is_default_constructible<_Hash>,
60 is_default_constructible<_Allocator>>{},
61 __detail::_Hash_node_base>;
176 template<
typename _Key,
typename _Value,
typename _Alloc,
177 typename _ExtractKey,
typename _Equal,
178 typename _Hash,
typename _RangeHash,
typename _Unused,
179 typename _RehashPolicy,
typename _Traits>
181 :
public __detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal,
182 _Hash, _RangeHash, _Unused, _Traits>,
183 public __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
184 _Hash, _RangeHash, _Unused,
185 _RehashPolicy, _Traits>,
186 public __detail::_Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal,
187 _Hash, _RangeHash, _Unused,
188 _RehashPolicy, _Traits>,
189 public __detail::_Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
190 _Hash, _RangeHash, _Unused,
191 _RehashPolicy, _Traits>,
192 public __detail::_Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal,
193 _Hash, _RangeHash, _Unused,
194 _RehashPolicy, _Traits>,
195 private __detail::_Hashtable_alloc<
196 __alloc_rebind<_Alloc,
197 __detail::_Hash_node<_Value,
198 _Traits::__hash_cached::value>>>,
199 private _Hashtable_enable_default_ctor<_Equal, _Hash, _Alloc>
201 static_assert(is_same<typename remove_cv<_Value>::type, _Value>::value,
202 "unordered container must have a non-const, non-volatile value_type");
203#if __cplusplus > 201703L || defined __STRICT_ANSI__
204 static_assert(is_same<typename _Alloc::value_type, _Value>{},
205 "unordered container must have the same value_type as its allocator");
208 using __traits_type = _Traits;
209 using __hash_cached =
typename __traits_type::__hash_cached;
210 using __constant_iterators =
typename __traits_type::__constant_iterators;
211 using __node_type = __detail::_Hash_node<_Value, __hash_cached::value>;
212 using __node_alloc_type = __alloc_rebind<_Alloc, __node_type>;
214 using __hashtable_alloc = __detail::_Hashtable_alloc<__node_alloc_type>;
216 using __node_value_type =
217 __detail::_Hash_node_value<_Value, __hash_cached::value>;
218 using __node_ptr =
typename __hashtable_alloc::__node_ptr;
219 using __value_alloc_traits =
220 typename __hashtable_alloc::__value_alloc_traits;
221 using __node_alloc_traits =
222 typename __hashtable_alloc::__node_alloc_traits;
223 using __node_base =
typename __hashtable_alloc::__node_base;
224 using __node_base_ptr =
typename __hashtable_alloc::__node_base_ptr;
225 using __buckets_ptr =
typename __hashtable_alloc::__buckets_ptr;
227 using __insert_base = __detail::_Insert<_Key, _Value, _Alloc, _ExtractKey,
230 _RehashPolicy, _Traits>;
231 using __enable_default_ctor
232 = _Hashtable_enable_default_ctor<_Equal, _Hash, _Alloc>;
235 typedef _Key key_type;
236 typedef _Value value_type;
237 typedef _Alloc allocator_type;
238 typedef _Equal key_equal;
242 typedef typename __value_alloc_traits::pointer pointer;
243 typedef typename __value_alloc_traits::const_pointer const_pointer;
244 typedef value_type& reference;
245 typedef const value_type& const_reference;
247 using iterator =
typename __insert_base::iterator;
249 using const_iterator =
typename __insert_base::const_iterator;
251 using local_iterator = __detail::_Local_iterator<key_type, _Value,
252 _ExtractKey, _Hash, _RangeHash, _Unused,
253 __constant_iterators::value,
254 __hash_cached::value>;
256 using const_local_iterator = __detail::_Local_const_iterator<
258 _ExtractKey, _Hash, _RangeHash, _Unused,
259 __constant_iterators::value, __hash_cached::value>;
262 using __rehash_type = _RehashPolicy;
263 using __rehash_state =
typename __rehash_type::_State;
265 using __unique_keys =
typename __traits_type::__unique_keys;
267 using __hashtable_base = __detail::
268 _Hashtable_base<_Key, _Value, _ExtractKey,
269 _Equal, _Hash, _RangeHash, _Unused, _Traits>;
271 using __hash_code_base =
typename __hashtable_base::__hash_code_base;
272 using __hash_code =
typename __hashtable_base::__hash_code;
273 using __ireturn_type =
typename __insert_base::__ireturn_type;
275 using __map_base = __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey,
276 _Equal, _Hash, _RangeHash, _Unused,
277 _RehashPolicy, _Traits>;
279 using __rehash_base = __detail::_Rehash_base<_Key, _Value, _Alloc,
281 _Hash, _RangeHash, _Unused,
282 _RehashPolicy, _Traits>;
284 using __eq_base = __detail::_Equality<_Key, _Value, _Alloc, _ExtractKey,
285 _Equal, _Hash, _RangeHash, _Unused,
286 _RehashPolicy, _Traits>;
288 using __reuse_or_alloc_node_gen_t =
289 __detail::_ReuseOrAllocNode<__node_alloc_type>;
290 using __alloc_node_gen_t =
291 __detail::_AllocNode<__node_alloc_type>;
297 _Scoped_node(__node_ptr __n, __hashtable_alloc* __h)
298 : _M_h(__h), _M_node(__n) { }
301 template<
typename... _Args>
302 _Scoped_node(__hashtable_alloc* __h, _Args&&... __args)
304 _M_node(__h->_M_allocate_node(
std::
forward<_Args>(__args)...))
308 ~_Scoped_node() {
if (_M_node) _M_h->_M_deallocate_node(_M_node); };
310 _Scoped_node(
const _Scoped_node&) =
delete;
311 _Scoped_node& operator=(
const _Scoped_node&) =
delete;
313 __hashtable_alloc* _M_h;
317 template<
typename _Ht>
319 typename conditional<std::is_lvalue_reference<_Ht>::value,
320 const value_type&, value_type&&>::type
321 __fwd_value_for(value_type& __val)
noexcept
328 struct __hash_code_base_access : __hash_code_base
329 {
using __hash_code_base::_M_bucket_index; };
333 static_assert(
noexcept(declval<const __hash_code_base_access&>()
334 ._M_bucket_index(declval<const __node_value_type&>(),
336 "Cache the hash code or qualify your functors involved"
337 " in hash code and bucket index computation with noexcept");
340 static_assert(is_nothrow_default_constructible<_RangeHash>::value,
341 "Functor used to map hash code to bucket index"
342 " must be nothrow default constructible");
343 static_assert(
noexcept(
344 std::declval<const _RangeHash&>()((std::size_t)0, (std::size_t)0)),
345 "Functor used to map hash code to bucket index must be"
349 static_assert(is_nothrow_default_constructible<_ExtractKey>::value,
350 "_ExtractKey must be nothrow default constructible");
351 static_assert(
noexcept(
352 std::declval<const _ExtractKey&>()(std::declval<_Value>())),
353 "_ExtractKey functor must be noexcept invocable");
355 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
356 typename _ExtractKeya,
typename _Equala,
357 typename _Hasha,
typename _RangeHasha,
typename _Unuseda,
358 typename _RehashPolicya,
typename _Traitsa,
360 friend struct __detail::_Map_base;
362 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
363 typename _ExtractKeya,
typename _Equala,
364 typename _Hasha,
typename _RangeHasha,
typename _Unuseda,
365 typename _RehashPolicya,
typename _Traitsa>
366 friend struct __detail::_Insert_base;
368 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
369 typename _ExtractKeya,
typename _Equala,
370 typename _Hasha,
typename _RangeHasha,
typename _Unuseda,
371 typename _RehashPolicya,
typename _Traitsa,
372 bool _Constant_iteratorsa>
373 friend struct __detail::_Insert;
375 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
376 typename _ExtractKeya,
typename _Equala,
377 typename _Hasha,
typename _RangeHasha,
typename _Unuseda,
378 typename _RehashPolicya,
typename _Traitsa,
380 friend struct __detail::_Equality;
383 using size_type =
typename __hashtable_base::size_type;
384 using difference_type =
typename __hashtable_base::difference_type;
386#if __cplusplus > 201402L
387 using node_type = _Node_handle<_Key, _Value, __node_alloc_type>;
388 using insert_return_type = _Node_insert_return<iterator, node_type>;
392 __buckets_ptr _M_buckets = &_M_single_bucket;
393 size_type _M_bucket_count = 1;
394 __node_base _M_before_begin;
395 size_type _M_element_count = 0;
396 _RehashPolicy _M_rehash_policy;
404 __node_base_ptr _M_single_bucket =
nullptr;
410 _M_buckets[_M_bucket_index(*_M_begin())] = &_M_before_begin;
414 _M_update_bbegin(__node_ptr __n)
416 _M_before_begin._M_nxt = __n;
421 _M_uses_single_bucket(__buckets_ptr __bkts)
const
422 {
return __builtin_expect(__bkts == &_M_single_bucket,
false); }
425 _M_uses_single_bucket()
const
426 {
return _M_uses_single_bucket(_M_buckets); }
429 _M_base_alloc() {
return *
this; }
432 _M_allocate_buckets(size_type __bkt_count)
434 if (__builtin_expect(__bkt_count == 1,
false))
436 _M_single_bucket =
nullptr;
437 return &_M_single_bucket;
440 return __hashtable_alloc::_M_allocate_buckets(__bkt_count);
444 _M_deallocate_buckets(__buckets_ptr __bkts, size_type __bkt_count)
446 if (_M_uses_single_bucket(__bkts))
449 __hashtable_alloc::_M_deallocate_buckets(__bkts, __bkt_count);
453 _M_deallocate_buckets()
454 { _M_deallocate_buckets(_M_buckets, _M_bucket_count); }
459 _M_bucket_begin(size_type __bkt)
const;
463 {
return static_cast<__node_ptr
>(_M_before_begin._M_nxt); }
467 template<
typename _Ht>
469 _M_assign_elements(_Ht&&);
471 template<
typename _Ht,
typename _NodeGenerator>
473 _M_assign(_Ht&&,
const _NodeGenerator&);
476 _M_move_assign(_Hashtable&&, true_type);
479 _M_move_assign(_Hashtable&&, false_type);
484 _Hashtable(const _Hash& __h, const _Equal& __eq,
485 const allocator_type& __a)
486 : __hashtable_base(__h, __eq),
487 __hashtable_alloc(__node_alloc_type(__a)),
488 __enable_default_ctor(_Enable_default_constructor_tag{})
491 template<
bool _No_realloc = true>
492 static constexpr bool
495#if __cplusplus <= 201402L
496 return __and_<__bool_constant<_No_realloc>,
497 is_nothrow_copy_constructible<_Hash>,
498 is_nothrow_copy_constructible<_Equal>>::value;
500 if constexpr (_No_realloc)
501 if constexpr (is_nothrow_copy_constructible<_Hash>())
502 return is_nothrow_copy_constructible<_Equal>();
507 _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a,
509 noexcept(_S_nothrow_move());
511 _Hashtable(_Hashtable&&, __node_alloc_type&&,
514 template<
typename _InputIterator>
515 _Hashtable(_InputIterator __first, _InputIterator __last,
516 size_type __bkt_count_hint,
517 const _Hash&,
const _Equal&,
const allocator_type&,
520 template<
typename _InputIterator>
521 _Hashtable(_InputIterator __first, _InputIterator __last,
522 size_type __bkt_count_hint,
523 const _Hash&,
const _Equal&,
const allocator_type&,
528 _Hashtable() =
default;
530 _Hashtable(
const _Hashtable&);
532 _Hashtable(
const _Hashtable&,
const allocator_type&);
535 _Hashtable(size_type __bkt_count_hint,
536 const _Hash& __hf = _Hash(),
537 const key_equal& __eql = key_equal(),
538 const allocator_type& __a = allocator_type());
541 _Hashtable(_Hashtable&& __ht)
542 noexcept(_S_nothrow_move())
543 : _Hashtable(
std::
move(__ht),
std::
move(__ht._M_node_allocator()),
547 _Hashtable(_Hashtable&& __ht,
const allocator_type& __a)
548 noexcept(_S_nothrow_move<__node_alloc_traits::_S_always_equal()>())
549 : _Hashtable(
std::
move(__ht), __node_alloc_type(__a),
550 typename __node_alloc_traits::is_always_equal{})
554 _Hashtable(
const allocator_type& __a)
555 : __hashtable_alloc(__node_alloc_type(__a)),
556 __enable_default_ctor(_Enable_default_constructor_tag{})
559 template<
typename _InputIterator>
560 _Hashtable(_InputIterator __f, _InputIterator __l,
561 size_type __bkt_count_hint = 0,
562 const _Hash& __hf = _Hash(),
563 const key_equal& __eql = key_equal(),
564 const allocator_type& __a = allocator_type())
565 : _Hashtable(__f, __l, __bkt_count_hint, __hf, __eql, __a,
569 _Hashtable(initializer_list<value_type> __l,
570 size_type __bkt_count_hint = 0,
571 const _Hash& __hf = _Hash(),
572 const key_equal& __eql = key_equal(),
573 const allocator_type& __a = allocator_type())
574 : _Hashtable(__l.
begin(), __l.
end(), __bkt_count_hint,
575 __hf, __eql, __a, __unique_keys{})
579 operator=(
const _Hashtable& __ht);
582 operator=(_Hashtable&& __ht)
583 noexcept(__node_alloc_traits::_S_nothrow_move()
584 && is_nothrow_move_assignable<_Hash>::value
585 && is_nothrow_move_assignable<_Equal>::value)
587 constexpr bool __move_storage =
588 __node_alloc_traits::_S_propagate_on_move_assign()
589 || __node_alloc_traits::_S_always_equal();
590 _M_move_assign(
std::move(__ht), __bool_constant<__move_storage>());
595 operator=(initializer_list<value_type> __l)
597 __reuse_or_alloc_node_gen_t __roan(_M_begin(), *
this);
598 _M_before_begin._M_nxt =
nullptr;
602 auto __l_bkt_count = _M_rehash_policy._M_bkt_for_elements(__l.size());
605 if (_M_bucket_count < __l_bkt_count)
606 rehash(__l_bkt_count);
608 this->_M_insert_range(__l.begin(), __l.end(), __roan, __unique_keys{});
612 ~_Hashtable() noexcept;
616 noexcept(__and_<__is_nothrow_swappable<_Hash>,
617 __is_nothrow_swappable<_Equal>>::value);
622 {
return iterator(_M_begin()); }
625 begin() const noexcept
626 {
return const_iterator(_M_begin()); }
630 {
return iterator(
nullptr); }
634 {
return const_iterator(
nullptr); }
638 {
return const_iterator(_M_begin()); }
641 cend() const noexcept
642 {
return const_iterator(
nullptr); }
645 size() const noexcept
646 {
return _M_element_count; }
648 _GLIBCXX_NODISCARD
bool
649 empty() const noexcept
650 {
return size() == 0; }
653 get_allocator() const noexcept
654 {
return allocator_type(this->_M_node_allocator()); }
657 max_size() const noexcept
658 {
return __node_alloc_traits::max_size(this->_M_node_allocator()); }
663 {
return this->_M_eq(); }
669 bucket_count() const noexcept
670 {
return _M_bucket_count; }
673 max_bucket_count() const noexcept
674 {
return max_size(); }
677 bucket_size(size_type __bkt)
const
681 bucket(
const key_type& __k)
const
682 {
return _M_bucket_index(this->_M_hash_code(__k)); }
685 begin(size_type __bkt)
687 return local_iterator(*
this, _M_bucket_begin(__bkt),
688 __bkt, _M_bucket_count);
693 {
return local_iterator(*
this,
nullptr, __bkt, _M_bucket_count); }
696 begin(size_type __bkt)
const
698 return const_local_iterator(*
this, _M_bucket_begin(__bkt),
699 __bkt, _M_bucket_count);
703 end(size_type __bkt)
const
704 {
return const_local_iterator(*
this,
nullptr, __bkt, _M_bucket_count); }
708 cbegin(size_type __bkt)
const
710 return const_local_iterator(*
this, _M_bucket_begin(__bkt),
711 __bkt, _M_bucket_count);
715 cend(size_type __bkt)
const
716 {
return const_local_iterator(*
this,
nullptr, __bkt, _M_bucket_count); }
719 load_factor() const noexcept
721 return static_cast<float>(
size()) /
static_cast<float>(bucket_count());
730 __rehash_policy()
const
731 {
return _M_rehash_policy; }
734 __rehash_policy(
const _RehashPolicy& __pol)
735 { _M_rehash_policy = __pol; }
739 find(
const key_type& __k);
742 find(
const key_type& __k)
const;
745 count(
const key_type& __k)
const;
748 equal_range(
const key_type& __k);
751 equal_range(
const key_type& __k)
const;
753#if __cplusplus >= 202002L
754#define __cpp_lib_generic_unordered_lookup 201811L
756 template<
typename _Kt,
757 typename = __has_is_transparent_t<_Hash, _Kt>,
758 typename = __has_is_transparent_t<_Equal, _Kt>>
760 _M_find_tr(
const _Kt& __k);
762 template<
typename _Kt,
763 typename = __has_is_transparent_t<_Hash, _Kt>,
764 typename = __has_is_transparent_t<_Equal, _Kt>>
766 _M_find_tr(
const _Kt& __k)
const;
768 template<
typename _Kt,
769 typename = __has_is_transparent_t<_Hash, _Kt>,
770 typename = __has_is_transparent_t<_Equal, _Kt>>
772 _M_count_tr(
const _Kt& __k)
const;
774 template<
typename _Kt,
775 typename = __has_is_transparent_t<_Hash, _Kt>,
776 typename = __has_is_transparent_t<_Equal, _Kt>>
777 pair<iterator, iterator>
778 _M_equal_range_tr(
const _Kt& __k);
780 template<
typename _Kt,
781 typename = __has_is_transparent_t<_Hash, _Kt>,
782 typename = __has_is_transparent_t<_Equal, _Kt>>
783 pair<const_iterator, const_iterator>
784 _M_equal_range_tr(
const _Kt& __k)
const;
790 _M_bucket_index(
const __node_value_type& __n)
const noexcept
791 {
return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); }
794 _M_bucket_index(__hash_code __c)
const
795 {
return __hash_code_base::_M_bucket_index(__c, _M_bucket_count); }
800 _M_find_before_node(size_type,
const key_type&, __hash_code)
const;
802 template<
typename _Kt>
804 _M_find_before_node_tr(size_type,
const _Kt&, __hash_code)
const;
807 _M_find_node(size_type __bkt,
const key_type& __key,
808 __hash_code __c)
const
810 __node_base_ptr __before_n = _M_find_before_node(__bkt, __key, __c);
812 return static_cast<__node_ptr
>(__before_n->_M_nxt);
816 template<
typename _Kt>
818 _M_find_node_tr(size_type __bkt,
const _Kt& __key,
819 __hash_code __c)
const
821 auto __before_n = _M_find_before_node_tr(__bkt, __key, __c);
823 return static_cast<__node_ptr
>(__before_n->_M_nxt);
829 _M_insert_bucket_begin(size_type, __node_ptr);
833 _M_remove_bucket_begin(size_type __bkt, __node_ptr __next_n,
834 size_type __next_bkt);
838 _M_get_previous_node(size_type __bkt, __node_ptr __n);
844 _M_insert_unique_node(size_type __bkt, __hash_code,
845 __node_ptr __n, size_type __n_elt = 1);
850 _M_insert_multi_node(__node_ptr __hint,
851 __hash_code __code, __node_ptr __n);
853 template<
typename... _Args>
855 _M_emplace(true_type __uks, _Args&&... __args);
857 template<
typename... _Args>
859 _M_emplace(false_type __uks, _Args&&... __args)
860 {
return _M_emplace(
cend(), __uks, std::forward<_Args>(__args)...); }
863 template<
typename... _Args>
865 _M_emplace(const_iterator, true_type __uks, _Args&&... __args)
866 {
return _M_emplace(__uks, std::forward<_Args>(__args)...).first; }
868 template<
typename... _Args>
870 _M_emplace(const_iterator, false_type __uks, _Args&&... __args);
872 template<
typename _Arg,
typename _NodeGenerator>
874 _M_insert(_Arg&&,
const _NodeGenerator&, true_type __uks);
876 template<
typename _Arg,
typename _NodeGenerator>
878 _M_insert(_Arg&& __arg,
const _NodeGenerator& __node_gen,
881 return _M_insert(
cend(), std::forward<_Arg>(__arg), __node_gen,
886 template<
typename _Arg,
typename _NodeGenerator>
888 _M_insert(const_iterator, _Arg&& __arg,
889 const _NodeGenerator& __node_gen, true_type __uks)
892 _M_insert(std::forward<_Arg>(__arg), __node_gen, __uks).first;
896 template<
typename _Arg,
typename _NodeGenerator>
898 _M_insert(const_iterator, _Arg&&,
899 const _NodeGenerator&, false_type __uks);
902 _M_erase(true_type __uks,
const key_type&);
905 _M_erase(false_type __uks,
const key_type&);
908 _M_erase(size_type __bkt, __node_base_ptr __prev_n, __node_ptr __n);
912 template<
typename... _Args>
914 emplace(_Args&&... __args)
915 {
return _M_emplace(__unique_keys{}, std::forward<_Args>(__args)...); }
917 template<
typename... _Args>
919 emplace_hint(const_iterator __hint, _Args&&... __args)
921 return _M_emplace(__hint, __unique_keys{},
922 std::forward<_Args>(__args)...);
929 erase(const_iterator);
934 {
return erase(const_iterator(__it)); }
937 erase(
const key_type& __k)
938 {
return _M_erase(__unique_keys{}, __k); }
941 erase(const_iterator, const_iterator);
948 void rehash(size_type __bkt_count);
953#if __cplusplus > 201402L
956 _M_reinsert_node(node_type&& __nh)
958 insert_return_type __ret;
960 __ret.position =
end();
963 __glibcxx_assert(get_allocator() == __nh.get_allocator());
965 const key_type& __k = __nh._M_key();
966 __hash_code __code = this->_M_hash_code(__k);
967 size_type __bkt = _M_bucket_index(__code);
968 if (__node_ptr __n = _M_find_node(__bkt, __k, __code))
971 __ret.position = iterator(__n);
972 __ret.inserted =
false;
977 = _M_insert_unique_node(__bkt, __code, __nh._M_ptr);
978 __nh._M_ptr =
nullptr;
979 __ret.inserted =
true;
987 _M_reinsert_node_multi(const_iterator __hint, node_type&& __nh)
992 __glibcxx_assert(get_allocator() == __nh.get_allocator());
994 const key_type& __k = __nh._M_key();
995 auto __code = this->_M_hash_code(__k);
997 = _M_insert_multi_node(__hint._M_cur, __code, __nh._M_ptr);
998 __nh._M_ptr =
nullptr;
1004 _M_extract_node(
size_t __bkt, __node_base_ptr __prev_n)
1006 __node_ptr __n =
static_cast<__node_ptr
>(__prev_n->_M_nxt);
1007 if (__prev_n == _M_buckets[__bkt])
1008 _M_remove_bucket_begin(__bkt, __n->_M_next(),
1009 __n->_M_nxt ? _M_bucket_index(*__n->_M_next()) : 0);
1010 else if (__n->_M_nxt)
1012 size_type __next_bkt = _M_bucket_index(*__n->_M_next());
1013 if (__next_bkt != __bkt)
1014 _M_buckets[__next_bkt] = __prev_n;
1017 __prev_n->_M_nxt = __n->_M_nxt;
1018 __n->_M_nxt =
nullptr;
1020 return { __n, this->_M_node_allocator() };
1026 extract(const_iterator __pos)
1028 size_t __bkt = _M_bucket_index(*__pos._M_cur);
1029 return _M_extract_node(__bkt,
1030 _M_get_previous_node(__bkt, __pos._M_cur));
1035 extract(
const _Key& __k)
1038 __hash_code __code = this->_M_hash_code(__k);
1039 std::size_t __bkt = _M_bucket_index(__code);
1040 if (__node_base_ptr __prev_node = _M_find_before_node(__bkt, __k, __code))
1041 __nh = _M_extract_node(__bkt, __prev_node);
1046 template<
typename _Compatible_Hashtable>
1048 _M_merge_unique(_Compatible_Hashtable& __src)
noexcept
1050 static_assert(is_same_v<
typename _Compatible_Hashtable::node_type,
1051 node_type>,
"Node types are compatible");
1052 __glibcxx_assert(get_allocator() == __src.get_allocator());
1054 auto __n_elt = __src.size();
1055 for (
auto __i = __src.begin(), __end = __src.end(); __i != __end;)
1058 const key_type& __k = _ExtractKey{}(*__pos);
1059 __hash_code __code = this->_M_hash_code(__k);
1060 size_type __bkt = _M_bucket_index(__code);
1061 if (_M_find_node(__bkt, __k, __code) ==
nullptr)
1063 auto __nh = __src.extract(__pos);
1064 _M_insert_unique_node(__bkt, __code, __nh._M_ptr, __n_elt);
1065 __nh._M_ptr =
nullptr;
1068 else if (__n_elt != 1)
1074 template<
typename _Compatible_Hashtable>
1076 _M_merge_multi(_Compatible_Hashtable& __src)
noexcept
1078 static_assert(is_same_v<
typename _Compatible_Hashtable::node_type,
1079 node_type>,
"Node types are compatible");
1080 __glibcxx_assert(get_allocator() == __src.get_allocator());
1082 this->reserve(
size() + __src.size());
1083 for (
auto __i = __src.begin(), __end = __src.end(); __i != __end;)
1084 _M_reinsert_node_multi(
cend(), __src.extract(__i++));
1090 void _M_rehash_aux(size_type __bkt_count, true_type __uks);
1093 void _M_rehash_aux(size_type __bkt_count, false_type __uks);
1097 void _M_rehash(size_type __bkt_count,
const __rehash_state& __state);
1102 template<
typename _Key,
typename _Value,
typename _Alloc,
1103 typename _ExtractKey,
typename _Equal,
1104 typename _Hash,
typename _RangeHash,
typename _Unused,
1105 typename _RehashPolicy,
typename _Traits>
1107 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1108 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1109 _M_bucket_begin(size_type __bkt)
const
1112 __node_base_ptr __n = _M_buckets[__bkt];
1113 return __n ?
static_cast<__node_ptr
>(__n->_M_nxt) : nullptr;
1116 template<
typename _Key,
typename _Value,
typename _Alloc,
1117 typename _ExtractKey,
typename _Equal,
1118 typename _Hash,
typename _RangeHash,
typename _Unused,
1119 typename _RehashPolicy,
typename _Traits>
1120 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1121 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1122 _Hashtable(size_type __bkt_count_hint,
1123 const _Hash& __h,
const _Equal& __eq,
const allocator_type& __a)
1124 : _Hashtable(__h, __eq, __a)
1126 auto __bkt_count = _M_rehash_policy._M_next_bkt(__bkt_count_hint);
1127 if (__bkt_count > _M_bucket_count)
1129 _M_buckets = _M_allocate_buckets(__bkt_count);
1130 _M_bucket_count = __bkt_count;
1134 template<
typename _Key,
typename _Value,
typename _Alloc,
1135 typename _ExtractKey,
typename _Equal,
1136 typename _Hash,
typename _RangeHash,
typename _Unused,
1137 typename _RehashPolicy,
typename _Traits>
1138 template<
typename _InputIterator>
1139 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1140 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1141 _Hashtable(_InputIterator __f, _InputIterator __l,
1142 size_type __bkt_count_hint,
1143 const _Hash& __h,
const _Equal& __eq,
1144 const allocator_type& __a, true_type )
1145 : _Hashtable(__bkt_count_hint, __h, __eq, __a)
1147 for (; __f != __l; ++__f)
1151 template<
typename _Key,
typename _Value,
typename _Alloc,
1152 typename _ExtractKey,
typename _Equal,
1153 typename _Hash,
typename _RangeHash,
typename _Unused,
1154 typename _RehashPolicy,
typename _Traits>
1155 template<
typename _InputIterator>
1156 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1157 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1158 _Hashtable(_InputIterator __f, _InputIterator __l,
1159 size_type __bkt_count_hint,
1160 const _Hash& __h,
const _Equal& __eq,
1161 const allocator_type& __a, false_type )
1162 : _Hashtable(__h, __eq, __a)
1164 auto __nb_elems = __detail::__distance_fw(__f, __l);
1166 _M_rehash_policy._M_next_bkt(
1167 std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems),
1170 if (__bkt_count > _M_bucket_count)
1172 _M_buckets = _M_allocate_buckets(__bkt_count);
1173 _M_bucket_count = __bkt_count;
1176 for (; __f != __l; ++__f)
1180 template<
typename _Key,
typename _Value,
typename _Alloc,
1181 typename _ExtractKey,
typename _Equal,
1182 typename _Hash,
typename _RangeHash,
typename _Unused,
1183 typename _RehashPolicy,
typename _Traits>
1185 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1186 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1187 operator=(
const _Hashtable& __ht)
1193 if (__node_alloc_traits::_S_propagate_on_copy_assign())
1195 auto& __this_alloc = this->_M_node_allocator();
1196 auto& __that_alloc = __ht._M_node_allocator();
1197 if (!__node_alloc_traits::_S_always_equal()
1198 && __this_alloc != __that_alloc)
1201 this->_M_deallocate_nodes(_M_begin());
1202 _M_before_begin._M_nxt =
nullptr;
1203 _M_deallocate_buckets();
1204 _M_buckets =
nullptr;
1205 std::__alloc_on_copy(__this_alloc, __that_alloc);
1206 __hashtable_base::operator=(__ht);
1207 _M_bucket_count = __ht._M_bucket_count;
1208 _M_element_count = __ht._M_element_count;
1209 _M_rehash_policy = __ht._M_rehash_policy;
1210 __alloc_node_gen_t __alloc_node_gen(*
this);
1213 _M_assign(__ht, __alloc_node_gen);
1220 __throw_exception_again;
1224 std::__alloc_on_copy(__this_alloc, __that_alloc);
1228 _M_assign_elements(__ht);
1232 template<
typename _Key,
typename _Value,
typename _Alloc,
1233 typename _ExtractKey,
typename _Equal,
1234 typename _Hash,
typename _RangeHash,
typename _Unused,
1235 typename _RehashPolicy,
typename _Traits>
1236 template<
typename _Ht>
1238 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1239 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1240 _M_assign_elements(_Ht&& __ht)
1242 __buckets_ptr __former_buckets =
nullptr;
1243 std::size_t __former_bucket_count = _M_bucket_count;
1244 const __rehash_state& __former_state = _M_rehash_policy._M_state();
1246 if (_M_bucket_count != __ht._M_bucket_count)
1248 __former_buckets = _M_buckets;
1249 _M_buckets = _M_allocate_buckets(__ht._M_bucket_count);
1250 _M_bucket_count = __ht._M_bucket_count;
1253 __builtin_memset(_M_buckets, 0,
1254 _M_bucket_count *
sizeof(__node_base_ptr));
1258 __hashtable_base::operator=(std::forward<_Ht>(__ht));
1259 _M_element_count = __ht._M_element_count;
1260 _M_rehash_policy = __ht._M_rehash_policy;
1261 __reuse_or_alloc_node_gen_t __roan(_M_begin(), *
this);
1262 _M_before_begin._M_nxt =
nullptr;
1263 _M_assign(std::forward<_Ht>(__ht), __roan);
1264 if (__former_buckets)
1265 _M_deallocate_buckets(__former_buckets, __former_bucket_count);
1269 if (__former_buckets)
1272 _M_deallocate_buckets();
1273 _M_rehash_policy._M_reset(__former_state);
1274 _M_buckets = __former_buckets;
1275 _M_bucket_count = __former_bucket_count;
1277 __builtin_memset(_M_buckets, 0,
1278 _M_bucket_count *
sizeof(__node_base_ptr));
1279 __throw_exception_again;
1283 template<
typename _Key,
typename _Value,
typename _Alloc,
1284 typename _ExtractKey,
typename _Equal,
1285 typename _Hash,
typename _RangeHash,
typename _Unused,
1286 typename _RehashPolicy,
typename _Traits>
1287 template<
typename _Ht,
typename _NodeGenerator>
1289 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1290 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1291 _M_assign(_Ht&& __ht,
const _NodeGenerator& __node_gen)
1293 __buckets_ptr __buckets =
nullptr;
1295 _M_buckets = __buckets = _M_allocate_buckets(_M_bucket_count);
1299 if (!__ht._M_before_begin._M_nxt)
1304 __node_ptr __ht_n = __ht._M_begin();
1306 = __node_gen(__fwd_value_for<_Ht>(__ht_n->_M_v()));
1307 this->_M_copy_code(*__this_n, *__ht_n);
1308 _M_update_bbegin(__this_n);
1311 __node_ptr __prev_n = __this_n;
1312 for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next())
1314 __this_n = __node_gen(__fwd_value_for<_Ht>(__ht_n->_M_v()));
1315 __prev_n->_M_nxt = __this_n;
1316 this->_M_copy_code(*__this_n, *__ht_n);
1317 size_type __bkt = _M_bucket_index(*__this_n);
1318 if (!_M_buckets[__bkt])
1319 _M_buckets[__bkt] = __prev_n;
1320 __prev_n = __this_n;
1327 _M_deallocate_buckets();
1328 __throw_exception_again;
1332 template<
typename _Key,
typename _Value,
typename _Alloc,
1333 typename _ExtractKey,
typename _Equal,
1334 typename _Hash,
typename _RangeHash,
typename _Unused,
1335 typename _RehashPolicy,
typename _Traits>
1337 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1338 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1341 _M_rehash_policy._M_reset();
1342 _M_bucket_count = 1;
1343 _M_single_bucket =
nullptr;
1344 _M_buckets = &_M_single_bucket;
1345 _M_before_begin._M_nxt =
nullptr;
1346 _M_element_count = 0;
1349 template<
typename _Key,
typename _Value,
typename _Alloc,
1350 typename _ExtractKey,
typename _Equal,
1351 typename _Hash,
typename _RangeHash,
typename _Unused,
1352 typename _RehashPolicy,
typename _Traits>
1354 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1355 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1356 _M_move_assign(_Hashtable&& __ht, true_type)
1361 this->_M_deallocate_nodes(_M_begin());
1362 _M_deallocate_buckets();
1363 __hashtable_base::operator=(
std::move(__ht));
1364 _M_rehash_policy = __ht._M_rehash_policy;
1365 if (!__ht._M_uses_single_bucket())
1366 _M_buckets = __ht._M_buckets;
1369 _M_buckets = &_M_single_bucket;
1370 _M_single_bucket = __ht._M_single_bucket;
1373 _M_bucket_count = __ht._M_bucket_count;
1374 _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt;
1375 _M_element_count = __ht._M_element_count;
1376 std::__alloc_on_move(this->_M_node_allocator(), __ht._M_node_allocator());
1383 template<
typename _Key,
typename _Value,
typename _Alloc,
1384 typename _ExtractKey,
typename _Equal,
1385 typename _Hash,
typename _RangeHash,
typename _Unused,
1386 typename _RehashPolicy,
typename _Traits>
1388 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1389 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1390 _M_move_assign(_Hashtable&& __ht, false_type)
1392 if (__ht._M_node_allocator() == this->_M_node_allocator())
1393 _M_move_assign(
std::move(__ht), true_type{});
1402 template<
typename _Key,
typename _Value,
typename _Alloc,
1403 typename _ExtractKey,
typename _Equal,
1404 typename _Hash,
typename _RangeHash,
typename _Unused,
1405 typename _RehashPolicy,
typename _Traits>
1406 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1407 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1408 _Hashtable(
const _Hashtable& __ht)
1409 : __hashtable_base(__ht),
1411 __rehash_base(__ht),
1413 __node_alloc_traits::_S_select_on_copy(__ht._M_node_allocator())),
1414 __enable_default_ctor(__ht),
1415 _M_buckets(nullptr),
1416 _M_bucket_count(__ht._M_bucket_count),
1417 _M_element_count(__ht._M_element_count),
1418 _M_rehash_policy(__ht._M_rehash_policy)
1420 __alloc_node_gen_t __alloc_node_gen(*
this);
1421 _M_assign(__ht, __alloc_node_gen);
1424 template<
typename _Key,
typename _Value,
typename _Alloc,
1425 typename _ExtractKey,
typename _Equal,
1426 typename _Hash,
typename _RangeHash,
typename _Unused,
1427 typename _RehashPolicy,
typename _Traits>
1428 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1429 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1430 _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a,
1432 noexcept(_S_nothrow_move())
1433 : __hashtable_base(__ht),
1435 __rehash_base(__ht),
1436 __hashtable_alloc(
std::
move(__a)),
1437 __enable_default_ctor(__ht),
1438 _M_buckets(__ht._M_buckets),
1439 _M_bucket_count(__ht._M_bucket_count),
1440 _M_before_begin(__ht._M_before_begin._M_nxt),
1441 _M_element_count(__ht._M_element_count),
1442 _M_rehash_policy(__ht._M_rehash_policy)
1445 if (__ht._M_uses_single_bucket())
1447 _M_buckets = &_M_single_bucket;
1448 _M_single_bucket = __ht._M_single_bucket;
1457 template<
typename _Key,
typename _Value,
typename _Alloc,
1458 typename _ExtractKey,
typename _Equal,
1459 typename _Hash,
typename _RangeHash,
typename _Unused,
1460 typename _RehashPolicy,
typename _Traits>
1461 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1462 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1463 _Hashtable(
const _Hashtable& __ht,
const allocator_type& __a)
1464 : __hashtable_base(__ht),
1466 __rehash_base(__ht),
1467 __hashtable_alloc(__node_alloc_type(__a)),
1468 __enable_default_ctor(__ht),
1470 _M_bucket_count(__ht._M_bucket_count),
1471 _M_element_count(__ht._M_element_count),
1472 _M_rehash_policy(__ht._M_rehash_policy)
1474 __alloc_node_gen_t __alloc_node_gen(*
this);
1475 _M_assign(__ht, __alloc_node_gen);
1478 template<
typename _Key,
typename _Value,
typename _Alloc,
1479 typename _ExtractKey,
typename _Equal,
1480 typename _Hash,
typename _RangeHash,
typename _Unused,
1481 typename _RehashPolicy,
typename _Traits>
1482 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1483 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1484 _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a,
1486 : __hashtable_base(__ht),
1488 __rehash_base(__ht),
1489 __hashtable_alloc(
std::
move(__a)),
1490 __enable_default_ctor(__ht),
1491 _M_buckets(nullptr),
1492 _M_bucket_count(__ht._M_bucket_count),
1493 _M_element_count(__ht._M_element_count),
1494 _M_rehash_policy(__ht._M_rehash_policy)
1496 if (__ht._M_node_allocator() == this->_M_node_allocator())
1498 if (__ht._M_uses_single_bucket())
1500 _M_buckets = &_M_single_bucket;
1501 _M_single_bucket = __ht._M_single_bucket;
1504 _M_buckets = __ht._M_buckets;
1508 _M_update_bbegin(__ht._M_begin());
1514 __alloc_node_gen_t __alloc_gen(*
this);
1516 using _Fwd_Ht =
typename
1517 conditional<__move_if_noexcept_cond<value_type>::value,
1518 const _Hashtable&, _Hashtable&&>::type;
1519 _M_assign(std::forward<_Fwd_Ht>(__ht), __alloc_gen);
1524 template<
typename _Key,
typename _Value,
typename _Alloc,
1525 typename _ExtractKey,
typename _Equal,
1526 typename _Hash,
typename _RangeHash,
typename _Unused,
1527 typename _RehashPolicy,
typename _Traits>
1528 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1529 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1530 ~_Hashtable() noexcept
1533 _M_deallocate_buckets();
1536 template<
typename _Key,
typename _Value,
typename _Alloc,
1537 typename _ExtractKey,
typename _Equal,
1538 typename _Hash,
typename _RangeHash,
typename _Unused,
1539 typename _RehashPolicy,
typename _Traits>
1541 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1542 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1543 swap(_Hashtable& __x)
1544 noexcept(__and_<__is_nothrow_swappable<_Hash>,
1545 __is_nothrow_swappable<_Equal>>::value)
1552 std::__alloc_on_swap(this->_M_node_allocator(), __x._M_node_allocator());
1553 std::swap(_M_rehash_policy, __x._M_rehash_policy);
1556 if (this->_M_uses_single_bucket())
1558 if (!__x._M_uses_single_bucket())
1560 _M_buckets = __x._M_buckets;
1561 __x._M_buckets = &__x._M_single_bucket;
1564 else if (__x._M_uses_single_bucket())
1566 __x._M_buckets = _M_buckets;
1567 _M_buckets = &_M_single_bucket;
1572 std::swap(_M_bucket_count, __x._M_bucket_count);
1573 std::swap(_M_before_begin._M_nxt, __x._M_before_begin._M_nxt);
1574 std::swap(_M_element_count, __x._M_element_count);
1575 std::swap(_M_single_bucket, __x._M_single_bucket);
1580 __x._M_update_bbegin();
1583 template<
typename _Key,
typename _Value,
typename _Alloc,
1584 typename _ExtractKey,
typename _Equal,
1585 typename _Hash,
typename _RangeHash,
typename _Unused,
1586 typename _RehashPolicy,
typename _Traits>
1588 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1589 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1590 find(
const key_type& __k)
1593 __hash_code __code = this->_M_hash_code(__k);
1594 std::size_t __bkt = _M_bucket_index(__code);
1595 return iterator(_M_find_node(__bkt, __k, __code));
1598 template<
typename _Key,
typename _Value,
typename _Alloc,
1599 typename _ExtractKey,
typename _Equal,
1600 typename _Hash,
typename _RangeHash,
typename _Unused,
1601 typename _RehashPolicy,
typename _Traits>
1603 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1604 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1605 find(
const key_type& __k)
const
1608 __hash_code __code = this->_M_hash_code(__k);
1609 std::size_t __bkt = _M_bucket_index(__code);
1610 return const_iterator(_M_find_node(__bkt, __k, __code));
1613#if __cplusplus > 201703L
1614 template<
typename _Key,
typename _Value,
typename _Alloc,
1615 typename _ExtractKey,
typename _Equal,
1616 typename _Hash,
typename _RangeHash,
typename _Unused,
1617 typename _RehashPolicy,
typename _Traits>
1618 template<
typename _Kt,
typename,
typename>
1620 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1621 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1622 _M_find_tr(
const _Kt& __k)
1625 __hash_code __code = this->_M_hash_code_tr(__k);
1626 std::size_t __bkt = _M_bucket_index(__code);
1627 return iterator(_M_find_node_tr(__bkt, __k, __code));
1630 template<
typename _Key,
typename _Value,
typename _Alloc,
1631 typename _ExtractKey,
typename _Equal,
1632 typename _Hash,
typename _RangeHash,
typename _Unused,
1633 typename _RehashPolicy,
typename _Traits>
1634 template<
typename _Kt,
typename,
typename>
1636 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1637 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1638 _M_find_tr(
const _Kt& __k)
const
1641 __hash_code __code = this->_M_hash_code_tr(__k);
1642 std::size_t __bkt = _M_bucket_index(__code);
1643 return const_iterator(_M_find_node_tr(__bkt, __k, __code));
1647 template<
typename _Key,
typename _Value,
typename _Alloc,
1648 typename _ExtractKey,
typename _Equal,
1649 typename _Hash,
typename _RangeHash,
typename _Unused,
1650 typename _RehashPolicy,
typename _Traits>
1652 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1653 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1654 count(
const key_type& __k)
const
1657 auto __it = find(__k);
1661 if (__unique_keys::value)
1667 size_type __result = 1;
1668 for (
auto __ref = __it++;
1669 __it._M_cur && this->_M_node_equals(*__ref._M_cur, *__it._M_cur);
1676#if __cplusplus > 201703L
1677 template<
typename _Key,
typename _Value,
typename _Alloc,
1678 typename _ExtractKey,
typename _Equal,
1679 typename _Hash,
typename _RangeHash,
typename _Unused,
1680 typename _RehashPolicy,
typename _Traits>
1681 template<
typename _Kt,
typename,
typename>
1683 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1684 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1685 _M_count_tr(
const _Kt& __k)
const
1688 __hash_code __code = this->_M_hash_code_tr(__k);
1689 std::size_t __bkt = _M_bucket_index(__code);
1690 auto __n = _M_find_node_tr(__bkt, __k, __code);
1698 size_type __result = 1;
1700 __it._M_cur && this->_M_equals_tr(__k, __code, *__it._M_cur);
1708 template<
typename _Key,
typename _Value,
typename _Alloc,
1709 typename _ExtractKey,
typename _Equal,
1710 typename _Hash,
typename _RangeHash,
typename _Unused,
1711 typename _RehashPolicy,
typename _Traits>
1713 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1714 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1715 equal_range(
const key_type& __k)
1716 -> pair<iterator, iterator>
1718 auto __ite = find(__k);
1720 return { __ite, __ite };
1722 auto __beg = __ite++;
1723 if (__unique_keys::value)
1724 return { __beg, __ite };
1729 while (__ite._M_cur && this->_M_node_equals(*__beg._M_cur, *__ite._M_cur))
1732 return { __beg, __ite };
1735 template<
typename _Key,
typename _Value,
typename _Alloc,
1736 typename _ExtractKey,
typename _Equal,
1737 typename _Hash,
typename _RangeHash,
typename _Unused,
1738 typename _RehashPolicy,
typename _Traits>
1740 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1741 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1742 equal_range(
const key_type& __k)
const
1743 -> pair<const_iterator, const_iterator>
1745 auto __ite = find(__k);
1747 return { __ite, __ite };
1749 auto __beg = __ite++;
1750 if (__unique_keys::value)
1751 return { __beg, __ite };
1756 while (__ite._M_cur && this->_M_node_equals(*__beg._M_cur, *__ite._M_cur))
1759 return { __beg, __ite };
1762#if __cplusplus > 201703L
1763 template<
typename _Key,
typename _Value,
typename _Alloc,
1764 typename _ExtractKey,
typename _Equal,
1765 typename _Hash,
typename _RangeHash,
typename _Unused,
1766 typename _RehashPolicy,
typename _Traits>
1767 template<
typename _Kt,
typename,
typename>
1769 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1770 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1771 _M_equal_range_tr(
const _Kt& __k)
1772 -> pair<iterator, iterator>
1774 __hash_code __code = this->_M_hash_code_tr(__k);
1775 std::size_t __bkt = _M_bucket_index(__code);
1776 auto __n = _M_find_node_tr(__bkt, __k, __code);
1777 iterator __ite(__n);
1779 return { __ite, __ite };
1784 auto __beg = __ite++;
1785 while (__ite._M_cur && this->_M_equals_tr(__k, __code, *__ite._M_cur))
1788 return { __beg, __ite };
1791 template<
typename _Key,
typename _Value,
typename _Alloc,
1792 typename _ExtractKey,
typename _Equal,
1793 typename _Hash,
typename _RangeHash,
typename _Unused,
1794 typename _RehashPolicy,
typename _Traits>
1795 template<
typename _Kt,
typename,
typename>
1797 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1798 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1799 _M_equal_range_tr(
const _Kt& __k)
const
1800 -> pair<const_iterator, const_iterator>
1802 __hash_code __code = this->_M_hash_code_tr(__k);
1803 std::size_t __bkt = _M_bucket_index(__code);
1804 auto __n = _M_find_node_tr(__bkt, __k, __code);
1805 const_iterator __ite(__n);
1807 return { __ite, __ite };
1812 auto __beg = __ite++;
1813 while (__ite._M_cur && this->_M_equals_tr(__k, __code, *__ite._M_cur))
1816 return { __beg, __ite };
1822 template<
typename _Key,
typename _Value,
typename _Alloc,
1823 typename _ExtractKey,
typename _Equal,
1824 typename _Hash,
typename _RangeHash,
typename _Unused,
1825 typename _RehashPolicy,
typename _Traits>
1827 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1828 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1829 _M_find_before_node(size_type __bkt,
const key_type& __k,
1830 __hash_code __code)
const
1833 __node_base_ptr __prev_p = _M_buckets[__bkt];
1837 for (__node_ptr __p =
static_cast<__node_ptr
>(__prev_p->_M_nxt);;
1838 __p = __p->_M_next())
1840 if (this->_M_equals(__k, __code, *__p))
1843 if (!__p->_M_nxt || _M_bucket_index(*__p->_M_next()) != __bkt)
1851 template<
typename _Key,
typename _Value,
typename _Alloc,
1852 typename _ExtractKey,
typename _Equal,
1853 typename _Hash,
typename _RangeHash,
typename _Unused,
1854 typename _RehashPolicy,
typename _Traits>
1855 template<
typename _Kt>
1857 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1858 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1859 _M_find_before_node_tr(size_type __bkt,
const _Kt& __k,
1860 __hash_code __code)
const
1863 __node_base_ptr __prev_p = _M_buckets[__bkt];
1867 for (__node_ptr __p =
static_cast<__node_ptr
>(__prev_p->_M_nxt);;
1868 __p = __p->_M_next())
1870 if (this->_M_equals_tr(__k, __code, *__p))
1873 if (!__p->_M_nxt || _M_bucket_index(*__p->_M_next()) != __bkt)
1881 template<
typename _Key,
typename _Value,
typename _Alloc,
1882 typename _ExtractKey,
typename _Equal,
1883 typename _Hash,
typename _RangeHash,
typename _Unused,
1884 typename _RehashPolicy,
typename _Traits>
1886 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1887 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1888 _M_insert_bucket_begin(size_type __bkt, __node_ptr __node)
1890 if (_M_buckets[__bkt])
1894 __node->_M_nxt = _M_buckets[__bkt]->_M_nxt;
1895 _M_buckets[__bkt]->_M_nxt = __node;
1902 __node->_M_nxt = _M_before_begin._M_nxt;
1903 _M_before_begin._M_nxt = __node;
1908 _M_buckets[_M_bucket_index(*__node->_M_next())] = __node;
1910 _M_buckets[__bkt] = &_M_before_begin;
1914 template<
typename _Key,
typename _Value,
typename _Alloc,
1915 typename _ExtractKey,
typename _Equal,
1916 typename _Hash,
typename _RangeHash,
typename _Unused,
1917 typename _RehashPolicy,
typename _Traits>
1919 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1920 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1921 _M_remove_bucket_begin(size_type __bkt, __node_ptr __next,
1922 size_type __next_bkt)
1924 if (!__next || __next_bkt != __bkt)
1929 _M_buckets[__next_bkt] = _M_buckets[__bkt];
1932 if (&_M_before_begin == _M_buckets[__bkt])
1933 _M_before_begin._M_nxt = __next;
1934 _M_buckets[__bkt] =
nullptr;
1938 template<
typename _Key,
typename _Value,
typename _Alloc,
1939 typename _ExtractKey,
typename _Equal,
1940 typename _Hash,
typename _RangeHash,
typename _Unused,
1941 typename _RehashPolicy,
typename _Traits>
1943 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1944 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1945 _M_get_previous_node(size_type __bkt, __node_ptr __n)
1948 __node_base_ptr __prev_n = _M_buckets[__bkt];
1949 while (__prev_n->_M_nxt != __n)
1950 __prev_n = __prev_n->_M_nxt;
1954 template<
typename _Key,
typename _Value,
typename _Alloc,
1955 typename _ExtractKey,
typename _Equal,
1956 typename _Hash,
typename _RangeHash,
typename _Unused,
1957 typename _RehashPolicy,
typename _Traits>
1958 template<
typename... _Args>
1960 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1961 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1962 _M_emplace(true_type , _Args&&... __args)
1963 -> pair<iterator, bool>
1966 _Scoped_node __node {
this, std::forward<_Args>(__args)... };
1967 const key_type& __k = _ExtractKey{}(__node._M_node->_M_v());
1968 __hash_code __code = this->_M_hash_code(__k);
1969 size_type __bkt = _M_bucket_index(__code);
1970 if (__node_ptr __p = _M_find_node(__bkt, __k, __code))
1972 return std::make_pair(iterator(__p),
false);
1975 auto __pos = _M_insert_unique_node(__bkt, __code, __node._M_node);
1976 __node._M_node =
nullptr;
1977 return { __pos,
true };
1980 template<
typename _Key,
typename _Value,
typename _Alloc,
1981 typename _ExtractKey,
typename _Equal,
1982 typename _Hash,
typename _RangeHash,
typename _Unused,
1983 typename _RehashPolicy,
typename _Traits>
1984 template<
typename... _Args>
1986 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1987 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1988 _M_emplace(const_iterator __hint, false_type ,
1993 _Scoped_node __node {
this, std::forward<_Args>(__args)... };
1994 const key_type& __k = _ExtractKey{}(__node._M_node->_M_v());
1996 __hash_code __code = this->_M_hash_code(__k);
1998 = _M_insert_multi_node(__hint._M_cur, __code, __node._M_node);
1999 __node._M_node =
nullptr;
2003 template<
typename _Key,
typename _Value,
typename _Alloc,
2004 typename _ExtractKey,
typename _Equal,
2005 typename _Hash,
typename _RangeHash,
typename _Unused,
2006 typename _RehashPolicy,
typename _Traits>
2008 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2009 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2010 _M_insert_unique_node(size_type __bkt, __hash_code __code,
2011 __node_ptr __node, size_type __n_elt)
2014 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
2016 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count,
2019 if (__do_rehash.
first)
2021 _M_rehash(__do_rehash.
second, __saved_state);
2022 __bkt = _M_bucket_index(__code);
2025 this->_M_store_code(*__node, __code);
2028 _M_insert_bucket_begin(__bkt, __node);
2030 return iterator(__node);
2033 template<
typename _Key,
typename _Value,
typename _Alloc,
2034 typename _ExtractKey,
typename _Equal,
2035 typename _Hash,
typename _RangeHash,
typename _Unused,
2036 typename _RehashPolicy,
typename _Traits>
2038 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2039 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2040 _M_insert_multi_node(__node_ptr __hint,
2041 __hash_code __code, __node_ptr __node)
2044 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
2046 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
2048 if (__do_rehash.
first)
2049 _M_rehash(__do_rehash.
second, __saved_state);
2051 this->_M_store_code(*__node, __code);
2052 const key_type& __k = _ExtractKey{}(__node->_M_v());
2053 size_type __bkt = _M_bucket_index(__code);
2057 __node_base_ptr __prev
2058 = __builtin_expect(__hint !=
nullptr,
false)
2059 && this->_M_equals(__k, __code, *__hint)
2061 : _M_find_before_node(__bkt, __k, __code);
2066 __node->_M_nxt = __prev->_M_nxt;
2067 __prev->_M_nxt = __node;
2068 if (__builtin_expect(__prev == __hint,
false))
2072 && !this->_M_equals(__k, __code, *__node->_M_next()))
2074 size_type __next_bkt = _M_bucket_index(*__node->_M_next());
2075 if (__next_bkt != __bkt)
2076 _M_buckets[__next_bkt] = __node;
2083 _M_insert_bucket_begin(__bkt, __node);
2085 return iterator(__node);
2089 template<
typename _Key,
typename _Value,
typename _Alloc,
2090 typename _ExtractKey,
typename _Equal,
2091 typename _Hash,
typename _RangeHash,
typename _Unused,
2092 typename _RehashPolicy,
typename _Traits>
2093 template<
typename _Arg,
typename _NodeGenerator>
2095 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2096 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2097 _M_insert(_Arg&& __v,
const _NodeGenerator& __node_gen,
2099 -> pair<iterator, bool>
2101 const key_type& __k = _ExtractKey{}(__v);
2102 __hash_code __code = this->_M_hash_code(__k);
2103 size_type __bkt = _M_bucket_index(__code);
2105 if (__node_ptr __node = _M_find_node(__bkt, __k, __code))
2106 return { iterator(__node),
false };
2108 _Scoped_node __node{ __node_gen(std::forward<_Arg>(__v)),
this };
2110 = _M_insert_unique_node(__bkt, __code, __node._M_node);
2111 __node._M_node =
nullptr;
2112 return { __pos,
true };
2116 template<
typename _Key,
typename _Value,
typename _Alloc,
2117 typename _ExtractKey,
typename _Equal,
2118 typename _Hash,
typename _RangeHash,
typename _Unused,
2119 typename _RehashPolicy,
typename _Traits>
2120 template<
typename _Arg,
typename _NodeGenerator>
2122 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2123 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2124 _M_insert(const_iterator __hint, _Arg&& __v,
2125 const _NodeGenerator& __node_gen,
2131 __hash_code __code = this->_M_hash_code(_ExtractKey{}(__v));
2134 _Scoped_node __node{ __node_gen(std::forward<_Arg>(__v)),
this };
2136 = _M_insert_multi_node(__hint._M_cur, __code, __node._M_node);
2137 __node._M_node =
nullptr;
2141 template<
typename _Key,
typename _Value,
typename _Alloc,
2142 typename _ExtractKey,
typename _Equal,
2143 typename _Hash,
typename _RangeHash,
typename _Unused,
2144 typename _RehashPolicy,
typename _Traits>
2146 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2147 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2148 erase(const_iterator __it)
2151 __node_ptr __n = __it._M_cur;
2152 std::size_t __bkt = _M_bucket_index(*__n);
2157 __node_base_ptr __prev_n = _M_get_previous_node(__bkt, __n);
2158 return _M_erase(__bkt, __prev_n, __n);
2161 template<
typename _Key,
typename _Value,
typename _Alloc,
2162 typename _ExtractKey,
typename _Equal,
2163 typename _Hash,
typename _RangeHash,
typename _Unused,
2164 typename _RehashPolicy,
typename _Traits>
2166 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2167 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2168 _M_erase(size_type __bkt, __node_base_ptr __prev_n, __node_ptr __n)
2171 if (__prev_n == _M_buckets[__bkt])
2172 _M_remove_bucket_begin(__bkt, __n->_M_next(),
2173 __n->_M_nxt ? _M_bucket_index(*__n->_M_next()) : 0);
2174 else if (__n->_M_nxt)
2176 size_type __next_bkt = _M_bucket_index(*__n->_M_next());
2177 if (__next_bkt != __bkt)
2178 _M_buckets[__next_bkt] = __prev_n;
2181 __prev_n->_M_nxt = __n->_M_nxt;
2182 iterator __result(__n->_M_next());
2183 this->_M_deallocate_node(__n);
2189 template<
typename _Key,
typename _Value,
typename _Alloc,
2190 typename _ExtractKey,
typename _Equal,
2191 typename _Hash,
typename _RangeHash,
typename _Unused,
2192 typename _RehashPolicy,
typename _Traits>
2194 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2195 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2196 _M_erase(true_type ,
const key_type& __k)
2199 __hash_code __code = this->_M_hash_code(__k);
2200 std::size_t __bkt = _M_bucket_index(__code);
2203 __node_base_ptr __prev_n = _M_find_before_node(__bkt, __k, __code);
2208 __node_ptr __n =
static_cast<__node_ptr
>(__prev_n->_M_nxt);
2209 _M_erase(__bkt, __prev_n, __n);
2213 template<
typename _Key,
typename _Value,
typename _Alloc,
2214 typename _ExtractKey,
typename _Equal,
2215 typename _Hash,
typename _RangeHash,
typename _Unused,
2216 typename _RehashPolicy,
typename _Traits>
2218 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2219 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2220 _M_erase(false_type ,
const key_type& __k)
2223 __hash_code __code = this->_M_hash_code(__k);
2224 std::size_t __bkt = _M_bucket_index(__code);
2227 __node_base_ptr __prev_n = _M_find_before_node(__bkt, __k, __code);
2237 __node_ptr __n =
static_cast<__node_ptr
>(__prev_n->_M_nxt);
2238 __node_ptr __n_last = __n->_M_next();
2239 while (__n_last && this->_M_node_equals(*__n, *__n_last))
2240 __n_last = __n_last->_M_next();
2242 std::size_t __n_last_bkt = __n_last ? _M_bucket_index(*__n_last) : __bkt;
2245 size_type __result = 0;
2248 __node_ptr __p = __n->_M_next();
2249 this->_M_deallocate_node(__n);
2253 while (__n != __n_last);
2255 _M_element_count -= __result;
2256 if (__prev_n == _M_buckets[__bkt])
2257 _M_remove_bucket_begin(__bkt, __n_last, __n_last_bkt);
2258 else if (__n_last_bkt != __bkt)
2259 _M_buckets[__n_last_bkt] = __prev_n;
2260 __prev_n->_M_nxt = __n_last;
2264 template<
typename _Key,
typename _Value,
typename _Alloc,
2265 typename _ExtractKey,
typename _Equal,
2266 typename _Hash,
typename _RangeHash,
typename _Unused,
2267 typename _RehashPolicy,
typename _Traits>
2269 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2270 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2271 erase(const_iterator __first, const_iterator __last)
2274 __node_ptr __n = __first._M_cur;
2275 __node_ptr __last_n = __last._M_cur;
2276 if (__n == __last_n)
2277 return iterator(__n);
2279 std::size_t __bkt = _M_bucket_index(*__n);
2281 __node_base_ptr __prev_n = _M_get_previous_node(__bkt, __n);
2282 bool __is_bucket_begin = __n == _M_bucket_begin(__bkt);
2283 std::size_t __n_bkt = __bkt;
2288 __node_ptr __tmp = __n;
2289 __n = __n->_M_next();
2290 this->_M_deallocate_node(__tmp);
2294 __n_bkt = _M_bucket_index(*__n);
2296 while (__n != __last_n && __n_bkt == __bkt);
2297 if (__is_bucket_begin)
2298 _M_remove_bucket_begin(__bkt, __n, __n_bkt);
2299 if (__n == __last_n)
2301 __is_bucket_begin =
true;
2305 if (__n && (__n_bkt != __bkt || __is_bucket_begin))
2306 _M_buckets[__n_bkt] = __prev_n;
2307 __prev_n->_M_nxt = __n;
2308 return iterator(__n);
2311 template<
typename _Key,
typename _Value,
typename _Alloc,
2312 typename _ExtractKey,
typename _Equal,
2313 typename _Hash,
typename _RangeHash,
typename _Unused,
2314 typename _RehashPolicy,
typename _Traits>
2316 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2317 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2320 this->_M_deallocate_nodes(_M_begin());
2321 __builtin_memset(_M_buckets, 0,
2322 _M_bucket_count *
sizeof(__node_base_ptr));
2323 _M_element_count = 0;
2324 _M_before_begin._M_nxt =
nullptr;
2327 template<
typename _Key,
typename _Value,
typename _Alloc,
2328 typename _ExtractKey,
typename _Equal,
2329 typename _Hash,
typename _RangeHash,
typename _Unused,
2330 typename _RehashPolicy,
typename _Traits>
2332 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2333 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2334 rehash(size_type __bkt_count)
2336 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
2338 =
std::max(_M_rehash_policy._M_bkt_for_elements(_M_element_count + 1),
2340 __bkt_count = _M_rehash_policy._M_next_bkt(__bkt_count);
2342 if (__bkt_count != _M_bucket_count)
2343 _M_rehash(__bkt_count, __saved_state);
2347 _M_rehash_policy._M_reset(__saved_state);
2350 template<
typename _Key,
typename _Value,
typename _Alloc,
2351 typename _ExtractKey,
typename _Equal,
2352 typename _Hash,
typename _RangeHash,
typename _Unused,
2353 typename _RehashPolicy,
typename _Traits>
2355 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2356 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2357 _M_rehash(size_type __bkt_count,
const __rehash_state& __state)
2361 _M_rehash_aux(__bkt_count, __unique_keys{});
2367 _M_rehash_policy._M_reset(__state);
2368 __throw_exception_again;
2373 template<
typename _Key,
typename _Value,
typename _Alloc,
2374 typename _ExtractKey,
typename _Equal,
2375 typename _Hash,
typename _RangeHash,
typename _Unused,
2376 typename _RehashPolicy,
typename _Traits>
2378 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2379 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2380 _M_rehash_aux(size_type __bkt_count, true_type )
2382 __buckets_ptr __new_buckets = _M_allocate_buckets(__bkt_count);
2383 __node_ptr __p = _M_begin();
2384 _M_before_begin._M_nxt =
nullptr;
2385 std::size_t __bbegin_bkt = 0;
2388 __node_ptr __next = __p->_M_next();
2390 = __hash_code_base::_M_bucket_index(*__p, __bkt_count);
2391 if (!__new_buckets[__bkt])
2393 __p->_M_nxt = _M_before_begin._M_nxt;
2394 _M_before_begin._M_nxt = __p;
2395 __new_buckets[__bkt] = &_M_before_begin;
2397 __new_buckets[__bbegin_bkt] = __p;
2398 __bbegin_bkt = __bkt;
2402 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2403 __new_buckets[__bkt]->_M_nxt = __p;
2409 _M_deallocate_buckets();
2410 _M_bucket_count = __bkt_count;
2411 _M_buckets = __new_buckets;
2416 template<
typename _Key,
typename _Value,
typename _Alloc,
2417 typename _ExtractKey,
typename _Equal,
2418 typename _Hash,
typename _RangeHash,
typename _Unused,
2419 typename _RehashPolicy,
typename _Traits>
2421 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2422 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2423 _M_rehash_aux(size_type __bkt_count, false_type )
2425 __buckets_ptr __new_buckets = _M_allocate_buckets(__bkt_count);
2426 __node_ptr __p = _M_begin();
2427 _M_before_begin._M_nxt =
nullptr;
2428 std::size_t __bbegin_bkt = 0;
2429 std::size_t __prev_bkt = 0;
2430 __node_ptr __prev_p =
nullptr;
2431 bool __check_bucket =
false;
2435 __node_ptr __next = __p->_M_next();
2437 = __hash_code_base::_M_bucket_index(*__p, __bkt_count);
2439 if (__prev_p && __prev_bkt == __bkt)
2444 __p->_M_nxt = __prev_p->_M_nxt;
2445 __prev_p->_M_nxt = __p;
2452 __check_bucket =
true;
2460 if (__prev_p->_M_nxt)
2462 std::size_t __next_bkt
2463 = __hash_code_base::_M_bucket_index(
2464 *__prev_p->_M_next(), __bkt_count);
2465 if (__next_bkt != __prev_bkt)
2466 __new_buckets[__next_bkt] = __prev_p;
2468 __check_bucket =
false;
2471 if (!__new_buckets[__bkt])
2473 __p->_M_nxt = _M_before_begin._M_nxt;
2474 _M_before_begin._M_nxt = __p;
2475 __new_buckets[__bkt] = &_M_before_begin;
2477 __new_buckets[__bbegin_bkt] = __p;
2478 __bbegin_bkt = __bkt;
2482 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2483 __new_buckets[__bkt]->_M_nxt = __p;
2491 if (__check_bucket && __prev_p->_M_nxt)
2493 std::size_t __next_bkt
2494 = __hash_code_base::_M_bucket_index(*__prev_p->_M_next(),
2496 if (__next_bkt != __prev_bkt)
2497 __new_buckets[__next_bkt] = __prev_p;
2500 _M_deallocate_buckets();
2501 _M_bucket_count = __bkt_count;
2502 _M_buckets = __new_buckets;
2505#if __cplusplus > 201402L
2506 template<
typename,
typename,
typename>
class _Hash_merge_helper { };
2509#if __cpp_deduction_guides >= 201606
2511 template<
typename _Hash>
2512 using _RequireNotAllocatorOrIntegral
2513 = __enable_if_t<!__or_<is_integral<_Hash>, __is_allocator<_Hash>>::value>;
2517_GLIBCXX_END_NAMESPACE_VERSION
integral_constant< bool, true > true_type
The type used as a compile-time boolean with true value.
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
void swap(any &__x, any &__y) noexcept
Exchange the states of two any objects.
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
_Tp * end(valarray< _Tp > &__va) noexcept
Return an iterator pointing to one past the last element of the valarray.
_Tp * begin(valarray< _Tp > &__va) noexcept
Return an iterator pointing to the first element of the valarray.
constexpr const _Tp & max(const _Tp &, const _Tp &)
This does what you think it does.
ISO C++ entities toplevel namespace is std.
constexpr iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
constexpr auto cend(const _Container &__cont) noexcept(noexcept(std::end(__cont))) -> decltype(std::end(__cont))
Return an iterator pointing to one past the last element of the const container.
constexpr auto empty(const _Container &__cont) noexcept(noexcept(__cont.empty())) -> decltype(__cont.empty())
Return whether a container is empty.
constexpr auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())
Return the size of a container.
constexpr auto cbegin(const _Container &__cont) noexcept(noexcept(std::begin(__cont))) -> decltype(std::begin(__cont))
Return an iterator pointing to the first element of the const container.
Struct holding two objects of arbitrary type.
_T1 first
The first member.
_T2 second
The second member.