34#pragma GCC system_header
41#ifdef __glibcxx_node_extract
45#pragma GCC diagnostic push
46#pragma GCC diagnostic ignored "-Wc++11-extensions"
48namespace std _GLIBCXX_VISIBILITY(default)
50_GLIBCXX_BEGIN_NAMESPACE_VERSION
53 template<
typename _Tp,
typename _Hash>
58 __is_nothrow_invocable<const _Hash&, const _Tp&>>>;
63 template<
typename _Equal,
typename _Hash,
typename _Allocator>
64 using _Hashtable_enable_default_ctor
65 = _Enable_default_constructor<__and_<is_default_constructible<_Equal>,
68 __detail::_Hash_node_base>;
185 template<
typename _Key,
typename _Value,
typename _Alloc,
186 typename _ExtractKey,
typename _Equal,
187 typename _Hash,
typename _RangeHash,
typename _Unused,
188 typename _RehashPolicy,
typename _Traits>
190 :
public __detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal,
191 _Hash, _RangeHash, _Unused, _Traits>,
192 public __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
193 _Hash, _RangeHash, _Unused,
194 _RehashPolicy, _Traits>,
195 public __detail::_Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
196 _Hash, _RangeHash, _Unused,
197 _RehashPolicy, _Traits>,
198 private __detail::_Hashtable_alloc<
199 __alloc_rebind<_Alloc,
200 __detail::_Hash_node<_Value,
201 _Traits::__hash_cached::value>>>,
202 private _Hashtable_enable_default_ctor<_Equal, _Hash, _Alloc>
204 static_assert(is_same<typename remove_cv<_Value>::type, _Value>::value,
205 "unordered container must have a non-const, non-volatile value_type");
206#if __cplusplus > 201703L || defined __STRICT_ANSI__
207 static_assert(is_same<typename _Alloc::value_type, _Value>{},
208 "unordered container must have the same value_type as its allocator");
210 static_assert(is_copy_constructible<_Hash>::value,
211 "hash function must be copy constructible");
213 using __traits_type = _Traits;
214 using __hash_cached =
typename __traits_type::__hash_cached;
215 using __constant_iterators =
typename __traits_type::__constant_iterators;
216 using __node_type = __detail::_Hash_node<_Value, __hash_cached::value>;
217 using __node_alloc_type = __alloc_rebind<_Alloc, __node_type>;
219 using __hashtable_alloc = __detail::_Hashtable_alloc<__node_alloc_type>;
221 using __node_value_type =
222 __detail::_Hash_node_value<_Value, __hash_cached::value>;
223 using __node_ptr =
typename __hashtable_alloc::__node_ptr;
224 using __value_alloc_traits =
225 typename __hashtable_alloc::__value_alloc_traits;
226 using __node_alloc_traits =
227 typename __hashtable_alloc::__node_alloc_traits;
228 using __node_base =
typename __hashtable_alloc::__node_base;
229 using __node_base_ptr =
typename __hashtable_alloc::__node_base_ptr;
230 using __buckets_ptr =
typename __hashtable_alloc::__buckets_ptr;
232 using __enable_default_ctor
233 = _Hashtable_enable_default_ctor<_Equal, _Hash, _Alloc>;
234 using __rehash_guard_t
235 = __detail::_RehashStateGuard<_RehashPolicy>;
238 typedef _Key key_type;
239 typedef _Value value_type;
240 typedef _Alloc allocator_type;
241 typedef _Equal key_equal;
245 typedef typename __value_alloc_traits::pointer pointer;
246 typedef typename __value_alloc_traits::const_pointer const_pointer;
247 typedef value_type& reference;
248 typedef const value_type& const_reference;
251 = __detail::_Node_iterator<_Value, __constant_iterators::value,
252 __hash_cached::value>;
255 = __detail::_Node_const_iterator<_Value, __constant_iterators::value,
256 __hash_cached::value>;
258 using local_iterator = __detail::_Local_iterator<key_type, _Value,
259 _ExtractKey, _Hash, _RangeHash, _Unused,
260 __constant_iterators::value,
261 __hash_cached::value>;
263 using const_local_iterator = __detail::_Local_const_iterator<
265 _ExtractKey, _Hash, _RangeHash, _Unused,
266 __constant_iterators::value, __hash_cached::value>;
269 using __rehash_type = _RehashPolicy;
271 using __unique_keys =
typename __traits_type::__unique_keys;
273 using __hashtable_base = __detail::
274 _Hashtable_base<_Key, _Value, _ExtractKey,
275 _Equal, _Hash, _RangeHash, _Unused, _Traits>;
277 using __hash_code_base =
typename __hashtable_base::__hash_code_base;
278 using __hash_code =
typename __hashtable_base::__hash_code;
279 using __ireturn_type = __conditional_t<__unique_keys::value,
283 using __map_base = __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey,
284 _Equal, _Hash, _RangeHash, _Unused,
285 _RehashPolicy, _Traits>;
287 using __rehash_base = __detail::_Rehash_base<_Key, _Value, _Alloc,
289 _Hash, _RangeHash, _Unused,
290 _RehashPolicy, _Traits>;
292 using __node_builder_t = __detail::_NodeBuilder<_ExtractKey>;
298 _Scoped_node(__node_ptr __n, __hashtable_alloc* __h)
299 : _M_h(__h), _M_node(__n) { }
302 template<
typename... _Args>
303 _Scoped_node(__hashtable_alloc* __h, _Args&&... __args)
305 _M_node(__h->_M_allocate_node(std::
forward<_Args>(__args)...))
309 ~_Scoped_node() {
if (_M_node) _M_h->_M_deallocate_node(_M_node); };
311 _Scoped_node(
const _Scoped_node&) =
delete;
312 _Scoped_node& operator=(
const _Scoped_node&) =
delete;
314 __hashtable_alloc* _M_h;
322 struct __hash_code_base_access : __hash_code_base
323 {
using __hash_code_base::_M_bucket_index; };
326 static_assert(is_nothrow_default_constructible<_RangeHash>::value,
327 "Functor used to map hash code to bucket index"
328 " must be nothrow default constructible");
329 static_assert(
noexcept(
331 "Functor used to map hash code to bucket index must be"
335 static_assert(is_nothrow_default_constructible<_ExtractKey>::value,
336 "_ExtractKey must be nothrow default constructible");
337 static_assert(
noexcept(
339 "_ExtractKey functor must be noexcept invocable");
341 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
342 typename _ExtractKeya,
typename _Equala,
343 typename _Hasha,
typename _RangeHasha,
typename _Unuseda,
344 typename _RehashPolicya,
typename _Traitsa,
346 friend struct __detail::_Map_base;
349 using size_type =
typename __hashtable_base::size_type;
350 using difference_type =
typename __hashtable_base::difference_type;
352#ifdef __glibcxx_node_extract
353 using node_type = _Node_handle<_Key, _Value, __node_alloc_type>;
354 using insert_return_type = _Node_insert_return<iterator, node_type>;
358 __buckets_ptr _M_buckets = &_M_single_bucket;
359 size_type _M_bucket_count = 1;
360 __node_base _M_before_begin;
361 size_type _M_element_count = 0;
362 _RehashPolicy _M_rehash_policy;
370 __node_base_ptr _M_single_bucket =
nullptr;
375 if (
auto __begin = _M_begin())
376 _M_buckets[_M_bucket_index(*__begin)] = &_M_before_begin;
380 _M_update_bbegin(__node_ptr __n)
382 _M_before_begin._M_nxt = __n;
387 _M_uses_single_bucket(__buckets_ptr __bkts)
const
388 {
return __builtin_expect(__bkts == &_M_single_bucket,
false); }
391 _M_uses_single_bucket()
const
392 {
return _M_uses_single_bucket(_M_buckets); }
394 static constexpr size_t
395 __small_size_threshold() noexcept
398 __detail::_Hashtable_hash_traits<_Hash>::__small_size_threshold();
402 _M_base_alloc() {
return *
this; }
405 _M_allocate_buckets(size_type __bkt_count)
407 if (__builtin_expect(__bkt_count == 1,
false))
409 _M_single_bucket =
nullptr;
410 return &_M_single_bucket;
413 return __hashtable_alloc::_M_allocate_buckets(__bkt_count);
417 _M_deallocate_buckets(__buckets_ptr __bkts, size_type __bkt_count)
419 if (_M_uses_single_bucket(__bkts))
422 __hashtable_alloc::_M_deallocate_buckets(__bkts, __bkt_count);
426 _M_deallocate_buckets()
427 { _M_deallocate_buckets(_M_buckets, _M_bucket_count); }
432 _M_bucket_begin(size_type __bkt)
const
434 __node_base_ptr __n = _M_buckets[__bkt];
435 return __n ?
static_cast<__node_ptr
>(__n->_M_nxt) : nullptr;
440 {
return static_cast<__node_ptr
>(_M_before_begin._M_nxt); }
444 template<
typename _Ht>
446 _M_assign_elements(_Ht&&);
448 template<
typename _Ht>
450 _M_assign(_Ht&& __ht)
452 __detail::_AllocNode<__node_alloc_type> __alloc_node_gen(*
this);
456 template<
typename _Ht,
typename _NodeGenerator>
458 _M_assign(_Ht&&, _NodeGenerator&);
461 _M_move_assign(_Hashtable&&, true_type);
464 _M_move_assign(_Hashtable&&, false_type);
469 _Hashtable(const _Hash& __h, const _Equal& __eq,
470 const allocator_type& __a)
471 : __hashtable_base(__h, __eq),
472 __hashtable_alloc(__node_alloc_type(__a)),
473 __enable_default_ctor(_Enable_default_constructor_tag{})
476 template<
bool _No_realloc = true>
477 static constexpr bool
480#if __cpp_constexpr >= 201304
481# pragma GCC diagnostic push
482# pragma GCC diagnostic ignored "-Wc++17-extensions"
483 if constexpr (_No_realloc)
484 if constexpr (is_nothrow_copy_constructible<_Hash>::value)
485 return is_nothrow_copy_constructible<_Equal>::value;
487# pragma GCC diagnostic pop
489 return __and_<__bool_constant<_No_realloc>,
490 is_nothrow_copy_constructible<_Hash>,
491 is_nothrow_copy_constructible<_Equal>>::value;
495 _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a,
497 noexcept(_S_nothrow_move());
499 _Hashtable(_Hashtable&&, __node_alloc_type&&,
502 template<
typename _InputIterator>
503 _Hashtable(_InputIterator __first, _InputIterator __last,
504 size_type __bkt_count_hint,
505 const _Hash&,
const _Equal&,
const allocator_type&,
508 template<
typename _InputIterator>
509 _Hashtable(_InputIterator __first, _InputIterator __last,
510 size_type __bkt_count_hint,
511 const _Hash&,
const _Equal&,
const allocator_type&,
516 _Hashtable() =
default;
518 _Hashtable(
const _Hashtable&);
520 _Hashtable(
const _Hashtable&,
const allocator_type&);
523 _Hashtable(size_type __bkt_count_hint,
524 const _Hash& __hf = _Hash(),
525 const key_equal& __eql = key_equal(),
526 const allocator_type& __a = allocator_type());
529 _Hashtable(_Hashtable&& __ht)
530 noexcept(_S_nothrow_move())
531 : _Hashtable(std::move(__ht), std::move(__ht._M_node_allocator()),
535 _Hashtable(_Hashtable&& __ht,
const allocator_type& __a)
536 noexcept(_S_nothrow_move<__node_alloc_traits::_S_always_equal()>())
537 : _Hashtable(std::move(__ht), __node_alloc_type(__a),
538 typename __node_alloc_traits::is_always_equal{})
542 _Hashtable(
const allocator_type& __a)
543 : __hashtable_alloc(__node_alloc_type(__a)),
544 __enable_default_ctor(_Enable_default_constructor_tag{})
547 template<
typename _InputIterator>
548 _Hashtable(_InputIterator __f, _InputIterator __l,
549 size_type __bkt_count_hint = 0,
550 const _Hash& __hf = _Hash(),
551 const key_equal& __eql = key_equal(),
552 const allocator_type& __a = allocator_type())
553 : _Hashtable(__f, __l, __bkt_count_hint, __hf, __eql, __a,
557 _Hashtable(initializer_list<value_type> __l,
558 size_type __bkt_count_hint = 0,
559 const _Hash& __hf = _Hash(),
560 const key_equal& __eql = key_equal(),
561 const allocator_type& __a = allocator_type())
562 : _Hashtable(__l.begin(), __l.end(), __bkt_count_hint,
563 __hf, __eql, __a, __unique_keys{})
567 operator=(
const _Hashtable& __ht);
570 operator=(_Hashtable&& __ht)
571 noexcept(__node_alloc_traits::_S_nothrow_move()
572 && is_nothrow_move_assignable<_Hash>::value
573 && is_nothrow_move_assignable<_Equal>::value)
575 constexpr bool __move_storage =
576 __node_alloc_traits::_S_propagate_on_move_assign()
577 || __node_alloc_traits::_S_always_equal();
578 _M_move_assign(
std::move(__ht), __bool_constant<__move_storage>());
582#pragma GCC diagnostic push
583#pragma GCC diagnostic ignored "-Wc++17-extensions"
585 operator=(initializer_list<value_type> __l)
587 using __reuse_or_alloc_node_gen_t =
588 __detail::_ReuseOrAllocNode<__node_alloc_type>;
590 __reuse_or_alloc_node_gen_t __roan(_M_begin(), *
this);
591 _M_before_begin._M_nxt =
nullptr;
595 auto __l_bkt_count = _M_rehash_policy._M_bkt_for_elements(__l.size());
599 if (_M_bucket_count < __l_bkt_count)
600 rehash(__l_bkt_count);
604 for (
auto& __e : __l)
606 const key_type& __k = _ExtractKey{}(__e);
608 if constexpr (__unique_keys::value)
610 if (
auto __loc = _M_locate(__k))
614 __code = __loc._M_hash_code;
615 __bkt = __loc._M_bucket_index;
620 __code = this->_M_hash_code(__k);
621 __bkt = _M_bucket_index(__code);
624 _M_insert_unique_node(__bkt, __code, __roan(__e));
629#pragma GCC diagnostic pop
631 ~_Hashtable() noexcept;
635 noexcept(__and_<__is_nothrow_swappable<_Hash>,
636 __is_nothrow_swappable<_Equal>>::value);
641 {
return iterator(_M_begin()); }
644 begin() const noexcept
645 {
return const_iterator(_M_begin()); }
649 {
return iterator(
nullptr); }
653 {
return const_iterator(
nullptr); }
656 cbegin() const noexcept
657 {
return const_iterator(_M_begin()); }
660 cend() const noexcept
661 {
return const_iterator(
nullptr); }
664 size() const noexcept
665 {
return _M_element_count; }
667 _GLIBCXX_NODISCARD
bool
668 empty() const noexcept
669 {
return size() == 0; }
672 get_allocator() const noexcept
673 {
return allocator_type(this->_M_node_allocator()); }
676 max_size() const noexcept
677 {
return __node_alloc_traits::max_size(this->_M_node_allocator()); }
682 {
return this->_M_eq(); }
688 bucket_count() const noexcept
689 {
return _M_bucket_count; }
692 max_bucket_count() const noexcept
693 {
return max_size(); }
696 bucket_size(size_type __bkt)
const
700 bucket(
const key_type& __k)
const
701 {
return _M_bucket_index(this->_M_hash_code(__k)); }
704 begin(size_type __bkt)
706 return local_iterator(*
this, _M_bucket_begin(__bkt),
707 __bkt, _M_bucket_count);
712 {
return local_iterator(*
this,
nullptr, __bkt, _M_bucket_count); }
715 begin(size_type __bkt)
const
717 return const_local_iterator(*
this, _M_bucket_begin(__bkt),
718 __bkt, _M_bucket_count);
722 end(size_type __bkt)
const
723 {
return const_local_iterator(*
this,
nullptr, __bkt, _M_bucket_count); }
727 cbegin(size_type __bkt)
const
729 return const_local_iterator(*
this, _M_bucket_begin(__bkt),
730 __bkt, _M_bucket_count);
734 cend(size_type __bkt)
const
735 {
return const_local_iterator(*
this,
nullptr, __bkt, _M_bucket_count); }
738 load_factor() const noexcept
740 return static_cast<float>(size()) /
static_cast<float>(bucket_count());
749 __rehash_policy()
const
750 {
return _M_rehash_policy; }
753 __rehash_policy(
const _RehashPolicy& __pol)
754 { _M_rehash_policy = __pol; }
758 find(
const key_type& __k);
761 find(
const key_type& __k)
const;
764 count(
const key_type& __k)
const;
767 equal_range(
const key_type& __k);
770 equal_range(
const key_type& __k)
const;
772#ifdef __glibcxx_generic_unordered_lookup
773 template<
typename _Kt,
774 typename = __has_is_transparent_t<_Hash, _Kt>,
775 typename = __has_is_transparent_t<_Equal, _Kt>>
777 _M_find_tr(
const _Kt& __k);
779 template<
typename _Kt,
780 typename = __has_is_transparent_t<_Hash, _Kt>,
781 typename = __has_is_transparent_t<_Equal, _Kt>>
783 _M_find_tr(
const _Kt& __k)
const;
785 template<
typename _Kt,
786 typename = __has_is_transparent_t<_Hash, _Kt>,
787 typename = __has_is_transparent_t<_Equal, _Kt>>
789 _M_count_tr(
const _Kt& __k)
const;
791 template<
typename _Kt,
792 typename = __has_is_transparent_t<_Hash, _Kt>,
793 typename = __has_is_transparent_t<_Equal, _Kt>>
794 pair<iterator, iterator>
795 _M_equal_range_tr(
const _Kt& __k);
797 template<
typename _Kt,
798 typename = __has_is_transparent_t<_Hash, _Kt>,
799 typename = __has_is_transparent_t<_Equal, _Kt>>
800 pair<const_iterator, const_iterator>
801 _M_equal_range_tr(
const _Kt& __k)
const;
804 void _M_rehash_insert(size_type __n);
809 _M_bucket_index(
const __node_value_type& __n)
const noexcept
810 {
return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); }
813 _M_bucket_index(__hash_code __c)
const
814 {
return __hash_code_base::_M_bucket_index(__c, _M_bucket_count); }
816#pragma GCC diagnostic push
817#pragma GCC diagnostic ignored "-Wc++17-extensions"
822 _M_hash_code_ext(
const __node_value_type& __from)
const
824 if constexpr (__and_<__hash_cached, is_empty<_Hash>>::value)
825 return __from._M_hash_code;
827 return this->_M_hash_code(_ExtractKey{}(__from._M_v()));
833 _M_bucket_index_ext(
const __node_value_type& __from)
const
834 {
return _RangeHash{}(_M_hash_code_ext(__from), _M_bucket_count); }
837 _M_copy_code(__node_value_type& __to,
838 const __node_value_type& __from)
const
840 if constexpr (__hash_cached::value)
841 __to._M_hash_code = _M_hash_code_ext(__from);
845 _M_store_code(__node_value_type& __to, __hash_code __code)
const
847 if constexpr (__hash_cached::value)
848 __to._M_hash_code = __code;
850#pragma GCC diagnostic pop
857 size_type __bkt,
const key_type& __k, __hash_code __code)
const
858 {
return _M_find_before_node_tr<key_type>(__bkt, __k, __code); }
860 template<
typename _Kt>
862 _M_find_before_node_tr(size_type,
const _Kt&, __hash_code)
const;
866 struct __location_type
869 explicit operator bool() const noexcept
870 {
return static_cast<bool>(_M_before); }
873 explicit operator iterator() const noexcept
874 {
return iterator(_M_node()); }
877 explicit operator const_iterator() const noexcept
878 {
return const_iterator(_M_node()); }
881 __node_ptr _M_node()
const
884 return static_cast<__node_ptr
>(_M_before->_M_nxt);
888 __node_base_ptr _M_before{};
889 __hash_code _M_hash_code{};
890 size_type _M_bucket_index = size_type(-1);
909 _M_locate(
const key_type& __k)
const
910 {
return _M_locate_tr<key_type>(__k); }
912 template <
typename _Kt>
914 _M_locate_tr(
const _Kt& __k)
const;
917 _M_find_node(size_type __bkt,
const key_type& __key,
918 __hash_code __c)
const
920 if (__node_base_ptr __before_n = _M_find_before_node(__bkt, __key, __c))
921 return static_cast<__node_ptr
>(__before_n->_M_nxt);
925 template<
typename _Kt>
927 _M_find_node_tr(size_type __bkt,
const _Kt& __key,
928 __hash_code __c)
const
930 if (
auto __before_n = _M_find_before_node_tr(__bkt, __key, __c))
931 return static_cast<__node_ptr
>(__before_n->_M_nxt);
937 _M_insert_bucket_begin(size_type __bkt, __node_ptr __node)
939 if (_M_buckets[__bkt])
943 __node->_M_nxt = _M_buckets[__bkt]->_M_nxt;
944 _M_buckets[__bkt]->_M_nxt = __node;
951 __node->_M_nxt = _M_before_begin._M_nxt;
952 _M_before_begin._M_nxt = __node;
957 _M_buckets[_M_bucket_index(*__node->_M_next())] = __node;
959 _M_buckets[__bkt] = &_M_before_begin;
965 _M_remove_bucket_begin(size_type __bkt, __node_ptr __next_n,
966 size_type __next_bkt)
969 _M_buckets[__bkt] =
nullptr;
970 else if (__next_bkt != __bkt)
972 _M_buckets[__next_bkt] = _M_buckets[__bkt];
973 _M_buckets[__bkt] =
nullptr;
979 _M_get_previous_node(size_type __bkt, __node_ptr __n);
981 pair<__node_ptr, __hash_code>
982 _M_compute_hash_code(__node_ptr __hint,
const key_type& __k)
const;
991 _M_insert_unique_node(size_type __bkt, __hash_code,
992 __node_ptr __n, size_type __n_elt = 1);
997 _M_insert_multi_node(__node_ptr __hint,
998 __hash_code __code, __node_ptr __n);
1000 template<
typename... _Args>
1002 _M_emplace_uniq(_Args&&... __args);
1004#pragma GCC diagnostic push
1005#pragma GCC diagnostic ignored "-Wc++14-extensions"
1006 template<
typename _Arg,
typename _DArg = __remove_cvref_t<_Arg>,
1007 typename = _ExtractKey>
1008 static constexpr bool __is_key_type =
false;
1010 template<
typename _Arg>
1011 static constexpr bool
1012 __is_key_type<_Arg, key_type, __detail::_Identity> =
true;
1014 template<
typename _Arg,
typename _Arg1,
typename _Arg2>
1015 static constexpr bool
1016 __is_key_type<_Arg, pair<_Arg1, _Arg2>, __detail::_Select1st>
1017 = is_same<__remove_cvref_t<_Arg1>, key_type>::value;
1018#pragma GCC diagnostic pop
1020 template<
typename... _Args>
1022 _M_emplace_multi(const_iterator, _Args&&... __args);
1025 _M_erase(size_type __bkt, __node_base_ptr __prev_n, __node_ptr __n);
1028 _M_erase_some(size_type __bkt, __node_base_ptr __prev_n, __node_ptr __n);
1030 template<
typename _InputIterator>
1032 _M_insert_range_multi(_InputIterator __first, _InputIterator __last);
1035#pragma GCC diagnostic push
1036#pragma GCC diagnostic ignored "-Wc++17-extensions"
1038 template<
typename... _Args>
1040 emplace(_Args&&... __args)
1042 if constexpr (__unique_keys::value)
1048 template<
typename... _Args>
1050 emplace_hint(const_iterator __hint, _Args&&... __args)
1052 if constexpr (__unique_keys::value)
1060 insert(
const value_type& __v)
1062 if constexpr (__unique_keys::value)
1063 return _M_emplace_uniq(__v);
1065 return _M_emplace_multi(cend(), __v);
1069 insert(const_iterator __hint,
const value_type& __v)
1071 if constexpr (__unique_keys::value)
1072 return _M_emplace_uniq(__v).first;
1074 return _M_emplace_multi(__hint, __v);
1078 insert(value_type&& __v)
1080 if constexpr (__unique_keys::value)
1083 return _M_emplace_multi(cend(),
std::move(__v));
1087 insert(const_iterator __hint, value_type&& __v)
1089 if constexpr (__unique_keys::value)
1090 return _M_emplace_uniq(
std::move(__v)).first;
1092 return _M_emplace_multi(__hint,
std::move(__v));
1095#ifdef __glibcxx_unordered_map_try_emplace
1096 template<
typename _KType,
typename... _Args>
1098 try_emplace(const_iterator, _KType&& __k, _Args&&... __args)
1102 if (
auto __loc = _M_locate(__k))
1103 return { iterator(__loc),
false };
1106 __code = __loc._M_hash_code;
1107 __bkt = __loc._M_bucket_index;
1110 _Scoped_node __node {
1116 auto __it = _M_insert_unique_node(__bkt, __code, __node._M_node);
1117 __node._M_node =
nullptr;
1118 return { __it,
true };
1123 insert(initializer_list<value_type> __l)
1124 { this->insert(__l.begin(), __l.end()); }
1126 template<
typename _InputIterator>
1128 insert(_InputIterator __first, _InputIterator __last)
1130 if constexpr (__unique_keys::value)
1131 for (; __first != __last; ++__first)
1132 _M_emplace_uniq(*__first);
1134 return _M_insert_range_multi(__first, __last);
1138 template<
typename _Pair,
1139 typename = _Require<__not_<is_same<_Key, _Value>>,
1140 is_constructible<value_type, _Pair&&>>>
1144 if constexpr (__unique_keys::value)
1151 template<
typename _Pair,
1152 typename = _Require<__not_<is_same<_Key, _Value>>,
1153 is_constructible<value_type, _Pair&&>>>
1155 insert(const_iterator __hint, _Pair&& __v)
1157 if constexpr (__unique_keys::value)
1162#pragma GCC diagnostic pop
1166 erase(const_iterator);
1171 erase(iterator __it)
1172 {
return erase(const_iterator(__it)); }
1175 erase(
const key_type& __k);
1177 template <
typename _Kt>
1179 _M_erase_tr(
const _Kt& __k);
1182 erase(const_iterator, const_iterator);
1189 void rehash(size_type __bkt_count);
1194#if __glibcxx_node_extract
1197 _M_reinsert_node(node_type&& __nh)
1199 insert_return_type __ret;
1201 __ret.position = end();
1204 __glibcxx_assert(get_allocator() == __nh.get_allocator());
1206 if (
auto __loc = _M_locate(__nh._M_key()))
1209 __ret.position = iterator(__loc);
1210 __ret.inserted =
false;
1214 auto __code = __loc._M_hash_code;
1215 auto __bkt = __loc._M_bucket_index;
1217 = _M_insert_unique_node(__bkt, __code, __nh._M_ptr);
1218 __ret.inserted =
true;
1227 _M_reinsert_node_multi(const_iterator __hint, node_type&& __nh)
1232 __glibcxx_assert(get_allocator() == __nh.get_allocator());
1234 const key_type& __k = __nh._M_key();
1235 auto __code = this->_M_hash_code(__k);
1237 = _M_insert_multi_node(__hint._M_cur, __code, __nh._M_ptr);
1244 _M_extract_node(
size_t __bkt, __node_base_ptr __prev_n)
1246 __node_ptr __n =
static_cast<__node_ptr
>(__prev_n->_M_nxt);
1247 if (__prev_n == _M_buckets[__bkt])
1248 _M_remove_bucket_begin(__bkt, __n->_M_next(),
1249 __n->_M_nxt ? _M_bucket_index(*__n->_M_next()) : 0);
1250 else if (__n->_M_nxt)
1252 size_type __next_bkt = _M_bucket_index(*__n->_M_next());
1253 if (__next_bkt != __bkt)
1254 _M_buckets[__next_bkt] = __prev_n;
1257 __prev_n->_M_nxt = __n->_M_nxt;
1258 __n->_M_nxt =
nullptr;
1260 return { __n, this->_M_node_allocator() };
1267 template<
typename _H2>
1269 _M_src_hash_code(
const _H2&,
const __node_value_type& __src_n)
const
1271 if constexpr (__and_<__hash_cached,
1272 is_same<_H2, _Hash>, is_empty<_Hash>>::value)
1274 return __src_n._M_hash_code;
1276 return this->_M_hash_code(_ExtractKey{}(__src_n._M_v()));
1282 extract(const_iterator __pos)
1284 size_t __bkt = _M_bucket_index(*__pos._M_cur);
1285 return _M_extract_node(__bkt,
1286 _M_get_previous_node(__bkt, __pos._M_cur));
1291 extract(
const _Key& __k)
1292 {
return _M_extract_tr<_Key>(__k); }
1294 template <
typename _Kt>
1296 _M_extract_tr(
const _Kt& __k)
1299 __hash_code __code = this->_M_hash_code_tr(__k);
1300 std::size_t __bkt = _M_bucket_index(__code);
1301 if (__node_base_ptr __prev_node =
1302 _M_find_before_node_tr(__bkt, __k, __code))
1303 __nh = _M_extract_node(__bkt, __prev_node);
1309 _M_merge_unique(_Hashtable& __src)
1311 __glibcxx_assert(get_allocator() == __src.get_allocator());
1313 using _PTr = pointer_traits<__node_base_ptr>;
1315 auto __n_elt = __src.size();
1316 size_type __first = 1;
1319 auto __prev = _PTr::pointer_to(__src._M_before_begin);
1322 const auto __next = __prev->_M_nxt;
1323 const auto& __node =
static_cast<__node_type&
>(*__next);
1324 const key_type& __k = _ExtractKey{}(__node._M_v());
1325 const auto __loc = _M_locate(__k);
1332 auto __src_bkt = __src._M_bucket_index(__node);
1333 auto __nh = __src._M_extract_node(__src_bkt, __prev);
1334 _M_insert_unique_node(__loc._M_bucket_index, __loc._M_hash_code,
1335 __nh._M_ptr, __first * __n_elt + 1);
1342 template<
typename _Compatible_Hashtable>
1344 _M_merge_unique(_Compatible_Hashtable& __src)
1346 static_assert(is_same_v<
typename _Compatible_Hashtable::node_type,
1347 node_type>,
"Node types are compatible");
1348 __glibcxx_assert(get_allocator() == __src.get_allocator());
1350 auto __n_elt = __src.size();
1351 size_type __first = 1;
1354 for (
auto __i = __src.cbegin(), __end = __src.cend(); __i != __end;)
1358 const key_type& __k = _ExtractKey{}(*__pos);
1359 const auto __loc = _M_locate(__k);
1363 auto __nh = __src.extract(__pos);
1364 _M_insert_unique_node(__loc._M_bucket_index,
1365 __loc._M_hash_code, __nh._M_ptr,
1366 __first * __n_elt + 1);
1374 _M_merge_multi(_Hashtable& __src)
1376 __glibcxx_assert(get_allocator() == __src.get_allocator());
1378 if (__src.size() == 0) [[__unlikely__]]
1381 using _PTr = pointer_traits<__node_base_ptr>;
1383 __node_ptr __hint =
nullptr;
1384 this->reserve(size() + __src.size());
1387 auto __prev = _PTr::pointer_to(__src._M_before_begin);
1390 const auto& __node =
static_cast<__node_type&
>(*__prev->_M_nxt);
1392 auto __code = _M_hash_code_ext(__node);
1394 size_type __src_bkt = __src._M_bucket_index(__node);
1395 auto __nh = __src._M_extract_node(__src_bkt, __prev);
1396 __hint = _M_insert_multi_node(__hint, __code, __nh._M_ptr)._M_cur;
1399 while (__prev->_M_nxt !=
nullptr);
1403 template<
typename _Compatible_Hashtable>
1405 _M_merge_multi(_Compatible_Hashtable& __src)
1407 static_assert(is_same_v<
typename _Compatible_Hashtable::node_type,
1408 node_type>,
"Node types are compatible");
1409 __glibcxx_assert(get_allocator() == __src.get_allocator());
1411 __node_ptr __hint =
nullptr;
1412 this->reserve(size() + __src.size());
1415 for (
auto __i = __src.cbegin(), __end = __src.cend(); __i != __end;)
1419 = _M_src_hash_code(__src.hash_function(), *__pos._M_cur);
1420 auto __nh = __src.extract(__pos);
1421 __hint = _M_insert_multi_node(__hint, __code, __nh._M_ptr)._M_cur;
1428 _M_equal(
const _Hashtable& __other)
const;
1432 void _M_rehash(size_type __bkt_count, true_type __uks);
1435 void _M_rehash(size_type __bkt_count, false_type __uks);
1439 template<
typename _Key,
typename _Value,
typename _Alloc,
1440 typename _ExtractKey,
typename _Equal,
1441 typename _Hash,
typename _RangeHash,
typename _Unused,
1442 typename _RehashPolicy,
typename _Traits>
1443 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1444 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1446 const _Hash& __h,
const _Equal& __eq,
const allocator_type& __a)
1447 : _Hashtable(__h, __eq, __a)
1449 auto __bkt_count = _M_rehash_policy._M_next_bkt(__bkt_count_hint);
1450 if (__bkt_count > _M_bucket_count)
1452 _M_buckets = _M_allocate_buckets(__bkt_count);
1453 _M_bucket_count = __bkt_count;
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 template<
typename _InputIterator>
1463 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1464 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1465 _Hashtable(_InputIterator __f, _InputIterator __l,
1466 size_type __bkt_count_hint,
1467 const _Hash& __h,
const _Equal& __eq,
1468 const allocator_type& __a, true_type )
1469 : _Hashtable(__bkt_count_hint, __h, __eq, __a)
1470 { this->insert(__f, __l); }
1472 template<
typename _Key,
typename _Value,
typename _Alloc,
1473 typename _ExtractKey,
typename _Equal,
1474 typename _Hash,
typename _RangeHash,
typename _Unused,
1475 typename _RehashPolicy,
typename _Traits>
1476 template<
typename _InputIterator>
1477 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1478 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1479 _Hashtable(_InputIterator __f, _InputIterator __l,
1480 size_type __bkt_count_hint,
1481 const _Hash& __h,
const _Equal& __eq,
1482 const allocator_type& __a, false_type __uks)
1483 : _Hashtable(__h, __eq, __a)
1485 auto __nb_elems = __detail::__distance_fw(__f, __l);
1487 _M_rehash_policy._M_next_bkt(
1488 std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems),
1491 if (__bkt_count > _M_bucket_count)
1493 _M_buckets = _M_allocate_buckets(__bkt_count);
1494 _M_bucket_count = __bkt_count;
1497 for (; __f != __l; ++__f)
1498 _M_emplace_multi(cend(), *__f);
1501 template<
typename _Key,
typename _Value,
typename _Alloc,
1502 typename _ExtractKey,
typename _Equal,
1503 typename _Hash,
typename _RangeHash,
typename _Unused,
1504 typename _RehashPolicy,
typename _Traits>
1506 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1507 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1508 operator=(
const _Hashtable& __ht)
1514 if (__node_alloc_traits::_S_propagate_on_copy_assign())
1516 auto& __this_alloc = this->_M_node_allocator();
1517 auto& __that_alloc = __ht._M_node_allocator();
1518 if (!__node_alloc_traits::_S_always_equal()
1519 && __this_alloc != __that_alloc)
1522 this->_M_deallocate_nodes(_M_begin());
1523 _M_before_begin._M_nxt =
nullptr;
1524 _M_deallocate_buckets();
1525 _M_buckets =
nullptr;
1526 std::__alloc_on_copy(__this_alloc, __that_alloc);
1527 __hashtable_base::operator=(__ht);
1528 _M_bucket_count = __ht._M_bucket_count;
1529 _M_element_count = __ht._M_element_count;
1530 _M_rehash_policy = __ht._M_rehash_policy;
1534 ~_Guard() {
if (_M_ht) _M_ht->_M_reset(); }
1539 _Guard __guard{
this};
1541 __guard._M_ht =
nullptr;
1544 std::__alloc_on_copy(__this_alloc, __that_alloc);
1548 _M_assign_elements(__ht);
1552 template<
typename _Key,
typename _Value,
typename _Alloc,
1553 typename _ExtractKey,
typename _Equal,
1554 typename _Hash,
typename _RangeHash,
typename _Unused,
1555 typename _RehashPolicy,
typename _Traits>
1556 template<
typename _Ht>
1558 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1559 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1560 _M_assign_elements(_Ht&& __ht)
1562 using __reuse_or_alloc_node_gen_t =
1563 __detail::_ReuseOrAllocNode<__node_alloc_type>;
1565 __buckets_ptr __former_buckets =
nullptr;
1566 std::size_t __former_bucket_count = _M_bucket_count;
1567 __rehash_guard_t __rehash_guard(_M_rehash_policy);
1569 if (_M_bucket_count != __ht._M_bucket_count)
1571 __former_buckets = _M_buckets;
1572 _M_buckets = _M_allocate_buckets(__ht._M_bucket_count);
1573 _M_bucket_count = __ht._M_bucket_count;
1576 std::fill_n(_M_buckets, _M_bucket_count,
nullptr);
1581 _M_element_count = __ht._M_element_count;
1582 _M_rehash_policy = __ht._M_rehash_policy;
1583 __reuse_or_alloc_node_gen_t __roan(_M_begin(), *
this);
1584 _M_before_begin._M_nxt =
nullptr;
1586 if (__former_buckets)
1587 _M_deallocate_buckets(__former_buckets, __former_bucket_count);
1588 __rehash_guard._M_guarded_obj =
nullptr;
1592 if (__former_buckets)
1595 _M_deallocate_buckets();
1596 _M_buckets = __former_buckets;
1597 _M_bucket_count = __former_bucket_count;
1599 std::fill_n(_M_buckets, _M_bucket_count,
nullptr);
1600 __throw_exception_again;
1604 template<
typename _Key,
typename _Value,
typename _Alloc,
1605 typename _ExtractKey,
typename _Equal,
1606 typename _Hash,
typename _RangeHash,
typename _Unused,
1607 typename _RehashPolicy,
typename _Traits>
1608 template<
typename _Ht,
typename _NodeGenerator>
1610 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1611 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1612 _M_assign(_Ht&& __ht, _NodeGenerator& __node_gen)
1621 if (_M_dealloc_buckets)
1622 _M_ht->_M_deallocate_buckets();
1625 _Hashtable* _M_ht =
nullptr;
1626 bool _M_dealloc_buckets =
false;
1632 _M_buckets = _M_allocate_buckets(_M_bucket_count);
1633 __guard._M_dealloc_buckets =
true;
1636 if (!__ht._M_before_begin._M_nxt)
1639 __guard._M_ht =
this;
1641 using _FromVal = __conditional_t<is_lvalue_reference<_Ht>::value,
1642 const value_type&, value_type&&>;
1646 __node_ptr __ht_n = __ht._M_begin();
1648 = __node_gen(
static_cast<_FromVal
>(__ht_n->_M_v()));
1649 _M_copy_code(*__this_n, *__ht_n);
1650 _M_update_bbegin(__this_n);
1653 __node_ptr __prev_n = __this_n;
1654 for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next())
1656 __this_n = __node_gen(
static_cast<_FromVal
>(__ht_n->_M_v()));
1657 __prev_n->_M_nxt = __this_n;
1658 _M_copy_code(*__this_n, *__ht_n);
1659 size_type __bkt = _M_bucket_index(*__this_n);
1660 if (!_M_buckets[__bkt])
1661 _M_buckets[__bkt] = __prev_n;
1662 __prev_n = __this_n;
1664 __guard._M_ht =
nullptr;
1667 template<
typename _Key,
typename _Value,
typename _Alloc,
1668 typename _ExtractKey,
typename _Equal,
1669 typename _Hash,
typename _RangeHash,
typename _Unused,
1670 typename _RehashPolicy,
typename _Traits>
1672 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1673 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1676 _M_rehash_policy._M_reset();
1677 _M_bucket_count = 1;
1678 _M_single_bucket =
nullptr;
1679 _M_buckets = &_M_single_bucket;
1680 _M_before_begin._M_nxt =
nullptr;
1681 _M_element_count = 0;
1684 template<
typename _Key,
typename _Value,
typename _Alloc,
1685 typename _ExtractKey,
typename _Equal,
1686 typename _Hash,
typename _RangeHash,
typename _Unused,
1687 typename _RehashPolicy,
typename _Traits>
1689 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1690 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1691 _M_move_assign(_Hashtable&& __ht, true_type)
1696 this->_M_deallocate_nodes(_M_begin());
1697 _M_deallocate_buckets();
1698 __hashtable_base::operator=(
std::move(__ht));
1699 _M_rehash_policy = __ht._M_rehash_policy;
1700 if (!__ht._M_uses_single_bucket())
1701 _M_buckets = __ht._M_buckets;
1704 _M_buckets = &_M_single_bucket;
1705 _M_single_bucket = __ht._M_single_bucket;
1708 _M_bucket_count = __ht._M_bucket_count;
1709 _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt;
1710 _M_element_count = __ht._M_element_count;
1711 std::__alloc_on_move(this->_M_node_allocator(), __ht._M_node_allocator());
1718 template<
typename _Key,
typename _Value,
typename _Alloc,
1719 typename _ExtractKey,
typename _Equal,
1720 typename _Hash,
typename _RangeHash,
typename _Unused,
1721 typename _RehashPolicy,
typename _Traits>
1723 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1724 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1725 _M_move_assign(_Hashtable&& __ht, false_type)
1727 if (__ht._M_node_allocator() == this->_M_node_allocator())
1728 _M_move_assign(
std::move(__ht), true_type{});
1737 template<
typename _Key,
typename _Value,
typename _Alloc,
1738 typename _ExtractKey,
typename _Equal,
1739 typename _Hash,
typename _RangeHash,
typename _Unused,
1740 typename _RehashPolicy,
typename _Traits>
1742 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1743 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1744 _Hashtable(
const _Hashtable& __ht)
1745 : __hashtable_base(__ht),
1747 __rehash_base(__ht),
1749 __node_alloc_traits::_S_select_on_copy(__ht._M_node_allocator())),
1750 __enable_default_ctor(__ht),
1751 _M_buckets(nullptr),
1752 _M_bucket_count(__ht._M_bucket_count),
1753 _M_element_count(__ht._M_element_count),
1754 _M_rehash_policy(__ht._M_rehash_policy)
1759 template<
typename _Key,
typename _Value,
typename _Alloc,
1760 typename _ExtractKey,
typename _Equal,
1761 typename _Hash,
typename _RangeHash,
typename _Unused,
1762 typename _RehashPolicy,
typename _Traits>
1763 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1764 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1765 _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a,
1767 noexcept(_S_nothrow_move())
1768 : __hashtable_base(__ht),
1770 __rehash_base(__ht),
1771 __hashtable_alloc(
std::move(__a)),
1772 __enable_default_ctor(__ht),
1773 _M_buckets(__ht._M_buckets),
1774 _M_bucket_count(__ht._M_bucket_count),
1775 _M_before_begin(__ht._M_before_begin._M_nxt),
1776 _M_element_count(__ht._M_element_count),
1777 _M_rehash_policy(__ht._M_rehash_policy)
1780 if (__ht._M_uses_single_bucket())
1782 _M_buckets = &_M_single_bucket;
1783 _M_single_bucket = __ht._M_single_bucket;
1792 template<
typename _Key,
typename _Value,
typename _Alloc,
1793 typename _ExtractKey,
typename _Equal,
1794 typename _Hash,
typename _RangeHash,
typename _Unused,
1795 typename _RehashPolicy,
typename _Traits>
1797 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1798 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1799 _Hashtable(
const _Hashtable& __ht,
const allocator_type& __a)
1800 : __hashtable_base(__ht),
1802 __rehash_base(__ht),
1803 __hashtable_alloc(__node_alloc_type(__a)),
1804 __enable_default_ctor(__ht),
1806 _M_bucket_count(__ht._M_bucket_count),
1807 _M_element_count(__ht._M_element_count),
1808 _M_rehash_policy(__ht._M_rehash_policy)
1813 template<
typename _Key,
typename _Value,
typename _Alloc,
1814 typename _ExtractKey,
typename _Equal,
1815 typename _Hash,
typename _RangeHash,
typename _Unused,
1816 typename _RehashPolicy,
typename _Traits>
1817 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1818 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1819 _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a,
1821 : __hashtable_base(__ht),
1823 __rehash_base(__ht),
1824 __hashtable_alloc(
std::move(__a)),
1825 __enable_default_ctor(__ht),
1826 _M_buckets(nullptr),
1827 _M_bucket_count(__ht._M_bucket_count),
1828 _M_element_count(__ht._M_element_count),
1829 _M_rehash_policy(__ht._M_rehash_policy)
1831 if (__ht._M_node_allocator() == this->_M_node_allocator())
1833 if (__ht._M_uses_single_bucket())
1835 _M_buckets = &_M_single_bucket;
1836 _M_single_bucket = __ht._M_single_bucket;
1839 _M_buckets = __ht._M_buckets;
1843 _M_update_bbegin(__ht._M_begin());
1849 using _Fwd_Ht = __conditional_t<
1850 __move_if_noexcept_cond<value_type>::value,
1851 const _Hashtable&, _Hashtable&&>;
1857 template<
typename _Key,
typename _Value,
typename _Alloc,
1858 typename _ExtractKey,
typename _Equal,
1859 typename _Hash,
typename _RangeHash,
typename _Unused,
1860 typename _RehashPolicy,
typename _Traits>
1861 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1862 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1863 ~_Hashtable() noexcept
1870 static_assert(
noexcept(declval<const __hash_code_base_access&>()
1871 ._M_bucket_index(declval<const __node_value_type&>(),
1873 "Cache the hash code or qualify your functors involved"
1874 " in hash code and bucket index computation with noexcept");
1876 this->_M_deallocate_nodes(_M_begin());
1877 _M_deallocate_buckets();
1880 template<
typename _Key,
typename _Value,
typename _Alloc,
1881 typename _ExtractKey,
typename _Equal,
1882 typename _Hash,
typename _RangeHash,
typename _Unused,
1883 typename _RehashPolicy,
typename _Traits>
1885 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1886 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1887 swap(_Hashtable& __x)
1888 noexcept(__and_<__is_nothrow_swappable<_Hash>,
1889 __is_nothrow_swappable<_Equal>>::value)
1892 swap(__hash_code_base::_M_hash._M_obj,
1893 __x.__hash_code_base::_M_hash._M_obj);
1894 swap(__hashtable_base::_M_equal._M_obj,
1895 __x.__hashtable_base::_M_equal._M_obj);
1897#pragma GCC diagnostic push
1898#pragma GCC diagnostic ignored "-Wc++17-extensions"
1899 if constexpr (__node_alloc_traits::propagate_on_container_swap::value)
1900 swap(this->_M_node_allocator(), __x._M_node_allocator());
1901#pragma GCC diagnostic pop
1903 std::swap(_M_rehash_policy, __x._M_rehash_policy);
1906 if (this->_M_uses_single_bucket())
1908 if (!__x._M_uses_single_bucket())
1910 _M_buckets = __x._M_buckets;
1911 __x._M_buckets = &__x._M_single_bucket;
1914 else if (__x._M_uses_single_bucket())
1916 __x._M_buckets = _M_buckets;
1917 _M_buckets = &_M_single_bucket;
1920 std::swap(_M_buckets, __x._M_buckets);
1922 std::swap(_M_bucket_count, __x._M_bucket_count);
1923 std::swap(_M_before_begin._M_nxt, __x._M_before_begin._M_nxt);
1924 std::swap(_M_element_count, __x._M_element_count);
1925 std::swap(_M_single_bucket, __x._M_single_bucket);
1930 __x._M_update_bbegin();
1933 template<
typename _Key,
typename _Value,
typename _Alloc,
1934 typename _ExtractKey,
typename _Equal,
1935 typename _Hash,
typename _RangeHash,
typename _Unused,
1936 typename _RehashPolicy,
typename _Traits>
1938 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1939 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1940 find(
const key_type& __k)
1942 {
return iterator(_M_locate(__k)); }
1944 template<
typename _Key,
typename _Value,
typename _Alloc,
1945 typename _ExtractKey,
typename _Equal,
1946 typename _Hash,
typename _RangeHash,
typename _Unused,
1947 typename _RehashPolicy,
typename _Traits>
1949 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1950 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1951 find(
const key_type& __k)
const
1953 {
return const_iterator(_M_locate(__k)); }
1955#ifdef __glibcxx_generic_unordered_lookup
1956 template<
typename _Key,
typename _Value,
typename _Alloc,
1957 typename _ExtractKey,
typename _Equal,
1958 typename _Hash,
typename _RangeHash,
typename _Unused,
1959 typename _RehashPolicy,
typename _Traits>
1960 template<
typename _Kt,
typename,
typename>
1962 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1963 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1964 _M_find_tr(
const _Kt& __k)
1967 if (size() <= __small_size_threshold())
1969 for (
auto __n = _M_begin(); __n; __n = __n->_M_next())
1970 if (this->_M_key_equals_tr(__k, *__n))
1971 return iterator(__n);
1975 __hash_code __code = this->_M_hash_code_tr(__k);
1976 std::size_t __bkt = _M_bucket_index(__code);
1977 return iterator(_M_find_node_tr(__bkt, __k, __code));
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 _Kt,
typename,
typename>
1986 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1987 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1988 _M_find_tr(
const _Kt& __k)
const
1991 if (size() <= __small_size_threshold())
1993 for (
auto __n = _M_begin(); __n; __n = __n->_M_next())
1994 if (this->_M_key_equals_tr(__k, *__n))
1995 return const_iterator(__n);
1999 __hash_code __code = this->_M_hash_code_tr(__k);
2000 std::size_t __bkt = _M_bucket_index(__code);
2001 return const_iterator(_M_find_node_tr(__bkt, __k, __code));
2005 template<
typename _Key,
typename _Value,
typename _Alloc,
2006 typename _ExtractKey,
typename _Equal,
2007 typename _Hash,
typename _RangeHash,
typename _Unused,
2008 typename _RehashPolicy,
typename _Traits>
2010 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2011 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2012 count(
const key_type& __k)
const
2015 auto __it = find(__k);
2019 if (__unique_keys::value)
2022 size_type __result = 1;
2023 for (
auto __ref = __it++;
2024 __it._M_cur && this->_M_node_equals(*__ref._M_cur, *__it._M_cur);
2031#ifdef __glibcxx_generic_unordered_lookup
2032 template<
typename _Key,
typename _Value,
typename _Alloc,
2033 typename _ExtractKey,
typename _Equal,
2034 typename _Hash,
typename _RangeHash,
typename _Unused,
2035 typename _RehashPolicy,
typename _Traits>
2036 template<
typename _Kt,
typename,
typename>
2038 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2039 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2040 _M_count_tr(
const _Kt& __k)
const
2043 if (size() <= __small_size_threshold())
2045 size_type __result = 0;
2046 for (
auto __n = _M_begin(); __n; __n = __n->_M_next())
2048 if (this->_M_key_equals_tr(__k, *__n))
2061 __hash_code __code = this->_M_hash_code_tr(__k);
2062 std::size_t __bkt = _M_bucket_index(__code);
2063 auto __n = _M_find_node_tr(__bkt, __k, __code);
2068 size_type __result = 1;
2070 __it._M_cur && this->_M_equals_tr(__k, __code, *__it._M_cur);
2078 template<
typename _Key,
typename _Value,
typename _Alloc,
2079 typename _ExtractKey,
typename _Equal,
2080 typename _Hash,
typename _RangeHash,
typename _Unused,
2081 typename _RehashPolicy,
typename _Traits>
2083 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2084 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2085 equal_range(
const key_type& __k)
2086 -> pair<iterator, iterator>
2088 auto __ite = find(__k);
2090 return { __ite, __ite };
2092 auto __beg = __ite++;
2093 if (__unique_keys::value)
2094 return { __beg, __ite };
2096 while (__ite._M_cur && this->_M_node_equals(*__beg._M_cur, *__ite._M_cur))
2099 return { __beg, __ite };
2102 template<
typename _Key,
typename _Value,
typename _Alloc,
2103 typename _ExtractKey,
typename _Equal,
2104 typename _Hash,
typename _RangeHash,
typename _Unused,
2105 typename _RehashPolicy,
typename _Traits>
2107 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2108 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2109 equal_range(
const key_type& __k)
const
2110 -> pair<const_iterator, const_iterator>
2112 auto __ite = find(__k);
2114 return { __ite, __ite };
2116 auto __beg = __ite++;
2117 if (__unique_keys::value)
2118 return { __beg, __ite };
2120 while (__ite._M_cur && this->_M_node_equals(*__beg._M_cur, *__ite._M_cur))
2123 return { __beg, __ite };
2126#ifdef __glibcxx_generic_unordered_lookup
2127 template<
typename _Key,
typename _Value,
typename _Alloc,
2128 typename _ExtractKey,
typename _Equal,
2129 typename _Hash,
typename _RangeHash,
typename _Unused,
2130 typename _RehashPolicy,
typename _Traits>
2131 template<
typename _Kt,
typename,
typename>
2133 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2134 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2135 _M_equal_range_tr(
const _Kt& __k)
2136 -> pair<iterator, iterator>
2138 if (size() <= __small_size_threshold())
2140 __node_ptr __n, __beg =
nullptr;
2141 for (__n = _M_begin(); __n; __n = __n->_M_next())
2143 if (this->_M_key_equals_tr(__k, *__n))
2154 return { iterator(__beg), iterator(__n) };
2157 __hash_code __code = this->_M_hash_code_tr(__k);
2158 std::size_t __bkt = _M_bucket_index(__code);
2159 auto __n = _M_find_node_tr(__bkt, __k, __code);
2160 iterator __ite(__n);
2162 return { __ite, __ite };
2164 auto __beg = __ite++;
2165 while (__ite._M_cur && this->_M_equals_tr(__k, __code, *__ite._M_cur))
2168 return { __beg, __ite };
2171 template<
typename _Key,
typename _Value,
typename _Alloc,
2172 typename _ExtractKey,
typename _Equal,
2173 typename _Hash,
typename _RangeHash,
typename _Unused,
2174 typename _RehashPolicy,
typename _Traits>
2175 template<
typename _Kt,
typename,
typename>
2177 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2178 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2179 _M_equal_range_tr(
const _Kt& __k)
const
2180 -> pair<const_iterator, const_iterator>
2182 if (size() <= __small_size_threshold())
2184 __node_ptr __n, __beg =
nullptr;
2185 for (__n = _M_begin(); __n; __n = __n->_M_next())
2187 if (this->_M_key_equals_tr(__k, *__n))
2198 return { const_iterator(__beg), const_iterator(__n) };
2201 __hash_code __code = this->_M_hash_code_tr(__k);
2202 std::size_t __bkt = _M_bucket_index(__code);
2203 auto __n = _M_find_node_tr(__bkt, __k, __code);
2204 const_iterator __ite(__n);
2206 return { __ite, __ite };
2208 auto __beg = __ite++;
2209 while (__ite._M_cur && this->_M_equals_tr(__k, __code, *__ite._M_cur))
2212 return { __beg, __ite };
2218 template<
typename _Key,
typename _Value,
typename _Alloc,
2219 typename _ExtractKey,
typename _Equal,
2220 typename _Hash,
typename _RangeHash,
typename _Unused,
2221 typename _RehashPolicy,
typename _Traits>
2222 template<
typename _Kt>
2224 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2225 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2226 _M_find_before_node_tr(size_type __bkt,
const _Kt& __k,
2227 __hash_code __code)
const
2230 __node_base_ptr __prev_p = _M_buckets[__bkt];
2234 for (__node_ptr __p =
static_cast<__node_ptr
>(__prev_p->_M_nxt);;
2235 __p = __p->_M_next())
2237 if (this->_M_equals_tr(__k, __code, *__p))
2240 if (__builtin_expect (
2241 !__p->_M_nxt || _M_bucket_index(*__p->_M_next()) != __bkt, 0))
2249 template<
typename _Key,
typename _Value,
typename _Alloc,
2250 typename _ExtractKey,
typename _Equal,
2251 typename _Hash,
typename _RangeHash,
typename _Unused,
2252 typename _RehashPolicy,
typename _Traits>
2253 template <
typename _Kt>
2255 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2256 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2257 _M_locate_tr(
const _Kt& __k)
const
2260 __location_type __loc;
2261 const auto __size = size();
2263 if (__size <= __small_size_threshold())
2265 __loc._M_before = pointer_traits<__node_base_ptr>::
2266 pointer_to(
const_cast<__node_base&
>(_M_before_begin));
2267 while (__loc._M_before->_M_nxt)
2269 if (this->_M_key_equals_tr(__k, *__loc._M_node()))
2271 __loc._M_before = __loc._M_before->_M_nxt;
2273 __loc._M_before =
nullptr;
2276 __loc._M_hash_code = this->_M_hash_code_tr(__k);
2277 __loc._M_bucket_index = _M_bucket_index(__loc._M_hash_code);
2279 if (__size > __small_size_threshold())
2280 __loc._M_before = _M_find_before_node_tr(
2281 __loc._M_bucket_index, __k, __loc._M_hash_code);
2286 template<
typename _Key,
typename _Value,
typename _Alloc,
2287 typename _ExtractKey,
typename _Equal,
2288 typename _Hash,
typename _RangeHash,
typename _Unused,
2289 typename _RehashPolicy,
typename _Traits>
2291 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2292 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2293 _M_get_previous_node(size_type __bkt, __node_ptr __n)
2296 __node_base_ptr __prev_n = _M_buckets[__bkt];
2297 while (__prev_n->_M_nxt != __n)
2298 __prev_n = __prev_n->_M_nxt;
2302#pragma GCC diagnostic push
2303#pragma GCC diagnostic ignored "-Wc++17-extensions"
2304 template<
typename _Key,
typename _Value,
typename _Alloc,
2305 typename _ExtractKey,
typename _Equal,
2306 typename _Hash,
typename _RangeHash,
typename _Unused,
2307 typename _RehashPolicy,
typename _Traits>
2308 template<
typename... _Args>
2310 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2311 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2312 _M_emplace_uniq(_Args&&... __args)
2313 -> pair<iterator, bool>
2315 const key_type* __kp =
nullptr;
2317 if constexpr (
sizeof...(_Args) == 1)
2319 if constexpr (__is_key_type<_Args...>)
2321 const auto& __key = _ExtractKey{}(__args...);
2325 else if constexpr (
sizeof...(_Args) == 2)
2327 if constexpr (__is_key_type<
pair<
const _Args&...>>)
2329 pair<
const _Args&...> __refs(__args...);
2330 const auto& __key = _ExtractKey{}(__refs);
2335 _Scoped_node __node { __node_ptr(),
this };
2336 __hash_code __code = 0;
2337 size_type __bkt = 0;
2339 if (__kp ==
nullptr)
2344 const key_type& __key = _ExtractKey{}(__node._M_node->_M_v());
2348 if (
auto __loc = _M_locate(*__kp))
2350 return { iterator(__loc),
false };
2353 __code = __loc._M_hash_code;
2354 __bkt = __loc._M_bucket_index;
2357 if (!__node._M_node)
2362 auto __pos = _M_insert_unique_node(__bkt, __code, __node._M_node);
2363 __node._M_node =
nullptr;
2364 return { __pos,
true };
2366#pragma GCC diagnostic pop
2368 template<
typename _Key,
typename _Value,
typename _Alloc,
2369 typename _ExtractKey,
typename _Equal,
2370 typename _Hash,
typename _RangeHash,
typename _Unused,
2371 typename _RehashPolicy,
typename _Traits>
2372 template<
typename... _Args>
2374 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2375 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2376 _M_emplace_multi(const_iterator __hint, _Args&&... __args)
2381 const key_type& __k = _ExtractKey{}(__node._M_node->_M_v());
2383 auto __res = this->_M_compute_hash_code(__hint._M_cur, __k);
2385 = _M_insert_multi_node(__res.first, __res.second, __node._M_node);
2386 __node._M_node =
nullptr;
2390 template<
typename _Key,
typename _Value,
typename _Alloc,
2391 typename _ExtractKey,
typename _Equal,
2392 typename _Hash,
typename _RangeHash,
typename _Unused,
2393 typename _RehashPolicy,
typename _Traits>
2395 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2396 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2397 _M_rehash_insert(size_type __n)
2403 __rehash_guard_t __rehash_guard(_M_rehash_policy);
2404 __pair_type __do_rehash
2405 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, __n);
2407 if (__do_rehash.first)
2408 _M_rehash(__do_rehash.second, false_type{});
2410 __rehash_guard._M_guarded_obj =
nullptr;
2414 template<
typename _Key,
typename _Value,
typename _Alloc,
2415 typename _ExtractKey,
typename _Equal,
2416 typename _Hash,
typename _RangeHash,
typename _Unused,
2417 typename _RehashPolicy,
typename _Traits>
2418 template<
typename _InputIterator>
2420 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2421 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2422 _M_insert_range_multi(_InputIterator __first, _InputIterator __last)
2424 _M_rehash_insert(__detail::__distance_fw(__first, __last));
2425 for (; __first != __last; ++__first)
2426 _M_emplace_multi(cend(), *__first);
2429 template<
typename _Key,
typename _Value,
typename _Alloc,
2430 typename _ExtractKey,
typename _Equal,
2431 typename _Hash,
typename _RangeHash,
typename _Unused,
2432 typename _RehashPolicy,
typename _Traits>
2434 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2435 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2436 _M_compute_hash_code(__node_ptr __hint,
const key_type& __k)
const
2437 -> pair<__node_ptr, __hash_code>
2439 if (size() <= __small_size_threshold())
2443 for (
auto __it = __hint; __it; __it = __it->_M_next())
2444 if (this->_M_key_equals(__k, *__it))
2445 return { __it, this->_M_hash_code(*__it) };
2448 for (
auto __it = _M_begin(); __it != __hint; __it = __it->_M_next())
2449 if (this->_M_key_equals(__k, *__it))
2450 return { __it, this->_M_hash_code(*__it) };
2455 return { __hint, this->_M_hash_code(__k) };
2458 template<
typename _Key,
typename _Value,
typename _Alloc,
2459 typename _ExtractKey,
typename _Equal,
2460 typename _Hash,
typename _RangeHash,
typename _Unused,
2461 typename _RehashPolicy,
typename _Traits>
2463 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2464 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2465 _M_insert_unique_node(size_type __bkt, __hash_code __code,
2466 __node_ptr __node, size_type __n_elt)
2469 __rehash_guard_t __rehash_guard(_M_rehash_policy);
2471 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count,
2474 if (__do_rehash.
first)
2476 _M_rehash(__do_rehash.
second, true_type{});
2477 __bkt = _M_bucket_index(__code);
2480 __rehash_guard._M_guarded_obj =
nullptr;
2481 _M_store_code(*__node, __code);
2484 _M_insert_bucket_begin(__bkt, __node);
2486 return iterator(__node);
2489 template<
typename _Key,
typename _Value,
typename _Alloc,
2490 typename _ExtractKey,
typename _Equal,
2491 typename _Hash,
typename _RangeHash,
typename _Unused,
2492 typename _RehashPolicy,
typename _Traits>
2494 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2495 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2496 _M_insert_multi_node(__node_ptr __hint,
2497 __hash_code __code, __node_ptr __node)
2500 __rehash_guard_t __rehash_guard(_M_rehash_policy);
2502 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
2504 if (__do_rehash.
first)
2505 _M_rehash(__do_rehash.
second, false_type{});
2507 __rehash_guard._M_guarded_obj =
nullptr;
2508 _M_store_code(*__node, __code);
2509 const key_type& __k = _ExtractKey{}(__node->_M_v());
2510 size_type __bkt = _M_bucket_index(__code);
2514 __node_base_ptr __prev
2515 = __builtin_expect(__hint !=
nullptr,
false)
2516 && this->_M_equals(__k, __code, *__hint)
2518 : _M_find_before_node(__bkt, __k, __code);
2523 __node->_M_nxt = __prev->_M_nxt;
2524 __prev->_M_nxt = __node;
2525 if (__builtin_expect(__prev == __hint,
false))
2529 && !this->_M_equals(__k, __code, *__node->_M_next()))
2531 size_type __next_bkt = _M_bucket_index(*__node->_M_next());
2532 if (__next_bkt != __bkt)
2533 _M_buckets[__next_bkt] = __node;
2540 _M_insert_bucket_begin(__bkt, __node);
2542 return iterator(__node);
2545 template<
typename _Key,
typename _Value,
typename _Alloc,
2546 typename _ExtractKey,
typename _Equal,
2547 typename _Hash,
typename _RangeHash,
typename _Unused,
2548 typename _RehashPolicy,
typename _Traits>
2550 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2551 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2552 erase(const_iterator __it)
2555 __node_ptr __n = __it._M_cur;
2556 std::size_t __bkt = _M_bucket_index(*__n);
2561 __node_base_ptr __prev_n = _M_get_previous_node(__bkt, __n);
2562 return _M_erase(__bkt, __prev_n, __n);
2565 template<
typename _Key,
typename _Value,
typename _Alloc,
2566 typename _ExtractKey,
typename _Equal,
2567 typename _Hash,
typename _RangeHash,
typename _Unused,
2568 typename _RehashPolicy,
typename _Traits>
2570 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2571 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2572 _M_erase(size_type __bkt, __node_base_ptr __prev_n, __node_ptr __n)
2575 if (__prev_n == _M_buckets[__bkt])
2576 _M_remove_bucket_begin(__bkt, __n->_M_next(),
2577 __n->_M_nxt ? _M_bucket_index(*__n->_M_next()) : 0);
2578 else if (__n->_M_nxt)
2580 size_type __next_bkt = _M_bucket_index(*__n->_M_next());
2581 if (__next_bkt != __bkt)
2582 _M_buckets[__next_bkt] = __prev_n;
2585 __prev_n->_M_nxt = __n->_M_nxt;
2586 iterator __result(__n->_M_next());
2587 this->_M_deallocate_node(__n);
2593#pragma GCC diagnostic push
2594#pragma GCC diagnostic ignored "-Wc++17-extensions"
2596 template<
typename _Key,
typename _Value,
typename _Alloc,
2597 typename _ExtractKey,
typename _Equal,
2598 typename _Hash,
typename _RangeHash,
typename _Unused,
2599 typename _RehashPolicy,
typename _Traits>
2601 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2602 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2603 erase(
const key_type& __k)
2606 auto __loc = _M_locate(__k);
2610 __node_base_ptr __prev_n = __loc._M_before;
2611 __node_ptr __n = __loc._M_node();
2612 auto __bkt = __loc._M_bucket_index;
2613 if (__bkt == size_type(-1))
2614 __bkt = _M_bucket_index(*__n);
2615 if constexpr (__unique_keys::value)
2617 _M_erase(__bkt, __prev_n, __n);
2621 return _M_erase_some(__bkt, __prev_n, __n);
2624 template<
typename _Key,
typename _Value,
typename _Alloc,
2625 typename _ExtractKey,
typename _Equal,
2626 typename _Hash,
typename _RangeHash,
typename _Unused,
2627 typename _RehashPolicy,
typename _Traits>
2629 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2630 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2631 _M_erase_some(size_type __bkt, __node_base_ptr __prev_n, __node_ptr __n)
2640 __node_ptr __n_last = __n->_M_next();
2641 while (__n_last && this->_M_node_equals(*__n, *__n_last))
2642 __n_last = __n_last->_M_next();
2644 std::size_t __n_last_bkt
2645 = __n_last ? _M_bucket_index(*__n_last) : __bkt;
2648 size_type __result = 0;
2651 __node_ptr __p = __n->_M_next();
2652 this->_M_deallocate_node(__n);
2656 while (__n != __n_last);
2658 _M_element_count -= __result;
2659 if (__prev_n == _M_buckets[__bkt])
2660 _M_remove_bucket_begin(__bkt, __n_last, __n_last_bkt);
2661 else if (__n_last_bkt != __bkt)
2662 _M_buckets[__n_last_bkt] = __prev_n;
2663 __prev_n->_M_nxt = __n_last;
2667 template<
typename _Key,
typename _Value,
typename _Alloc,
2668 typename _ExtractKey,
typename _Equal,
2669 typename _Hash,
typename _RangeHash,
typename _Unused,
2670 typename _RehashPolicy,
typename _Traits>
2671 template <
typename _Kt>
2673 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2674 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2675 _M_erase_tr(
const _Kt& __k)
2678 auto __loc = _M_locate_tr(__k);
2682 __node_base_ptr __prev_n = __loc._M_before;
2683 __node_ptr __n = __loc._M_node();
2684 auto __bkt = __loc._M_bucket_index;
2685 if (__bkt == size_type(-1))
2686 __bkt = _M_bucket_index(*__n);
2687 if constexpr (__unique_keys::value)
2689 _M_erase(__bkt, __prev_n, __n);
2693 return _M_erase_some(__bkt, __prev_n, __n);
2696#pragma GCC diagnostic pop
2698 template<
typename _Key,
typename _Value,
typename _Alloc,
2699 typename _ExtractKey,
typename _Equal,
2700 typename _Hash,
typename _RangeHash,
typename _Unused,
2701 typename _RehashPolicy,
typename _Traits>
2703 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2704 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2705 erase(const_iterator __first, const_iterator __last)
2708 __node_ptr __n = __first._M_cur;
2709 __node_ptr __last_n = __last._M_cur;
2710 if (__n == __last_n)
2711 return iterator(__n);
2713 std::size_t __bkt = _M_bucket_index(*__n);
2715 __node_base_ptr __prev_n = _M_get_previous_node(__bkt, __n);
2716 bool __is_bucket_begin = __n == _M_bucket_begin(__bkt);
2717 std::size_t __n_bkt = __bkt;
2722 __node_ptr __tmp = __n;
2723 __n = __n->_M_next();
2724 this->_M_deallocate_node(__tmp);
2728 __n_bkt = _M_bucket_index(*__n);
2730 while (__n != __last_n && __n_bkt == __bkt);
2731 if (__is_bucket_begin)
2732 _M_remove_bucket_begin(__bkt, __n, __n_bkt);
2733 if (__n == __last_n)
2735 __is_bucket_begin =
true;
2739 if (__n && (__n_bkt != __bkt || __is_bucket_begin))
2740 _M_buckets[__n_bkt] = __prev_n;
2741 __prev_n->_M_nxt = __n;
2742 return iterator(__n);
2745 template<
typename _Key,
typename _Value,
typename _Alloc,
2746 typename _ExtractKey,
typename _Equal,
2747 typename _Hash,
typename _RangeHash,
typename _Unused,
2748 typename _RehashPolicy,
typename _Traits>
2750 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2751 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2754 this->_M_deallocate_nodes(_M_begin());
2755 std::fill_n(_M_buckets, _M_bucket_count,
nullptr);
2756 _M_element_count = 0;
2757 _M_before_begin._M_nxt =
nullptr;
2760 template<
typename _Key,
typename _Value,
typename _Alloc,
2761 typename _ExtractKey,
typename _Equal,
2762 typename _Hash,
typename _RangeHash,
typename _Unused,
2763 typename _RehashPolicy,
typename _Traits>
2765 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2766 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2767 rehash(size_type __bkt_count)
2769 __rehash_guard_t __rehash_guard(_M_rehash_policy);
2771 =
std::max(_M_rehash_policy._M_bkt_for_elements(_M_element_count + 1),
2773 __bkt_count = _M_rehash_policy._M_next_bkt(__bkt_count);
2775 if (__bkt_count != _M_bucket_count)
2777 _M_rehash(__bkt_count, __unique_keys{});
2778 __rehash_guard._M_guarded_obj =
nullptr;
2783 template<
typename _Key,
typename _Value,
typename _Alloc,
2784 typename _ExtractKey,
typename _Equal,
2785 typename _Hash,
typename _RangeHash,
typename _Unused,
2786 typename _RehashPolicy,
typename _Traits>
2788 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2789 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2790 _M_rehash(size_type __bkt_count, true_type )
2792 __buckets_ptr __new_buckets = _M_allocate_buckets(__bkt_count);
2793 __node_ptr __p = _M_begin();
2794 _M_before_begin._M_nxt =
nullptr;
2795 std::size_t __bbegin_bkt = 0;
2798 __node_ptr __next = __p->_M_next();
2800 = __hash_code_base::_M_bucket_index(*__p, __bkt_count);
2801 if (!__new_buckets[__bkt])
2803 __p->_M_nxt = _M_before_begin._M_nxt;
2804 _M_before_begin._M_nxt = __p;
2805 __new_buckets[__bkt] = &_M_before_begin;
2807 __new_buckets[__bbegin_bkt] = __p;
2808 __bbegin_bkt = __bkt;
2812 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2813 __new_buckets[__bkt]->_M_nxt = __p;
2819 _M_deallocate_buckets();
2820 _M_bucket_count = __bkt_count;
2821 _M_buckets = __new_buckets;
2826 template<
typename _Key,
typename _Value,
typename _Alloc,
2827 typename _ExtractKey,
typename _Equal,
2828 typename _Hash,
typename _RangeHash,
typename _Unused,
2829 typename _RehashPolicy,
typename _Traits>
2831 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2832 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2833 _M_rehash(size_type __bkt_count, false_type )
2835 __buckets_ptr __new_buckets = _M_allocate_buckets(__bkt_count);
2836 __node_ptr __p = _M_begin();
2837 _M_before_begin._M_nxt =
nullptr;
2838 std::size_t __bbegin_bkt = 0;
2839 std::size_t __prev_bkt = 0;
2840 __node_ptr __prev_p =
nullptr;
2841 bool __check_bucket =
false;
2845 __node_ptr __next = __p->_M_next();
2847 = __hash_code_base::_M_bucket_index(*__p, __bkt_count);
2849 if (__prev_p && __prev_bkt == __bkt)
2854 __p->_M_nxt = __prev_p->_M_nxt;
2855 __prev_p->_M_nxt = __p;
2862 __check_bucket =
true;
2870 if (__prev_p->_M_nxt)
2872 std::size_t __next_bkt
2873 = __hash_code_base::_M_bucket_index(
2874 *__prev_p->_M_next(), __bkt_count);
2875 if (__next_bkt != __prev_bkt)
2876 __new_buckets[__next_bkt] = __prev_p;
2878 __check_bucket =
false;
2881 if (!__new_buckets[__bkt])
2883 __p->_M_nxt = _M_before_begin._M_nxt;
2884 _M_before_begin._M_nxt = __p;
2885 __new_buckets[__bkt] = &_M_before_begin;
2887 __new_buckets[__bbegin_bkt] = __p;
2888 __bbegin_bkt = __bkt;
2892 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2893 __new_buckets[__bkt]->_M_nxt = __p;
2901 if (__check_bucket && __prev_p->_M_nxt)
2903 std::size_t __next_bkt
2904 = __hash_code_base::_M_bucket_index(*__prev_p->_M_next(),
2906 if (__next_bkt != __prev_bkt)
2907 __new_buckets[__next_bkt] = __prev_p;
2910 _M_deallocate_buckets();
2911 _M_bucket_count = __bkt_count;
2912 _M_buckets = __new_buckets;
2915#pragma GCC diagnostic push
2916#pragma GCC diagnostic ignored "-Wc++17-extensions"
2921 template<
typename _Key,
typename _Value,
typename _Alloc,
2922 typename _ExtractKey,
typename _Equal,
2923 typename _Hash,
typename _RangeHash,
typename _Unused,
2924 typename _RehashPolicy,
typename _Traits>
2926 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2927 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2928 _M_equal(
const _Hashtable& __other)
const
2930 if (size() != __other.size())
2933 if constexpr (__unique_keys::value)
2934 for (
auto __x_n = _M_begin(); __x_n; __x_n = __x_n->_M_next())
2936 std::size_t __ybkt = __other._M_bucket_index_ext(*__x_n);
2937 auto __prev_n = __other._M_buckets[__ybkt];
2941 for (__node_ptr __n =
static_cast<__node_ptr
>(__prev_n->_M_nxt);;
2942 __n = __n->_M_next())
2944 if (__n->_M_v() == __x_n->_M_v())
2948 || __other._M_bucket_index(*__n->_M_next()) != __ybkt)
2953 for (
auto __x_n = _M_begin(); __x_n;)
2955 std::size_t __x_count = 1;
2956 auto __x_n_end = __x_n->_M_next();
2958 && key_eq()(_ExtractKey{}(__x_n->_M_v()),
2959 _ExtractKey{}(__x_n_end->_M_v()));
2960 __x_n_end = __x_n_end->_M_next())
2963 std::size_t __ybkt = __other._M_bucket_index_ext(*__x_n);
2964 auto __y_prev_n = __other._M_buckets[__ybkt];
2968 __node_ptr __y_n =
static_cast<__node_ptr
>(__y_prev_n->_M_nxt);
2971 if (key_eq()(_ExtractKey{}(__y_n->_M_v()),
2972 _ExtractKey{}(__x_n->_M_v())))
2975 auto __y_ref_n = __y_n;
2976 for (__y_n = __y_n->_M_next(); __y_n; __y_n = __y_n->_M_next())
2977 if (!__other._M_node_equals(*__y_ref_n, *__y_n))
2980 if (!__y_n || __other._M_bucket_index(*__y_n) != __ybkt)
2984 auto __y_n_end = __y_n;
2985 for (; __y_n_end; __y_n_end = __y_n_end->_M_next())
2986 if (--__x_count == 0)
2992 const_iterator __itx(__x_n), __itx_end(__x_n_end);
2993 const_iterator __ity(__y_n);
2994 if (!std::is_permutation(__itx, __itx_end, __ity))
3002#pragma GCC diagnostic pop
3004#ifdef __glibcxx_node_extract
3005 template<
typename,
typename,
typename>
class _Hash_merge_helper { };
3008#if __cpp_deduction_guides >= 201606
3010 template<
typename _Hash>
3011 using _RequireNotAllocatorOrIntegral
3012 = __enable_if_t<!__or_<is_integral<_Hash>, __is_allocator<_Hash>>::value>;
3015#ifdef __cpp_concepts
3016template <
typename _Kt,
typename _Container>
3017 concept __heterogeneous_hash_key =
3018 __transparent_comparator<typename _Container::hasher> &&
3019 __transparent_comparator<typename _Container::key_equal> &&
3020 __heterogeneous_key<_Kt, _Container>;
3024_GLIBCXX_END_NAMESPACE_VERSION
3027#pragma GCC diagnostic pop
__bool_constant< true > true_type
The type used as a compile-time boolean with true value.
pair(_T1, _T2) -> pair< _T1, _T2 >
Two pairs are equal iff their members are equal.
auto declval() noexcept -> decltype(__declval< _Tp >(0))
constexpr tuple< _Elements &&... > forward_as_tuple(_Elements &&... __args) noexcept
Create a tuple of lvalue or rvalue references to the arguments.
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
constexpr piecewise_construct_t piecewise_construct
Tag for piecewise construction of std::pair 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.
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.
Struct holding two objects of arbitrary type.
_T1 first
The first member.
_T2 second
The second member.