34#pragma GCC system_header
41#if __cplusplus > 201402L
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>
56 __is_fast_hash<_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>,
66 is_default_constructible<_Hash>,
67 is_default_constructible<_Allocator>>{},
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(
330 std::declval<const _RangeHash&>()((std::size_t)0, (std::size_t)0)),
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(
338 std::declval<const _ExtractKey&>()(std::declval<_Value>())),
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#if __cplusplus > 201402L
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);
453 _M_assign(std::forward<_Ht>(__ht), __alloc_node_gen);
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 __cplusplus <= 201402L
481 return __and_<__bool_constant<_No_realloc>,
482 is_nothrow_copy_constructible<_Hash>,
483 is_nothrow_copy_constructible<_Equal>>::value;
485 if constexpr (_No_realloc)
486 if constexpr (is_nothrow_copy_constructible<_Hash>())
487 return is_nothrow_copy_constructible<_Equal>();
492 _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a,
494 noexcept(_S_nothrow_move());
496 _Hashtable(_Hashtable&&, __node_alloc_type&&,
499 template<
typename _InputIterator>
500 _Hashtable(_InputIterator __first, _InputIterator __last,
501 size_type __bkt_count_hint,
502 const _Hash&,
const _Equal&,
const allocator_type&,
505 template<
typename _InputIterator>
506 _Hashtable(_InputIterator __first, _InputIterator __last,
507 size_type __bkt_count_hint,
508 const _Hash&,
const _Equal&,
const allocator_type&,
513 _Hashtable() =
default;
515 _Hashtable(
const _Hashtable&);
517 _Hashtable(
const _Hashtable&,
const allocator_type&);
520 _Hashtable(size_type __bkt_count_hint,
521 const _Hash& __hf = _Hash(),
522 const key_equal& __eql = key_equal(),
523 const allocator_type& __a = allocator_type());
526 _Hashtable(_Hashtable&& __ht)
527 noexcept(_S_nothrow_move())
528 : _Hashtable(
std::
move(__ht),
std::
move(__ht._M_node_allocator()),
532 _Hashtable(_Hashtable&& __ht,
const allocator_type& __a)
533 noexcept(_S_nothrow_move<__node_alloc_traits::_S_always_equal()>())
534 : _Hashtable(
std::
move(__ht), __node_alloc_type(__a),
535 typename __node_alloc_traits::is_always_equal{})
539 _Hashtable(
const allocator_type& __a)
540 : __hashtable_alloc(__node_alloc_type(__a)),
541 __enable_default_ctor(_Enable_default_constructor_tag{})
544 template<
typename _InputIterator>
545 _Hashtable(_InputIterator __f, _InputIterator __l,
546 size_type __bkt_count_hint = 0,
547 const _Hash& __hf = _Hash(),
548 const key_equal& __eql = key_equal(),
549 const allocator_type& __a = allocator_type())
550 : _Hashtable(__f, __l, __bkt_count_hint, __hf, __eql, __a,
554 _Hashtable(initializer_list<value_type> __l,
555 size_type __bkt_count_hint = 0,
556 const _Hash& __hf = _Hash(),
557 const key_equal& __eql = key_equal(),
558 const allocator_type& __a = allocator_type())
559 : _Hashtable(__l.
begin(), __l.
end(), __bkt_count_hint,
560 __hf, __eql, __a, __unique_keys{})
564 operator=(
const _Hashtable& __ht);
567 operator=(_Hashtable&& __ht)
568 noexcept(__node_alloc_traits::_S_nothrow_move()
569 && is_nothrow_move_assignable<_Hash>::value
570 && is_nothrow_move_assignable<_Equal>::value)
572 constexpr bool __move_storage =
573 __node_alloc_traits::_S_propagate_on_move_assign()
574 || __node_alloc_traits::_S_always_equal();
575 _M_move_assign(
std::move(__ht), __bool_constant<__move_storage>());
579#pragma GCC diagnostic push
580#pragma GCC diagnostic ignored "-Wc++17-extensions"
582 operator=(initializer_list<value_type> __l)
584 using __reuse_or_alloc_node_gen_t =
585 __detail::_ReuseOrAllocNode<__node_alloc_type>;
587 __reuse_or_alloc_node_gen_t __roan(_M_begin(), *
this);
588 _M_before_begin._M_nxt =
nullptr;
592 auto __l_bkt_count = _M_rehash_policy._M_bkt_for_elements(__l.size());
596 if (_M_bucket_count < __l_bkt_count)
597 rehash(__l_bkt_count);
601 for (
auto& __e : __l)
603 const key_type& __k = _ExtractKey{}(__e);
605 if constexpr (__unique_keys::value)
607 if (
auto __loc = _M_locate(__k))
611 __code = __loc._M_hash_code;
612 __bkt = __loc._M_bucket_index;
617 __code = this->_M_hash_code(__k);
618 __bkt = _M_bucket_index(__code);
621 _M_insert_unique_node(__bkt, __code, __roan(__e));
626#pragma GCC diagnostic pop
628 ~_Hashtable() noexcept;
632 noexcept(__and_<__is_nothrow_swappable<_Hash>,
633 __is_nothrow_swappable<_Equal>>::value);
638 {
return iterator(_M_begin()); }
641 begin() const noexcept
642 {
return const_iterator(_M_begin()); }
646 {
return iterator(
nullptr); }
650 {
return const_iterator(
nullptr); }
654 {
return const_iterator(_M_begin()); }
657 cend() const noexcept
658 {
return const_iterator(
nullptr); }
661 size() const noexcept
662 {
return _M_element_count; }
664 _GLIBCXX_NODISCARD
bool
665 empty() const noexcept
666 {
return size() == 0; }
669 get_allocator() const noexcept
670 {
return allocator_type(this->_M_node_allocator()); }
673 max_size() const noexcept
674 {
return __node_alloc_traits::max_size(this->_M_node_allocator()); }
679 {
return this->_M_eq(); }
685 bucket_count() const noexcept
686 {
return _M_bucket_count; }
689 max_bucket_count() const noexcept
690 {
return max_size(); }
693 bucket_size(size_type __bkt)
const
697 bucket(
const key_type& __k)
const
698 {
return _M_bucket_index(this->_M_hash_code(__k)); }
701 begin(size_type __bkt)
703 return local_iterator(*
this, _M_bucket_begin(__bkt),
704 __bkt, _M_bucket_count);
709 {
return local_iterator(*
this,
nullptr, __bkt, _M_bucket_count); }
712 begin(size_type __bkt)
const
714 return const_local_iterator(*
this, _M_bucket_begin(__bkt),
715 __bkt, _M_bucket_count);
719 end(size_type __bkt)
const
720 {
return const_local_iterator(*
this,
nullptr, __bkt, _M_bucket_count); }
724 cbegin(size_type __bkt)
const
726 return const_local_iterator(*
this, _M_bucket_begin(__bkt),
727 __bkt, _M_bucket_count);
731 cend(size_type __bkt)
const
732 {
return const_local_iterator(*
this,
nullptr, __bkt, _M_bucket_count); }
735 load_factor() const noexcept
737 return static_cast<float>(
size()) /
static_cast<float>(bucket_count());
746 __rehash_policy()
const
747 {
return _M_rehash_policy; }
750 __rehash_policy(
const _RehashPolicy& __pol)
751 { _M_rehash_policy = __pol; }
755 find(
const key_type& __k);
758 find(
const key_type& __k)
const;
761 count(
const key_type& __k)
const;
764 equal_range(
const key_type& __k);
767 equal_range(
const key_type& __k)
const;
769#ifdef __glibcxx_generic_unordered_lookup
770 template<
typename _Kt,
771 typename = __has_is_transparent_t<_Hash, _Kt>,
772 typename = __has_is_transparent_t<_Equal, _Kt>>
774 _M_find_tr(
const _Kt& __k);
776 template<
typename _Kt,
777 typename = __has_is_transparent_t<_Hash, _Kt>,
778 typename = __has_is_transparent_t<_Equal, _Kt>>
780 _M_find_tr(
const _Kt& __k)
const;
782 template<
typename _Kt,
783 typename = __has_is_transparent_t<_Hash, _Kt>,
784 typename = __has_is_transparent_t<_Equal, _Kt>>
786 _M_count_tr(
const _Kt& __k)
const;
788 template<
typename _Kt,
789 typename = __has_is_transparent_t<_Hash, _Kt>,
790 typename = __has_is_transparent_t<_Equal, _Kt>>
791 pair<iterator, iterator>
792 _M_equal_range_tr(
const _Kt& __k);
794 template<
typename _Kt,
795 typename = __has_is_transparent_t<_Hash, _Kt>,
796 typename = __has_is_transparent_t<_Equal, _Kt>>
797 pair<const_iterator, const_iterator>
798 _M_equal_range_tr(
const _Kt& __k)
const;
804 _M_bucket_index(
const __node_value_type& __n)
const noexcept
805 {
return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); }
808 _M_bucket_index(__hash_code __c)
const
809 {
return __hash_code_base::_M_bucket_index(__c, _M_bucket_count); }
811#pragma GCC diagnostic push
812#pragma GCC diagnostic ignored "-Wc++17-extensions"
817 _M_hash_code_ext(
const __node_value_type& __from)
const
819 if constexpr (__and_<__hash_cached, is_empty<_Hash>>::value)
820 return __from._M_hash_code;
822 return this->_M_hash_code(_ExtractKey{}(__from._M_v()));
828 _M_bucket_index_ext(
const __node_value_type& __from)
const
829 {
return _RangeHash{}(_M_hash_code_ext(__from), _M_bucket_count); }
832 _M_copy_code(__node_value_type& __to,
833 const __node_value_type& __from)
const
835 if constexpr (__hash_cached::value)
836 __to._M_hash_code = _M_hash_code_ext(__from);
840 _M_store_code(__node_value_type& __to, __hash_code __code)
const
842 if constexpr (__hash_cached::value)
843 __to._M_hash_code = __code;
845#pragma GCC diagnostic pop
851 _M_find_before_node(size_type,
const key_type&, __hash_code)
const;
853 template<
typename _Kt>
855 _M_find_before_node_tr(size_type,
const _Kt&, __hash_code)
const;
859 struct __location_type
862 explicit operator bool() const noexcept
863 {
return static_cast<bool>(_M_before); }
866 explicit operator iterator() const noexcept
867 {
return iterator(_M_node()); }
870 explicit operator const_iterator() const noexcept
871 {
return const_iterator(_M_node()); }
874 __node_ptr _M_node()
const
877 return static_cast<__node_ptr
>(_M_before->_M_nxt);
881 __node_base_ptr _M_before{};
882 __hash_code _M_hash_code{};
883 size_type _M_bucket_index = size_type(-1);
901 _M_locate(
const key_type& __k)
const;
904 _M_find_node(size_type __bkt,
const key_type& __key,
905 __hash_code __c)
const
907 if (__node_base_ptr __before_n = _M_find_before_node(__bkt, __key, __c))
908 return static_cast<__node_ptr
>(__before_n->_M_nxt);
912 template<
typename _Kt>
914 _M_find_node_tr(size_type __bkt,
const _Kt& __key,
915 __hash_code __c)
const
917 if (
auto __before_n = _M_find_before_node_tr(__bkt, __key, __c))
918 return static_cast<__node_ptr
>(__before_n->_M_nxt);
924 _M_insert_bucket_begin(size_type __bkt, __node_ptr __node)
926 if (_M_buckets[__bkt])
930 __node->_M_nxt = _M_buckets[__bkt]->_M_nxt;
931 _M_buckets[__bkt]->_M_nxt = __node;
938 __node->_M_nxt = _M_before_begin._M_nxt;
939 _M_before_begin._M_nxt = __node;
944 _M_buckets[_M_bucket_index(*__node->_M_next())] = __node;
946 _M_buckets[__bkt] = &_M_before_begin;
952 _M_remove_bucket_begin(size_type __bkt, __node_ptr __next_n,
953 size_type __next_bkt)
956 _M_buckets[__bkt] =
nullptr;
957 else if (__next_bkt != __bkt)
959 _M_buckets[__next_bkt] = _M_buckets[__bkt];
960 _M_buckets[__bkt] =
nullptr;
966 _M_get_previous_node(size_type __bkt, __node_ptr __n);
968 pair<__node_ptr, __hash_code>
969 _M_compute_hash_code(__node_ptr __hint,
const key_type& __k)
const;
978 _M_insert_unique_node(size_type __bkt, __hash_code,
979 __node_ptr __n, size_type __n_elt = 1);
984 _M_insert_multi_node(__node_ptr __hint,
985 __hash_code __code, __node_ptr __n);
987 template<
typename... _Args>
989 _M_emplace_uniq(_Args&&... __args);
991#pragma GCC diagnostic push
992#pragma GCC diagnostic ignored "-Wc++14-extensions"
993 template<
typename _Arg,
typename _DArg = __remove_cvref_t<_Arg>,
994 typename = _ExtractKey>
995 static constexpr bool __is_key_type =
false;
997 template<
typename _Arg>
998 static constexpr bool
999 __is_key_type<_Arg, key_type, __detail::_Identity> =
true;
1001 template<
typename _Arg,
typename _Arg1,
typename _Arg2>
1002 static constexpr bool
1003 __is_key_type<_Arg, pair<_Arg1, _Arg2>, __detail::_Select1st>
1004 = is_same<__remove_cvref_t<_Arg1>, key_type>::value;
1005#pragma GCC diagnostic pop
1007 template<
typename... _Args>
1009 _M_emplace_multi(const_iterator, _Args&&... __args);
1012 _M_erase(size_type __bkt, __node_base_ptr __prev_n, __node_ptr __n);
1014 template<
typename _InputIterator>
1016 _M_insert_range_multi(_InputIterator __first, _InputIterator __last);
1019#pragma GCC diagnostic push
1020#pragma GCC diagnostic ignored "-Wc++17-extensions"
1022 template<
typename... _Args>
1024 emplace(_Args&&... __args)
1026 if constexpr (__unique_keys::value)
1027 return _M_emplace_uniq(std::forward<_Args>(__args)...);
1029 return _M_emplace_multi(
cend(), std::forward<_Args>(__args)...);
1032 template<
typename... _Args>
1034 emplace_hint(const_iterator __hint, _Args&&... __args)
1036 if constexpr (__unique_keys::value)
1037 return _M_emplace_uniq(std::forward<_Args>(__args)...).first;
1039 return _M_emplace_multi(__hint, std::forward<_Args>(__args)...);
1044 insert(
const value_type& __v)
1046 if constexpr (__unique_keys::value)
1047 return _M_emplace_uniq(__v);
1049 return _M_emplace_multi(
cend(), __v);
1053 insert(const_iterator __hint,
const value_type& __v)
1055 if constexpr (__unique_keys::value)
1056 return _M_emplace_uniq(__v).first;
1058 return _M_emplace_multi(__hint, __v);
1062 insert(value_type&& __v)
1064 if constexpr (__unique_keys::value)
1071 insert(const_iterator __hint, value_type&& __v)
1073 if constexpr (__unique_keys::value)
1074 return _M_emplace_uniq(
std::move(__v)).first;
1076 return _M_emplace_multi(__hint,
std::move(__v));
1079#ifdef __glibcxx_unordered_map_try_emplace
1080 template<
typename _KType,
typename... _Args>
1082 try_emplace(const_iterator, _KType&& __k, _Args&&... __args)
1086 if (
auto __loc = _M_locate(__k))
1087 return { iterator(__loc),
false };
1090 __code = __loc._M_hash_code;
1091 __bkt = __loc._M_bucket_index;
1094 _Scoped_node __node {
1100 auto __it = _M_insert_unique_node(__bkt, __code, __node._M_node);
1101 __node._M_node =
nullptr;
1102 return { __it,
true };
1107 insert(initializer_list<value_type> __l)
1108 { this->insert(__l.begin(), __l.end()); }
1110 template<
typename _InputIterator>
1112 insert(_InputIterator __first, _InputIterator __last)
1114 if constexpr (__unique_keys::value)
1115 for (; __first != __last; ++__first)
1116 _M_emplace_uniq(*__first);
1118 return _M_insert_range_multi(__first, __last);
1122 template<
typename _Pair,
1123 typename = _Require<__not_<is_same<_Key, _Value>>,
1124 is_constructible<value_type, _Pair&&>>>
1128 if constexpr (__unique_keys::value)
1129 return _M_emplace_uniq(std::forward<_Pair>(__v));
1131 return _M_emplace_multi(
cend(), std::forward<_Pair>(__v));
1135 template<
typename _Pair,
1136 typename = _Require<__not_<is_same<_Key, _Value>>,
1137 is_constructible<value_type, _Pair&&>>>
1139 insert(const_iterator __hint, _Pair&& __v)
1141 if constexpr (__unique_keys::value)
1142 return _M_emplace_uniq(std::forward<_Pair>(__v));
1144 return _M_emplace_multi(__hint, std::forward<_Pair>(__v));
1146#pragma GCC diagnostic pop
1150 erase(const_iterator);
1155 erase(iterator __it)
1156 {
return erase(const_iterator(__it)); }
1159 erase(
const key_type& __k);
1162 erase(const_iterator, const_iterator);
1169 void rehash(size_type __bkt_count);
1174#if __glibcxx_node_extract
1177 _M_reinsert_node(node_type&& __nh)
1179 insert_return_type __ret;
1181 __ret.position =
end();
1184 __glibcxx_assert(get_allocator() == __nh.get_allocator());
1186 if (
auto __loc = _M_locate(__nh._M_key()))
1189 __ret.position = iterator(__loc);
1190 __ret.inserted =
false;
1194 auto __code = __loc._M_hash_code;
1195 auto __bkt = __loc._M_bucket_index;
1197 = _M_insert_unique_node(__bkt, __code, __nh._M_ptr);
1198 __ret.inserted =
true;
1207 _M_reinsert_node_multi(const_iterator __hint, node_type&& __nh)
1212 __glibcxx_assert(get_allocator() == __nh.get_allocator());
1214 const key_type& __k = __nh._M_key();
1215 auto __code = this->_M_hash_code(__k);
1217 = _M_insert_multi_node(__hint._M_cur, __code, __nh._M_ptr);
1224 _M_extract_node(
size_t __bkt, __node_base_ptr __prev_n)
1226 __node_ptr __n =
static_cast<__node_ptr
>(__prev_n->_M_nxt);
1227 if (__prev_n == _M_buckets[__bkt])
1228 _M_remove_bucket_begin(__bkt, __n->_M_next(),
1229 __n->_M_nxt ? _M_bucket_index(*__n->_M_next()) : 0);
1230 else if (__n->_M_nxt)
1232 size_type __next_bkt = _M_bucket_index(*__n->_M_next());
1233 if (__next_bkt != __bkt)
1234 _M_buckets[__next_bkt] = __prev_n;
1237 __prev_n->_M_nxt = __n->_M_nxt;
1238 __n->_M_nxt =
nullptr;
1240 return { __n, this->_M_node_allocator() };
1247 template<
typename _H2>
1249 _M_src_hash_code(
const _H2&,
const __node_value_type& __src_n)
const
1251 if constexpr (__and_<__hash_cached,
1252 is_same<_H2, _Hash>, is_empty<_Hash>>::value)
1254 return __src_n._M_hash_code;
1256 return this->_M_hash_code(_ExtractKey{}(__src_n._M_v()));
1262 extract(const_iterator __pos)
1264 size_t __bkt = _M_bucket_index(*__pos._M_cur);
1265 return _M_extract_node(__bkt,
1266 _M_get_previous_node(__bkt, __pos._M_cur));
1271 extract(
const _Key& __k)
1274 __hash_code __code = this->_M_hash_code(__k);
1275 std::size_t __bkt = _M_bucket_index(__code);
1276 if (__node_base_ptr __prev_node = _M_find_before_node(__bkt, __k, __code))
1277 __nh = _M_extract_node(__bkt, __prev_node);
1283 _M_merge_unique(_Hashtable& __src)
1285 __glibcxx_assert(get_allocator() == __src.get_allocator());
1287 using _PTr = pointer_traits<__node_base_ptr>;
1289 auto __n_elt = __src.size();
1290 size_type __first = 1;
1293 auto __prev = _PTr::pointer_to(__src._M_before_begin);
1296 const auto __next = __prev->_M_nxt;
1297 const auto& __node =
static_cast<__node_type&
>(*__next);
1298 const key_type& __k = _ExtractKey{}(__node._M_v());
1299 const auto __loc = _M_locate(__k);
1306 auto __src_bkt = __src._M_bucket_index(__node);
1307 auto __nh = __src._M_extract_node(__src_bkt, __prev);
1308 _M_insert_unique_node(__loc._M_bucket_index, __loc._M_hash_code,
1309 __nh._M_ptr, __first * __n_elt + 1);
1316 template<
typename _Compatible_Hashtable>
1318 _M_merge_unique(_Compatible_Hashtable& __src)
1320 static_assert(is_same_v<
typename _Compatible_Hashtable::node_type,
1321 node_type>,
"Node types are compatible");
1322 __glibcxx_assert(get_allocator() == __src.get_allocator());
1324 auto __n_elt = __src.size();
1325 size_type __first = 1;
1328 for (
auto __i = __src.cbegin(), __end = __src.cend(); __i != __end;)
1332 const key_type& __k = _ExtractKey{}(*__pos);
1333 const auto __loc = _M_locate(__k);
1337 auto __nh = __src.extract(__pos);
1338 _M_insert_unique_node(__loc._M_bucket_index,
1339 __loc._M_hash_code, __nh._M_ptr,
1340 __first * __n_elt + 1);
1348 _M_merge_multi(_Hashtable& __src)
1350 __glibcxx_assert(get_allocator() == __src.get_allocator());
1352 if (__src.size() == 0) [[__unlikely__]]
1355 using _PTr = pointer_traits<__node_base_ptr>;
1357 __node_ptr __hint =
nullptr;
1358 this->reserve(
size() + __src.size());
1361 auto __prev = _PTr::pointer_to(__src._M_before_begin);
1364 const auto& __node =
static_cast<__node_type&
>(*__prev->_M_nxt);
1366 auto __code = _M_hash_code_ext(__node);
1368 size_type __src_bkt = __src._M_bucket_index(__node);
1369 auto __nh = __src._M_extract_node(__src_bkt, __prev);
1370 __hint = _M_insert_multi_node(__hint, __code, __nh._M_ptr)._M_cur;
1373 while (__prev->_M_nxt !=
nullptr);
1377 template<
typename _Compatible_Hashtable>
1379 _M_merge_multi(_Compatible_Hashtable& __src)
1381 static_assert(is_same_v<
typename _Compatible_Hashtable::node_type,
1382 node_type>,
"Node types are compatible");
1383 __glibcxx_assert(get_allocator() == __src.get_allocator());
1385 __node_ptr __hint =
nullptr;
1386 this->reserve(
size() + __src.size());
1389 for (
auto __i = __src.cbegin(), __end = __src.cend(); __i != __end;)
1393 = _M_src_hash_code(__src.hash_function(), *__pos._M_cur);
1394 auto __nh = __src.extract(__pos);
1395 __hint = _M_insert_multi_node(__hint, __code, __nh._M_ptr)._M_cur;
1402 _M_equal(
const _Hashtable& __other)
const;
1406 void _M_rehash(size_type __bkt_count, true_type __uks);
1409 void _M_rehash(size_type __bkt_count, false_type __uks);
1413 template<
typename _Key,
typename _Value,
typename _Alloc,
1414 typename _ExtractKey,
typename _Equal,
1415 typename _Hash,
typename _RangeHash,
typename _Unused,
1416 typename _RehashPolicy,
typename _Traits>
1417 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1418 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1419 _Hashtable(size_type __bkt_count_hint,
1420 const _Hash& __h,
const _Equal& __eq,
const allocator_type& __a)
1421 : _Hashtable(__h, __eq, __a)
1423 auto __bkt_count = _M_rehash_policy._M_next_bkt(__bkt_count_hint);
1424 if (__bkt_count > _M_bucket_count)
1426 _M_buckets = _M_allocate_buckets(__bkt_count);
1427 _M_bucket_count = __bkt_count;
1431 template<
typename _Key,
typename _Value,
typename _Alloc,
1432 typename _ExtractKey,
typename _Equal,
1433 typename _Hash,
typename _RangeHash,
typename _Unused,
1434 typename _RehashPolicy,
typename _Traits>
1435 template<
typename _InputIterator>
1437 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1438 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1439 _Hashtable(_InputIterator __f, _InputIterator __l,
1440 size_type __bkt_count_hint,
1441 const _Hash& __h,
const _Equal& __eq,
1442 const allocator_type& __a, true_type )
1443 : _Hashtable(__bkt_count_hint, __h, __eq, __a)
1444 { this->insert(__f, __l); }
1446 template<
typename _Key,
typename _Value,
typename _Alloc,
1447 typename _ExtractKey,
typename _Equal,
1448 typename _Hash,
typename _RangeHash,
typename _Unused,
1449 typename _RehashPolicy,
typename _Traits>
1450 template<
typename _InputIterator>
1451 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1452 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1453 _Hashtable(_InputIterator __f, _InputIterator __l,
1454 size_type __bkt_count_hint,
1455 const _Hash& __h,
const _Equal& __eq,
1456 const allocator_type& __a, false_type __uks)
1457 : _Hashtable(__h, __eq, __a)
1459 auto __nb_elems = __detail::__distance_fw(__f, __l);
1461 _M_rehash_policy._M_next_bkt(
1462 std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems),
1465 if (__bkt_count > _M_bucket_count)
1467 _M_buckets = _M_allocate_buckets(__bkt_count);
1468 _M_bucket_count = __bkt_count;
1471 for (; __f != __l; ++__f)
1472 _M_emplace_multi(
cend(), *__f);
1475 template<
typename _Key,
typename _Value,
typename _Alloc,
1476 typename _ExtractKey,
typename _Equal,
1477 typename _Hash,
typename _RangeHash,
typename _Unused,
1478 typename _RehashPolicy,
typename _Traits>
1480 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1481 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1482 operator=(
const _Hashtable& __ht)
1488 if (__node_alloc_traits::_S_propagate_on_copy_assign())
1490 auto& __this_alloc = this->_M_node_allocator();
1491 auto& __that_alloc = __ht._M_node_allocator();
1492 if (!__node_alloc_traits::_S_always_equal()
1493 && __this_alloc != __that_alloc)
1496 this->_M_deallocate_nodes(_M_begin());
1497 _M_before_begin._M_nxt =
nullptr;
1498 _M_deallocate_buckets();
1499 _M_buckets =
nullptr;
1500 std::__alloc_on_copy(__this_alloc, __that_alloc);
1501 __hashtable_base::operator=(__ht);
1502 _M_bucket_count = __ht._M_bucket_count;
1503 _M_element_count = __ht._M_element_count;
1504 _M_rehash_policy = __ht._M_rehash_policy;
1508 ~_Guard() {
if (_M_ht) _M_ht->_M_reset(); }
1513 _Guard __guard{
this};
1515 __guard._M_ht =
nullptr;
1518 std::__alloc_on_copy(__this_alloc, __that_alloc);
1522 _M_assign_elements(__ht);
1526 template<
typename _Key,
typename _Value,
typename _Alloc,
1527 typename _ExtractKey,
typename _Equal,
1528 typename _Hash,
typename _RangeHash,
typename _Unused,
1529 typename _RehashPolicy,
typename _Traits>
1530 template<
typename _Ht>
1532 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1533 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1534 _M_assign_elements(_Ht&& __ht)
1536 using __reuse_or_alloc_node_gen_t =
1537 __detail::_ReuseOrAllocNode<__node_alloc_type>;
1539 __buckets_ptr __former_buckets =
nullptr;
1540 std::size_t __former_bucket_count = _M_bucket_count;
1541 __rehash_guard_t __rehash_guard(_M_rehash_policy);
1543 if (_M_bucket_count != __ht._M_bucket_count)
1545 __former_buckets = _M_buckets;
1546 _M_buckets = _M_allocate_buckets(__ht._M_bucket_count);
1547 _M_bucket_count = __ht._M_bucket_count;
1550 std::fill_n(_M_buckets, _M_bucket_count,
nullptr);
1554 __hashtable_base::operator=(std::forward<_Ht>(__ht));
1555 _M_element_count = __ht._M_element_count;
1556 _M_rehash_policy = __ht._M_rehash_policy;
1557 __reuse_or_alloc_node_gen_t __roan(_M_begin(), *
this);
1558 _M_before_begin._M_nxt =
nullptr;
1559 _M_assign(std::forward<_Ht>(__ht), __roan);
1560 if (__former_buckets)
1561 _M_deallocate_buckets(__former_buckets, __former_bucket_count);
1562 __rehash_guard._M_guarded_obj =
nullptr;
1566 if (__former_buckets)
1569 _M_deallocate_buckets();
1570 _M_buckets = __former_buckets;
1571 _M_bucket_count = __former_bucket_count;
1573 std::fill_n(_M_buckets, _M_bucket_count,
nullptr);
1574 __throw_exception_again;
1578 template<
typename _Key,
typename _Value,
typename _Alloc,
1579 typename _ExtractKey,
typename _Equal,
1580 typename _Hash,
typename _RangeHash,
typename _Unused,
1581 typename _RehashPolicy,
typename _Traits>
1582 template<
typename _Ht,
typename _NodeGenerator>
1584 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1585 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1586 _M_assign(_Ht&& __ht, _NodeGenerator& __node_gen)
1595 if (_M_dealloc_buckets)
1596 _M_ht->_M_deallocate_buckets();
1599 _Hashtable* _M_ht =
nullptr;
1600 bool _M_dealloc_buckets =
false;
1606 _M_buckets = _M_allocate_buckets(_M_bucket_count);
1607 __guard._M_dealloc_buckets =
true;
1610 if (!__ht._M_before_begin._M_nxt)
1613 __guard._M_ht =
this;
1615 using _FromVal = __conditional_t<is_lvalue_reference<_Ht>::value,
1616 const value_type&, value_type&&>;
1620 __node_ptr __ht_n = __ht._M_begin();
1622 = __node_gen(
static_cast<_FromVal
>(__ht_n->_M_v()));
1623 _M_copy_code(*__this_n, *__ht_n);
1624 _M_update_bbegin(__this_n);
1627 __node_ptr __prev_n = __this_n;
1628 for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next())
1630 __this_n = __node_gen(
static_cast<_FromVal
>(__ht_n->_M_v()));
1631 __prev_n->_M_nxt = __this_n;
1632 _M_copy_code(*__this_n, *__ht_n);
1633 size_type __bkt = _M_bucket_index(*__this_n);
1634 if (!_M_buckets[__bkt])
1635 _M_buckets[__bkt] = __prev_n;
1636 __prev_n = __this_n;
1638 __guard._M_ht =
nullptr;
1641 template<
typename _Key,
typename _Value,
typename _Alloc,
1642 typename _ExtractKey,
typename _Equal,
1643 typename _Hash,
typename _RangeHash,
typename _Unused,
1644 typename _RehashPolicy,
typename _Traits>
1646 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1647 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1650 _M_rehash_policy._M_reset();
1651 _M_bucket_count = 1;
1652 _M_single_bucket =
nullptr;
1653 _M_buckets = &_M_single_bucket;
1654 _M_before_begin._M_nxt =
nullptr;
1655 _M_element_count = 0;
1658 template<
typename _Key,
typename _Value,
typename _Alloc,
1659 typename _ExtractKey,
typename _Equal,
1660 typename _Hash,
typename _RangeHash,
typename _Unused,
1661 typename _RehashPolicy,
typename _Traits>
1663 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1664 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1665 _M_move_assign(_Hashtable&& __ht, true_type)
1670 this->_M_deallocate_nodes(_M_begin());
1671 _M_deallocate_buckets();
1672 __hashtable_base::operator=(
std::move(__ht));
1673 _M_rehash_policy = __ht._M_rehash_policy;
1674 if (!__ht._M_uses_single_bucket())
1675 _M_buckets = __ht._M_buckets;
1678 _M_buckets = &_M_single_bucket;
1679 _M_single_bucket = __ht._M_single_bucket;
1682 _M_bucket_count = __ht._M_bucket_count;
1683 _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt;
1684 _M_element_count = __ht._M_element_count;
1685 std::__alloc_on_move(this->_M_node_allocator(), __ht._M_node_allocator());
1692 template<
typename _Key,
typename _Value,
typename _Alloc,
1693 typename _ExtractKey,
typename _Equal,
1694 typename _Hash,
typename _RangeHash,
typename _Unused,
1695 typename _RehashPolicy,
typename _Traits>
1697 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1698 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1699 _M_move_assign(_Hashtable&& __ht, false_type)
1701 if (__ht._M_node_allocator() == this->_M_node_allocator())
1702 _M_move_assign(
std::move(__ht), true_type{});
1711 template<
typename _Key,
typename _Value,
typename _Alloc,
1712 typename _ExtractKey,
typename _Equal,
1713 typename _Hash,
typename _RangeHash,
typename _Unused,
1714 typename _RehashPolicy,
typename _Traits>
1716 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1717 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1718 _Hashtable(
const _Hashtable& __ht)
1719 : __hashtable_base(__ht),
1721 __rehash_base(__ht),
1723 __node_alloc_traits::_S_select_on_copy(__ht._M_node_allocator())),
1724 __enable_default_ctor(__ht),
1725 _M_buckets(nullptr),
1726 _M_bucket_count(__ht._M_bucket_count),
1727 _M_element_count(__ht._M_element_count),
1728 _M_rehash_policy(__ht._M_rehash_policy)
1733 template<
typename _Key,
typename _Value,
typename _Alloc,
1734 typename _ExtractKey,
typename _Equal,
1735 typename _Hash,
typename _RangeHash,
typename _Unused,
1736 typename _RehashPolicy,
typename _Traits>
1737 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1738 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1739 _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a,
1741 noexcept(_S_nothrow_move())
1742 : __hashtable_base(__ht),
1744 __rehash_base(__ht),
1745 __hashtable_alloc(
std::
move(__a)),
1746 __enable_default_ctor(__ht),
1747 _M_buckets(__ht._M_buckets),
1748 _M_bucket_count(__ht._M_bucket_count),
1749 _M_before_begin(__ht._M_before_begin._M_nxt),
1750 _M_element_count(__ht._M_element_count),
1751 _M_rehash_policy(__ht._M_rehash_policy)
1754 if (__ht._M_uses_single_bucket())
1756 _M_buckets = &_M_single_bucket;
1757 _M_single_bucket = __ht._M_single_bucket;
1766 template<
typename _Key,
typename _Value,
typename _Alloc,
1767 typename _ExtractKey,
typename _Equal,
1768 typename _Hash,
typename _RangeHash,
typename _Unused,
1769 typename _RehashPolicy,
typename _Traits>
1771 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1772 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1773 _Hashtable(
const _Hashtable& __ht,
const allocator_type& __a)
1774 : __hashtable_base(__ht),
1776 __rehash_base(__ht),
1777 __hashtable_alloc(__node_alloc_type(__a)),
1778 __enable_default_ctor(__ht),
1780 _M_bucket_count(__ht._M_bucket_count),
1781 _M_element_count(__ht._M_element_count),
1782 _M_rehash_policy(__ht._M_rehash_policy)
1787 template<
typename _Key,
typename _Value,
typename _Alloc,
1788 typename _ExtractKey,
typename _Equal,
1789 typename _Hash,
typename _RangeHash,
typename _Unused,
1790 typename _RehashPolicy,
typename _Traits>
1791 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1792 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1793 _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a,
1795 : __hashtable_base(__ht),
1797 __rehash_base(__ht),
1798 __hashtable_alloc(
std::
move(__a)),
1799 __enable_default_ctor(__ht),
1800 _M_buckets(nullptr),
1801 _M_bucket_count(__ht._M_bucket_count),
1802 _M_element_count(__ht._M_element_count),
1803 _M_rehash_policy(__ht._M_rehash_policy)
1805 if (__ht._M_node_allocator() == this->_M_node_allocator())
1807 if (__ht._M_uses_single_bucket())
1809 _M_buckets = &_M_single_bucket;
1810 _M_single_bucket = __ht._M_single_bucket;
1813 _M_buckets = __ht._M_buckets;
1817 _M_update_bbegin(__ht._M_begin());
1823 using _Fwd_Ht = __conditional_t<
1824 __move_if_noexcept_cond<value_type>::value,
1825 const _Hashtable&, _Hashtable&&>;
1826 _M_assign(std::forward<_Fwd_Ht>(__ht));
1831 template<
typename _Key,
typename _Value,
typename _Alloc,
1832 typename _ExtractKey,
typename _Equal,
1833 typename _Hash,
typename _RangeHash,
typename _Unused,
1834 typename _RehashPolicy,
typename _Traits>
1835 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1836 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1837 ~_Hashtable() noexcept
1844 static_assert(
noexcept(declval<const __hash_code_base_access&>()
1845 ._M_bucket_index(declval<const __node_value_type&>(),
1847 "Cache the hash code or qualify your functors involved"
1848 " in hash code and bucket index computation with noexcept");
1850 this->_M_deallocate_nodes(_M_begin());
1851 _M_deallocate_buckets();
1854 template<
typename _Key,
typename _Value,
typename _Alloc,
1855 typename _ExtractKey,
typename _Equal,
1856 typename _Hash,
typename _RangeHash,
typename _Unused,
1857 typename _RehashPolicy,
typename _Traits>
1859 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1860 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1861 swap(_Hashtable& __x)
1862 noexcept(__and_<__is_nothrow_swappable<_Hash>,
1863 __is_nothrow_swappable<_Equal>>::value)
1866 swap(__hash_code_base::_M_hash._M_obj,
1867 __x.__hash_code_base::_M_hash._M_obj);
1868 swap(__hashtable_base::_M_equal._M_obj,
1869 __x.__hashtable_base::_M_equal._M_obj);
1871#pragma GCC diagnostic push
1872#pragma GCC diagnostic ignored "-Wc++17-extensions"
1873 if constexpr (__node_alloc_traits::propagate_on_container_swap::value)
1874 swap(this->_M_node_allocator(), __x._M_node_allocator());
1875#pragma GCC diagnostic pop
1877 std::swap(_M_rehash_policy, __x._M_rehash_policy);
1880 if (this->_M_uses_single_bucket())
1882 if (!__x._M_uses_single_bucket())
1884 _M_buckets = __x._M_buckets;
1885 __x._M_buckets = &__x._M_single_bucket;
1888 else if (__x._M_uses_single_bucket())
1890 __x._M_buckets = _M_buckets;
1891 _M_buckets = &_M_single_bucket;
1894 std::swap(_M_buckets, __x._M_buckets);
1896 std::swap(_M_bucket_count, __x._M_bucket_count);
1897 std::swap(_M_before_begin._M_nxt, __x._M_before_begin._M_nxt);
1898 std::swap(_M_element_count, __x._M_element_count);
1899 std::swap(_M_single_bucket, __x._M_single_bucket);
1904 __x._M_update_bbegin();
1907 template<
typename _Key,
typename _Value,
typename _Alloc,
1908 typename _ExtractKey,
typename _Equal,
1909 typename _Hash,
typename _RangeHash,
typename _Unused,
1910 typename _RehashPolicy,
typename _Traits>
1912 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1913 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1914 find(
const key_type& __k)
1916 {
return iterator(_M_locate(__k)); }
1918 template<
typename _Key,
typename _Value,
typename _Alloc,
1919 typename _ExtractKey,
typename _Equal,
1920 typename _Hash,
typename _RangeHash,
typename _Unused,
1921 typename _RehashPolicy,
typename _Traits>
1923 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1924 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1925 find(
const key_type& __k)
const
1927 {
return const_iterator(_M_locate(__k)); }
1929#if __cplusplus > 201703L
1930 template<
typename _Key,
typename _Value,
typename _Alloc,
1931 typename _ExtractKey,
typename _Equal,
1932 typename _Hash,
typename _RangeHash,
typename _Unused,
1933 typename _RehashPolicy,
typename _Traits>
1934 template<
typename _Kt,
typename,
typename>
1936 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1937 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1938 _M_find_tr(
const _Kt& __k)
1941 if (
size() <= __small_size_threshold())
1943 for (
auto __n = _M_begin(); __n; __n = __n->_M_next())
1944 if (this->_M_key_equals_tr(__k, *__n))
1945 return iterator(__n);
1949 __hash_code __code = this->_M_hash_code_tr(__k);
1950 std::size_t __bkt = _M_bucket_index(__code);
1951 return iterator(_M_find_node_tr(__bkt, __k, __code));
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 _Kt,
typename,
typename>
1960 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1961 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1962 _M_find_tr(
const _Kt& __k)
const
1965 if (
size() <= __small_size_threshold())
1967 for (
auto __n = _M_begin(); __n; __n = __n->_M_next())
1968 if (this->_M_key_equals_tr(__k, *__n))
1969 return const_iterator(__n);
1973 __hash_code __code = this->_M_hash_code_tr(__k);
1974 std::size_t __bkt = _M_bucket_index(__code);
1975 return const_iterator(_M_find_node_tr(__bkt, __k, __code));
1979 template<
typename _Key,
typename _Value,
typename _Alloc,
1980 typename _ExtractKey,
typename _Equal,
1981 typename _Hash,
typename _RangeHash,
typename _Unused,
1982 typename _RehashPolicy,
typename _Traits>
1984 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1985 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1986 count(
const key_type& __k)
const
1989 auto __it = find(__k);
1993 if (__unique_keys::value)
1996 size_type __result = 1;
1997 for (
auto __ref = __it++;
1998 __it._M_cur && this->_M_node_equals(*__ref._M_cur, *__it._M_cur);
2005#if __cplusplus > 201703L
2006 template<
typename _Key,
typename _Value,
typename _Alloc,
2007 typename _ExtractKey,
typename _Equal,
2008 typename _Hash,
typename _RangeHash,
typename _Unused,
2009 typename _RehashPolicy,
typename _Traits>
2010 template<
typename _Kt,
typename,
typename>
2012 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2013 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2014 _M_count_tr(
const _Kt& __k)
const
2017 if (
size() <= __small_size_threshold())
2019 size_type __result = 0;
2020 for (
auto __n = _M_begin(); __n; __n = __n->_M_next())
2022 if (this->_M_key_equals_tr(__k, *__n))
2035 __hash_code __code = this->_M_hash_code_tr(__k);
2036 std::size_t __bkt = _M_bucket_index(__code);
2037 auto __n = _M_find_node_tr(__bkt, __k, __code);
2042 size_type __result = 1;
2044 __it._M_cur && this->_M_equals_tr(__k, __code, *__it._M_cur);
2052 template<
typename _Key,
typename _Value,
typename _Alloc,
2053 typename _ExtractKey,
typename _Equal,
2054 typename _Hash,
typename _RangeHash,
typename _Unused,
2055 typename _RehashPolicy,
typename _Traits>
2057 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2058 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2059 equal_range(
const key_type& __k)
2060 -> pair<iterator, iterator>
2062 auto __ite = find(__k);
2064 return { __ite, __ite };
2066 auto __beg = __ite++;
2067 if (__unique_keys::value)
2068 return { __beg, __ite };
2070 while (__ite._M_cur && this->_M_node_equals(*__beg._M_cur, *__ite._M_cur))
2073 return { __beg, __ite };
2076 template<
typename _Key,
typename _Value,
typename _Alloc,
2077 typename _ExtractKey,
typename _Equal,
2078 typename _Hash,
typename _RangeHash,
typename _Unused,
2079 typename _RehashPolicy,
typename _Traits>
2081 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2082 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2083 equal_range(
const key_type& __k)
const
2084 -> pair<const_iterator, const_iterator>
2086 auto __ite = find(__k);
2088 return { __ite, __ite };
2090 auto __beg = __ite++;
2091 if (__unique_keys::value)
2092 return { __beg, __ite };
2094 while (__ite._M_cur && this->_M_node_equals(*__beg._M_cur, *__ite._M_cur))
2097 return { __beg, __ite };
2100#if __cplusplus > 201703L
2101 template<
typename _Key,
typename _Value,
typename _Alloc,
2102 typename _ExtractKey,
typename _Equal,
2103 typename _Hash,
typename _RangeHash,
typename _Unused,
2104 typename _RehashPolicy,
typename _Traits>
2105 template<
typename _Kt,
typename,
typename>
2107 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2108 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2109 _M_equal_range_tr(
const _Kt& __k)
2110 -> pair<iterator, iterator>
2112 if (
size() <= __small_size_threshold())
2114 __node_ptr __n, __beg =
nullptr;
2115 for (__n = _M_begin(); __n; __n = __n->_M_next())
2117 if (this->_M_key_equals_tr(__k, *__n))
2128 return { iterator(__beg), iterator(__n) };
2131 __hash_code __code = this->_M_hash_code_tr(__k);
2132 std::size_t __bkt = _M_bucket_index(__code);
2133 auto __n = _M_find_node_tr(__bkt, __k, __code);
2134 iterator __ite(__n);
2136 return { __ite, __ite };
2138 auto __beg = __ite++;
2139 while (__ite._M_cur && this->_M_equals_tr(__k, __code, *__ite._M_cur))
2142 return { __beg, __ite };
2145 template<
typename _Key,
typename _Value,
typename _Alloc,
2146 typename _ExtractKey,
typename _Equal,
2147 typename _Hash,
typename _RangeHash,
typename _Unused,
2148 typename _RehashPolicy,
typename _Traits>
2149 template<
typename _Kt,
typename,
typename>
2151 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2152 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2153 _M_equal_range_tr(
const _Kt& __k)
const
2154 -> pair<const_iterator, const_iterator>
2156 if (
size() <= __small_size_threshold())
2158 __node_ptr __n, __beg =
nullptr;
2159 for (__n = _M_begin(); __n; __n = __n->_M_next())
2161 if (this->_M_key_equals_tr(__k, *__n))
2172 return { const_iterator(__beg), const_iterator(__n) };
2175 __hash_code __code = this->_M_hash_code_tr(__k);
2176 std::size_t __bkt = _M_bucket_index(__code);
2177 auto __n = _M_find_node_tr(__bkt, __k, __code);
2178 const_iterator __ite(__n);
2180 return { __ite, __ite };
2182 auto __beg = __ite++;
2183 while (__ite._M_cur && this->_M_equals_tr(__k, __code, *__ite._M_cur))
2186 return { __beg, __ite };
2192 template<
typename _Key,
typename _Value,
typename _Alloc,
2193 typename _ExtractKey,
typename _Equal,
2194 typename _Hash,
typename _RangeHash,
typename _Unused,
2195 typename _RehashPolicy,
typename _Traits>
2197 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2198 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2199 _M_find_before_node(size_type __bkt,
const key_type& __k,
2200 __hash_code __code)
const
2203 __node_base_ptr __prev_p = _M_buckets[__bkt];
2207 for (__node_ptr __p =
static_cast<__node_ptr
>(__prev_p->_M_nxt);;
2208 __p = __p->_M_next())
2210 if (this->_M_equals(__k, __code, *__p))
2213 if (__builtin_expect (!__p->_M_nxt || _M_bucket_index(*__p->_M_next()) != __bkt, 0))
2221 template<
typename _Key,
typename _Value,
typename _Alloc,
2222 typename _ExtractKey,
typename _Equal,
2223 typename _Hash,
typename _RangeHash,
typename _Unused,
2224 typename _RehashPolicy,
typename _Traits>
2225 template<
typename _Kt>
2227 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2228 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2229 _M_find_before_node_tr(size_type __bkt,
const _Kt& __k,
2230 __hash_code __code)
const
2233 __node_base_ptr __prev_p = _M_buckets[__bkt];
2237 for (__node_ptr __p =
static_cast<__node_ptr
>(__prev_p->_M_nxt);;
2238 __p = __p->_M_next())
2240 if (this->_M_equals_tr(__k, __code, *__p))
2243 if (__builtin_expect (!__p->_M_nxt || _M_bucket_index(*__p->_M_next()) != __bkt, 0))
2251 template<
typename _Key,
typename _Value,
typename _Alloc,
2252 typename _ExtractKey,
typename _Equal,
2253 typename _Hash,
typename _RangeHash,
typename _Unused,
2254 typename _RehashPolicy,
typename _Traits>
2256 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2257 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2258 _M_locate(
const key_type& __k)
const
2261 __location_type __loc;
2262 const auto __size =
size();
2264 if (__size <= __small_size_threshold())
2266 __loc._M_before = pointer_traits<__node_base_ptr>::
2267 pointer_to(
const_cast<__node_base&
>(_M_before_begin));
2268 while (__loc._M_before->_M_nxt)
2270 if (this->_M_key_equals(__k, *__loc._M_node()))
2272 __loc._M_before = __loc._M_before->_M_nxt;
2274 __loc._M_before =
nullptr;
2277 __loc._M_hash_code = this->_M_hash_code(__k);
2278 __loc._M_bucket_index = _M_bucket_index(__loc._M_hash_code);
2280 if (__size > __small_size_threshold())
2281 __loc._M_before = _M_find_before_node(__loc._M_bucket_index, __k,
2282 __loc._M_hash_code);
2287 template<
typename _Key,
typename _Value,
typename _Alloc,
2288 typename _ExtractKey,
typename _Equal,
2289 typename _Hash,
typename _RangeHash,
typename _Unused,
2290 typename _RehashPolicy,
typename _Traits>
2292 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2293 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2294 _M_get_previous_node(size_type __bkt, __node_ptr __n)
2297 __node_base_ptr __prev_n = _M_buckets[__bkt];
2298 while (__prev_n->_M_nxt != __n)
2299 __prev_n = __prev_n->_M_nxt;
2303#pragma GCC diagnostic push
2304#pragma GCC diagnostic ignored "-Wc++17-extensions"
2305 template<
typename _Key,
typename _Value,
typename _Alloc,
2306 typename _ExtractKey,
typename _Equal,
2307 typename _Hash,
typename _RangeHash,
typename _Unused,
2308 typename _RehashPolicy,
typename _Traits>
2309 template<
typename... _Args>
2311 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2312 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2313 _M_emplace_uniq(_Args&&... __args)
2314 -> pair<iterator, bool>
2316 const key_type* __kp =
nullptr;
2318 if constexpr (
sizeof...(_Args) == 1)
2320 if constexpr (__is_key_type<_Args...>)
2322 const auto& __key = _ExtractKey{}(__args...);
2326 else if constexpr (
sizeof...(_Args) == 2)
2328 if constexpr (__is_key_type<pair<
const _Args&...>>)
2330 pair<
const _Args&...> __refs(__args...);
2331 const auto& __key = _ExtractKey{}(__refs);
2336 _Scoped_node __node { __node_ptr(),
this };
2337 __hash_code __code = 0;
2338 size_type __bkt = 0;
2340 if (__kp ==
nullptr)
2344 = this->_M_allocate_node(std::forward<_Args>(__args)...);
2345 const key_type& __key = _ExtractKey{}(__node._M_node->_M_v());
2349 if (
auto __loc = _M_locate(*__kp))
2351 return { iterator(__loc),
false };
2354 __code = __loc._M_hash_code;
2355 __bkt = __loc._M_bucket_index;
2358 if (!__node._M_node)
2360 = this->_M_allocate_node(std::forward<_Args>(__args)...);
2363 auto __pos = _M_insert_unique_node(__bkt, __code, __node._M_node);
2364 __node._M_node =
nullptr;
2365 return { __pos,
true };
2367#pragma GCC diagnostic pop
2369 template<
typename _Key,
typename _Value,
typename _Alloc,
2370 typename _ExtractKey,
typename _Equal,
2371 typename _Hash,
typename _RangeHash,
typename _Unused,
2372 typename _RehashPolicy,
typename _Traits>
2373 template<
typename... _Args>
2375 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2376 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2377 _M_emplace_multi(const_iterator __hint, _Args&&... __args)
2381 _Scoped_node __node {
this, std::forward<_Args>(__args)... };
2382 const key_type& __k = _ExtractKey{}(__node._M_node->_M_v());
2384 auto __res = this->_M_compute_hash_code(__hint._M_cur, __k);
2386 = _M_insert_multi_node(__res.first, __res.second, __node._M_node);
2387 __node._M_node =
nullptr;
2391 template<
typename _Key,
typename _Value,
typename _Alloc,
2392 typename _ExtractKey,
typename _Equal,
2393 typename _Hash,
typename _RangeHash,
typename _Unused,
2394 typename _RehashPolicy,
typename _Traits>
2395 template<
typename _InputIterator>
2397 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2398 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2399 _M_insert_range_multi(_InputIterator __first, _InputIterator __last)
2403 size_type __n_elt = __detail::__distance_fw(__first, __last);
2407 __rehash_guard_t __rehash_guard(_M_rehash_policy);
2408 __pair_type __do_rehash
2409 = _M_rehash_policy._M_need_rehash(_M_bucket_count,
2413 if (__do_rehash.first)
2414 _M_rehash(__do_rehash.second, false_type{});
2416 __rehash_guard._M_guarded_obj =
nullptr;
2417 for (; __first != __last; ++__first)
2418 _M_emplace_multi(
cend(), *__first);
2421 template<
typename _Key,
typename _Value,
typename _Alloc,
2422 typename _ExtractKey,
typename _Equal,
2423 typename _Hash,
typename _RangeHash,
typename _Unused,
2424 typename _RehashPolicy,
typename _Traits>
2426 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2427 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2428 _M_compute_hash_code(__node_ptr __hint,
const key_type& __k)
const
2429 -> pair<__node_ptr, __hash_code>
2431 if (
size() <= __small_size_threshold())
2435 for (
auto __it = __hint; __it; __it = __it->_M_next())
2436 if (this->_M_key_equals(__k, *__it))
2437 return { __it, this->_M_hash_code(*__it) };
2440 for (
auto __it = _M_begin(); __it != __hint; __it = __it->_M_next())
2441 if (this->_M_key_equals(__k, *__it))
2442 return { __it, this->_M_hash_code(*__it) };
2447 return { __hint, this->_M_hash_code(__k) };
2450 template<
typename _Key,
typename _Value,
typename _Alloc,
2451 typename _ExtractKey,
typename _Equal,
2452 typename _Hash,
typename _RangeHash,
typename _Unused,
2453 typename _RehashPolicy,
typename _Traits>
2455 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2456 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2457 _M_insert_unique_node(size_type __bkt, __hash_code __code,
2458 __node_ptr __node, size_type __n_elt)
2461 __rehash_guard_t __rehash_guard(_M_rehash_policy);
2463 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count,
2466 if (__do_rehash.
first)
2468 _M_rehash(__do_rehash.
second, true_type{});
2469 __bkt = _M_bucket_index(__code);
2472 __rehash_guard._M_guarded_obj =
nullptr;
2473 _M_store_code(*__node, __code);
2476 _M_insert_bucket_begin(__bkt, __node);
2478 return iterator(__node);
2481 template<
typename _Key,
typename _Value,
typename _Alloc,
2482 typename _ExtractKey,
typename _Equal,
2483 typename _Hash,
typename _RangeHash,
typename _Unused,
2484 typename _RehashPolicy,
typename _Traits>
2486 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2487 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2488 _M_insert_multi_node(__node_ptr __hint,
2489 __hash_code __code, __node_ptr __node)
2492 __rehash_guard_t __rehash_guard(_M_rehash_policy);
2494 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
2496 if (__do_rehash.
first)
2497 _M_rehash(__do_rehash.
second, false_type{});
2499 __rehash_guard._M_guarded_obj =
nullptr;
2500 _M_store_code(*__node, __code);
2501 const key_type& __k = _ExtractKey{}(__node->_M_v());
2502 size_type __bkt = _M_bucket_index(__code);
2506 __node_base_ptr __prev
2507 = __builtin_expect(__hint !=
nullptr,
false)
2508 && this->_M_equals(__k, __code, *__hint)
2510 : _M_find_before_node(__bkt, __k, __code);
2515 __node->_M_nxt = __prev->_M_nxt;
2516 __prev->_M_nxt = __node;
2517 if (__builtin_expect(__prev == __hint,
false))
2521 && !this->_M_equals(__k, __code, *__node->_M_next()))
2523 size_type __next_bkt = _M_bucket_index(*__node->_M_next());
2524 if (__next_bkt != __bkt)
2525 _M_buckets[__next_bkt] = __node;
2532 _M_insert_bucket_begin(__bkt, __node);
2534 return iterator(__node);
2537 template<
typename _Key,
typename _Value,
typename _Alloc,
2538 typename _ExtractKey,
typename _Equal,
2539 typename _Hash,
typename _RangeHash,
typename _Unused,
2540 typename _RehashPolicy,
typename _Traits>
2542 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2543 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2544 erase(const_iterator __it)
2547 __node_ptr __n = __it._M_cur;
2548 std::size_t __bkt = _M_bucket_index(*__n);
2553 __node_base_ptr __prev_n = _M_get_previous_node(__bkt, __n);
2554 return _M_erase(__bkt, __prev_n, __n);
2557 template<
typename _Key,
typename _Value,
typename _Alloc,
2558 typename _ExtractKey,
typename _Equal,
2559 typename _Hash,
typename _RangeHash,
typename _Unused,
2560 typename _RehashPolicy,
typename _Traits>
2562 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2563 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2564 _M_erase(size_type __bkt, __node_base_ptr __prev_n, __node_ptr __n)
2567 if (__prev_n == _M_buckets[__bkt])
2568 _M_remove_bucket_begin(__bkt, __n->_M_next(),
2569 __n->_M_nxt ? _M_bucket_index(*__n->_M_next()) : 0);
2570 else if (__n->_M_nxt)
2572 size_type __next_bkt = _M_bucket_index(*__n->_M_next());
2573 if (__next_bkt != __bkt)
2574 _M_buckets[__next_bkt] = __prev_n;
2577 __prev_n->_M_nxt = __n->_M_nxt;
2578 iterator __result(__n->_M_next());
2579 this->_M_deallocate_node(__n);
2585#pragma GCC diagnostic push
2586#pragma GCC diagnostic ignored "-Wc++17-extensions"
2587 template<
typename _Key,
typename _Value,
typename _Alloc,
2588 typename _ExtractKey,
typename _Equal,
2589 typename _Hash,
typename _RangeHash,
typename _Unused,
2590 typename _RehashPolicy,
typename _Traits>
2592 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2593 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2594 erase(
const key_type& __k)
2597 auto __loc = _M_locate(__k);
2601 __node_base_ptr __prev_n = __loc._M_before;
2602 __node_ptr __n = __loc._M_node();
2603 auto __bkt = __loc._M_bucket_index;
2604 if (__bkt == size_type(-1))
2605 __bkt = _M_bucket_index(*__n);
2607 if constexpr (__unique_keys::value)
2609 _M_erase(__bkt, __prev_n, __n);
2620 __node_ptr __n_last = __n->_M_next();
2621 while (__n_last && this->_M_node_equals(*__n, *__n_last))
2622 __n_last = __n_last->_M_next();
2624 std::size_t __n_last_bkt
2625 = __n_last ? _M_bucket_index(*__n_last) : __bkt;
2628 size_type __result = 0;
2631 __node_ptr __p = __n->_M_next();
2632 this->_M_deallocate_node(__n);
2636 while (__n != __n_last);
2638 _M_element_count -= __result;
2639 if (__prev_n == _M_buckets[__bkt])
2640 _M_remove_bucket_begin(__bkt, __n_last, __n_last_bkt);
2641 else if (__n_last_bkt != __bkt)
2642 _M_buckets[__n_last_bkt] = __prev_n;
2643 __prev_n->_M_nxt = __n_last;
2647#pragma GCC diagnostic pop
2649 template<
typename _Key,
typename _Value,
typename _Alloc,
2650 typename _ExtractKey,
typename _Equal,
2651 typename _Hash,
typename _RangeHash,
typename _Unused,
2652 typename _RehashPolicy,
typename _Traits>
2654 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2655 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2656 erase(const_iterator __first, const_iterator __last)
2659 __node_ptr __n = __first._M_cur;
2660 __node_ptr __last_n = __last._M_cur;
2661 if (__n == __last_n)
2662 return iterator(__n);
2664 std::size_t __bkt = _M_bucket_index(*__n);
2666 __node_base_ptr __prev_n = _M_get_previous_node(__bkt, __n);
2667 bool __is_bucket_begin = __n == _M_bucket_begin(__bkt);
2668 std::size_t __n_bkt = __bkt;
2673 __node_ptr __tmp = __n;
2674 __n = __n->_M_next();
2675 this->_M_deallocate_node(__tmp);
2679 __n_bkt = _M_bucket_index(*__n);
2681 while (__n != __last_n && __n_bkt == __bkt);
2682 if (__is_bucket_begin)
2683 _M_remove_bucket_begin(__bkt, __n, __n_bkt);
2684 if (__n == __last_n)
2686 __is_bucket_begin =
true;
2690 if (__n && (__n_bkt != __bkt || __is_bucket_begin))
2691 _M_buckets[__n_bkt] = __prev_n;
2692 __prev_n->_M_nxt = __n;
2693 return iterator(__n);
2696 template<
typename _Key,
typename _Value,
typename _Alloc,
2697 typename _ExtractKey,
typename _Equal,
2698 typename _Hash,
typename _RangeHash,
typename _Unused,
2699 typename _RehashPolicy,
typename _Traits>
2701 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2702 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2705 this->_M_deallocate_nodes(_M_begin());
2706 std::fill_n(_M_buckets, _M_bucket_count,
nullptr);
2707 _M_element_count = 0;
2708 _M_before_begin._M_nxt =
nullptr;
2711 template<
typename _Key,
typename _Value,
typename _Alloc,
2712 typename _ExtractKey,
typename _Equal,
2713 typename _Hash,
typename _RangeHash,
typename _Unused,
2714 typename _RehashPolicy,
typename _Traits>
2716 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2717 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2718 rehash(size_type __bkt_count)
2720 __rehash_guard_t __rehash_guard(_M_rehash_policy);
2722 =
std::max(_M_rehash_policy._M_bkt_for_elements(_M_element_count + 1),
2724 __bkt_count = _M_rehash_policy._M_next_bkt(__bkt_count);
2726 if (__bkt_count != _M_bucket_count)
2728 _M_rehash(__bkt_count, __unique_keys{});
2729 __rehash_guard._M_guarded_obj =
nullptr;
2734 template<
typename _Key,
typename _Value,
typename _Alloc,
2735 typename _ExtractKey,
typename _Equal,
2736 typename _Hash,
typename _RangeHash,
typename _Unused,
2737 typename _RehashPolicy,
typename _Traits>
2739 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2740 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2741 _M_rehash(size_type __bkt_count, true_type )
2743 __buckets_ptr __new_buckets = _M_allocate_buckets(__bkt_count);
2744 __node_ptr __p = _M_begin();
2745 _M_before_begin._M_nxt =
nullptr;
2746 std::size_t __bbegin_bkt = 0;
2749 __node_ptr __next = __p->_M_next();
2751 = __hash_code_base::_M_bucket_index(*__p, __bkt_count);
2752 if (!__new_buckets[__bkt])
2754 __p->_M_nxt = _M_before_begin._M_nxt;
2755 _M_before_begin._M_nxt = __p;
2756 __new_buckets[__bkt] = &_M_before_begin;
2758 __new_buckets[__bbegin_bkt] = __p;
2759 __bbegin_bkt = __bkt;
2763 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2764 __new_buckets[__bkt]->_M_nxt = __p;
2770 _M_deallocate_buckets();
2771 _M_bucket_count = __bkt_count;
2772 _M_buckets = __new_buckets;
2777 template<
typename _Key,
typename _Value,
typename _Alloc,
2778 typename _ExtractKey,
typename _Equal,
2779 typename _Hash,
typename _RangeHash,
typename _Unused,
2780 typename _RehashPolicy,
typename _Traits>
2782 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2783 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2784 _M_rehash(size_type __bkt_count, false_type )
2786 __buckets_ptr __new_buckets = _M_allocate_buckets(__bkt_count);
2787 __node_ptr __p = _M_begin();
2788 _M_before_begin._M_nxt =
nullptr;
2789 std::size_t __bbegin_bkt = 0;
2790 std::size_t __prev_bkt = 0;
2791 __node_ptr __prev_p =
nullptr;
2792 bool __check_bucket =
false;
2796 __node_ptr __next = __p->_M_next();
2798 = __hash_code_base::_M_bucket_index(*__p, __bkt_count);
2800 if (__prev_p && __prev_bkt == __bkt)
2805 __p->_M_nxt = __prev_p->_M_nxt;
2806 __prev_p->_M_nxt = __p;
2813 __check_bucket =
true;
2821 if (__prev_p->_M_nxt)
2823 std::size_t __next_bkt
2824 = __hash_code_base::_M_bucket_index(
2825 *__prev_p->_M_next(), __bkt_count);
2826 if (__next_bkt != __prev_bkt)
2827 __new_buckets[__next_bkt] = __prev_p;
2829 __check_bucket =
false;
2832 if (!__new_buckets[__bkt])
2834 __p->_M_nxt = _M_before_begin._M_nxt;
2835 _M_before_begin._M_nxt = __p;
2836 __new_buckets[__bkt] = &_M_before_begin;
2838 __new_buckets[__bbegin_bkt] = __p;
2839 __bbegin_bkt = __bkt;
2843 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2844 __new_buckets[__bkt]->_M_nxt = __p;
2852 if (__check_bucket && __prev_p->_M_nxt)
2854 std::size_t __next_bkt
2855 = __hash_code_base::_M_bucket_index(*__prev_p->_M_next(),
2857 if (__next_bkt != __prev_bkt)
2858 __new_buckets[__next_bkt] = __prev_p;
2861 _M_deallocate_buckets();
2862 _M_bucket_count = __bkt_count;
2863 _M_buckets = __new_buckets;
2866#pragma GCC diagnostic push
2867#pragma GCC diagnostic ignored "-Wc++17-extensions"
2872 template<
typename _Key,
typename _Value,
typename _Alloc,
2873 typename _ExtractKey,
typename _Equal,
2874 typename _Hash,
typename _RangeHash,
typename _Unused,
2875 typename _RehashPolicy,
typename _Traits>
2877 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2878 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2879 _M_equal(
const _Hashtable& __other)
const
2881 if (
size() != __other.size())
2884 if constexpr (__unique_keys::value)
2885 for (
auto __x_n = _M_begin(); __x_n; __x_n = __x_n->_M_next())
2887 std::size_t __ybkt = __other._M_bucket_index_ext(*__x_n);
2888 auto __prev_n = __other._M_buckets[__ybkt];
2892 for (__node_ptr __n =
static_cast<__node_ptr
>(__prev_n->_M_nxt);;
2893 __n = __n->_M_next())
2895 if (__n->_M_v() == __x_n->_M_v())
2899 || __other._M_bucket_index(*__n->_M_next()) != __ybkt)
2904 for (
auto __x_n = _M_begin(); __x_n;)
2906 std::size_t __x_count = 1;
2907 auto __x_n_end = __x_n->_M_next();
2909 && key_eq()(_ExtractKey{}(__x_n->_M_v()),
2910 _ExtractKey{}(__x_n_end->_M_v()));
2911 __x_n_end = __x_n_end->_M_next())
2914 std::size_t __ybkt = __other._M_bucket_index_ext(*__x_n);
2915 auto __y_prev_n = __other._M_buckets[__ybkt];
2919 __node_ptr __y_n =
static_cast<__node_ptr
>(__y_prev_n->_M_nxt);
2922 if (key_eq()(_ExtractKey{}(__y_n->_M_v()),
2923 _ExtractKey{}(__x_n->_M_v())))
2926 auto __y_ref_n = __y_n;
2927 for (__y_n = __y_n->_M_next(); __y_n; __y_n = __y_n->_M_next())
2928 if (!__other._M_node_equals(*__y_ref_n, *__y_n))
2931 if (!__y_n || __other._M_bucket_index(*__y_n) != __ybkt)
2935 auto __y_n_end = __y_n;
2936 for (; __y_n_end; __y_n_end = __y_n_end->_M_next())
2937 if (--__x_count == 0)
2943 const_iterator __itx(__x_n), __itx_end(__x_n_end);
2944 const_iterator __ity(__y_n);
2945 if (!std::is_permutation(__itx, __itx_end, __ity))
2953#pragma GCC diagnostic pop
2955#if __cplusplus > 201402L
2956 template<
typename,
typename,
typename>
class _Hash_merge_helper { };
2959#if __cpp_deduction_guides >= 201606
2961 template<
typename _Hash>
2962 using _RequireNotAllocatorOrIntegral
2963 = __enable_if_t<!__or_<is_integral<_Hash>, __is_allocator<_Hash>>::value>;
2967_GLIBCXX_END_NAMESPACE_VERSION
2970#pragma GCC diagnostic pop
__bool_constant< true > true_type
The type used as a compile-time boolean with true value.
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.
_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.