31 #define _HASHTABLE_H 1
33 #pragma GCC system_header
37 #if __cplusplus > 201402L
43 namespace std _GLIBCXX_VISIBILITY(default)
45 _GLIBCXX_BEGIN_NAMESPACE_VERSION
48 template<
typename _Tp,
typename _Hash>
51 __is_fast_hash<_Hash>,
53 __is_nothrow_invocable<const _Hash&, const _Tp&>>>;
58 template<
typename _Equal,
typename _Hash,
typename _Allocator>
59 using _Hashtable_enable_default_ctor
60 = _Enable_default_constructor<__and_<is_default_constructible<_Equal>,
61 is_default_constructible<_Hash>,
62 is_default_constructible<_Allocator>>{},
63 __detail::_Hash_node_base>;
178 template<
typename _Key,
typename _Value,
typename _Alloc,
179 typename _ExtractKey,
typename _Equal,
180 typename _Hash,
typename _RangeHash,
typename _Unused,
181 typename _RehashPolicy,
typename _Traits>
183 :
public __detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal,
184 _Hash, _RangeHash, _Unused, _Traits>,
185 public __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
186 _Hash, _RangeHash, _Unused,
187 _RehashPolicy, _Traits>,
188 public __detail::_Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal,
189 _Hash, _RangeHash, _Unused,
190 _RehashPolicy, _Traits>,
191 public __detail::_Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
192 _Hash, _RangeHash, _Unused,
193 _RehashPolicy, _Traits>,
194 public __detail::_Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal,
195 _Hash, _RangeHash, _Unused,
196 _RehashPolicy, _Traits>,
197 private __detail::_Hashtable_alloc<
198 __alloc_rebind<_Alloc,
199 __detail::_Hash_node<_Value,
200 _Traits::__hash_cached::value>>>,
201 private _Hashtable_enable_default_ctor<_Equal, _Hash, _Alloc>
203 static_assert(is_same<
typename remove_cv<_Value>::type, _Value>::value,
204 "unordered container must have a non-const, non-volatile value_type");
205 #if __cplusplus > 201703L || defined __STRICT_ANSI__
206 static_assert(is_same<typename _Alloc::value_type, _Value>{},
207 "unordered container must have the same value_type as its allocator");
210 using __traits_type = _Traits;
211 using __hash_cached =
typename __traits_type::__hash_cached;
212 using __constant_iterators =
typename __traits_type::__constant_iterators;
213 using __node_type = __detail::_Hash_node<_Value, __hash_cached::value>;
214 using __node_alloc_type = __alloc_rebind<_Alloc, __node_type>;
216 using __hashtable_alloc = __detail::_Hashtable_alloc<__node_alloc_type>;
218 using __node_value_type =
219 __detail::_Hash_node_value<_Value, __hash_cached::value>;
220 using __node_ptr =
typename __hashtable_alloc::__node_ptr;
221 using __value_alloc_traits =
222 typename __hashtable_alloc::__value_alloc_traits;
223 using __node_alloc_traits =
224 typename __hashtable_alloc::__node_alloc_traits;
225 using __node_base =
typename __hashtable_alloc::__node_base;
226 using __node_base_ptr =
typename __hashtable_alloc::__node_base_ptr;
227 using __buckets_ptr =
typename __hashtable_alloc::__buckets_ptr;
229 using __insert_base = __detail::_Insert<_Key, _Value, _Alloc, _ExtractKey,
232 _RehashPolicy, _Traits>;
233 using __enable_default_ctor
234 = _Hashtable_enable_default_ctor<_Equal, _Hash, _Alloc>;
237 typedef _Key key_type;
238 typedef _Value value_type;
239 typedef _Alloc allocator_type;
240 typedef _Equal key_equal;
244 typedef typename __value_alloc_traits::pointer pointer;
245 typedef typename __value_alloc_traits::const_pointer const_pointer;
246 typedef value_type& reference;
247 typedef const value_type& const_reference;
249 using iterator =
typename __insert_base::iterator;
251 using const_iterator =
typename __insert_base::const_iterator;
253 using local_iterator = __detail::_Local_iterator<key_type, _Value,
254 _ExtractKey, _Hash, _RangeHash, _Unused,
255 __constant_iterators::value,
256 __hash_cached::value>;
258 using const_local_iterator = __detail::_Local_const_iterator<
260 _ExtractKey, _Hash, _RangeHash, _Unused,
261 __constant_iterators::value, __hash_cached::value>;
264 using __rehash_type = _RehashPolicy;
265 using __rehash_state =
typename __rehash_type::_State;
267 using __unique_keys =
typename __traits_type::__unique_keys;
269 using __hashtable_base = __detail::
270 _Hashtable_base<_Key, _Value, _ExtractKey,
271 _Equal, _Hash, _RangeHash, _Unused, _Traits>;
273 using __hash_code_base =
typename __hashtable_base::__hash_code_base;
274 using __hash_code =
typename __hashtable_base::__hash_code;
275 using __ireturn_type =
typename __insert_base::__ireturn_type;
277 using __map_base = __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey,
278 _Equal, _Hash, _RangeHash, _Unused,
279 _RehashPolicy, _Traits>;
281 using __rehash_base = __detail::_Rehash_base<_Key, _Value, _Alloc,
283 _Hash, _RangeHash, _Unused,
284 _RehashPolicy, _Traits>;
286 using __eq_base = __detail::_Equality<_Key, _Value, _Alloc, _ExtractKey,
287 _Equal, _Hash, _RangeHash, _Unused,
288 _RehashPolicy, _Traits>;
290 using __reuse_or_alloc_node_gen_t =
291 __detail::_ReuseOrAllocNode<__node_alloc_type>;
292 using __alloc_node_gen_t =
293 __detail::_AllocNode<__node_alloc_type>;
294 using __node_builder_t =
295 __detail::_NodeBuilder<_ExtractKey>;
301 _Scoped_node(__node_ptr __n, __hashtable_alloc* __h)
302 : _M_h(__h), _M_node(__n) { }
305 template<
typename... _Args>
306 _Scoped_node(__hashtable_alloc* __h, _Args&&... __args)
308 _M_node(__h->_M_allocate_node(
std::
forward<_Args>(__args)...))
312 ~_Scoped_node() {
if (_M_node) _M_h->_M_deallocate_node(_M_node); };
314 _Scoped_node(
const _Scoped_node&) =
delete;
315 _Scoped_node& operator=(
const _Scoped_node&) =
delete;
317 __hashtable_alloc* _M_h;
321 template<
typename _Ht>
323 __conditional_t<std::is_lvalue_reference<_Ht>::value,
324 const value_type&, value_type&&>
325 __fwd_value_for(value_type& __val) noexcept
332 struct __hash_code_base_access : __hash_code_base
333 {
using __hash_code_base::_M_bucket_index; };
336 static_assert(is_nothrow_default_constructible<_RangeHash>::value,
337 "Functor used to map hash code to bucket index"
338 " must be nothrow default constructible");
339 static_assert(noexcept(
340 std::declval<const _RangeHash&>()((std::size_t)0, (std::size_t)0)),
341 "Functor used to map hash code to bucket index must be"
345 static_assert(is_nothrow_default_constructible<_ExtractKey>::value,
346 "_ExtractKey must be nothrow default constructible");
347 static_assert(noexcept(
348 std::declval<const _ExtractKey&>()(std::declval<_Value>())),
349 "_ExtractKey functor must be noexcept invocable");
351 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
352 typename _ExtractKeya,
typename _Equala,
353 typename _Hasha,
typename _RangeHasha,
typename _Unuseda,
354 typename _RehashPolicya,
typename _Traitsa,
356 friend struct __detail::_Map_base;
358 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
359 typename _ExtractKeya,
typename _Equala,
360 typename _Hasha,
typename _RangeHasha,
typename _Unuseda,
361 typename _RehashPolicya,
typename _Traitsa>
362 friend struct __detail::_Insert_base;
364 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
365 typename _ExtractKeya,
typename _Equala,
366 typename _Hasha,
typename _RangeHasha,
typename _Unuseda,
367 typename _RehashPolicya,
typename _Traitsa,
368 bool _Constant_iteratorsa>
369 friend struct __detail::_Insert;
371 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
372 typename _ExtractKeya,
typename _Equala,
373 typename _Hasha,
typename _RangeHasha,
typename _Unuseda,
374 typename _RehashPolicya,
typename _Traitsa,
376 friend struct __detail::_Equality;
379 using size_type =
typename __hashtable_base::size_type;
380 using difference_type =
typename __hashtable_base::difference_type;
382 #if __cplusplus > 201402L
383 using node_type = _Node_handle<_Key, _Value, __node_alloc_type>;
384 using insert_return_type = _Node_insert_return<iterator, node_type>;
388 __buckets_ptr _M_buckets = &_M_single_bucket;
389 size_type _M_bucket_count = 1;
390 __node_base _M_before_begin;
391 size_type _M_element_count = 0;
392 _RehashPolicy _M_rehash_policy;
400 __node_base_ptr _M_single_bucket =
nullptr;
406 _M_buckets[_M_bucket_index(*_M_begin())] = &_M_before_begin;
410 _M_update_bbegin(__node_ptr __n)
412 _M_before_begin._M_nxt = __n;
417 _M_uses_single_bucket(__buckets_ptr __bkts)
const
418 {
return __builtin_expect(__bkts == &_M_single_bucket,
false); }
421 _M_uses_single_bucket()
const
422 {
return _M_uses_single_bucket(_M_buckets); }
424 static constexpr
size_t
425 __small_size_threshold() noexcept
428 __detail::_Hashtable_hash_traits<_Hash>::__small_size_threshold();
432 _M_base_alloc() {
return *
this; }
435 _M_allocate_buckets(size_type __bkt_count)
437 if (__builtin_expect(__bkt_count == 1,
false))
439 _M_single_bucket =
nullptr;
440 return &_M_single_bucket;
443 return __hashtable_alloc::_M_allocate_buckets(__bkt_count);
447 _M_deallocate_buckets(__buckets_ptr __bkts, size_type __bkt_count)
449 if (_M_uses_single_bucket(__bkts))
452 __hashtable_alloc::_M_deallocate_buckets(__bkts, __bkt_count);
456 _M_deallocate_buckets()
457 { _M_deallocate_buckets(_M_buckets, _M_bucket_count); }
462 _M_bucket_begin(size_type __bkt)
const;
466 {
return static_cast<__node_ptr
>(_M_before_begin._M_nxt); }
470 template<
typename _Ht>
472 _M_assign_elements(_Ht&&);
474 template<
typename _Ht,
typename _NodeGenerator>
476 _M_assign(_Ht&&,
const _NodeGenerator&);
487 _Hashtable(const _Hash& __h, const _Equal& __eq,
488 const allocator_type& __a)
489 : __hashtable_base(__h, __eq),
490 __hashtable_alloc(__node_alloc_type(__a)),
491 __enable_default_ctor(_Enable_default_constructor_tag{})
494 template<
bool _No_realloc = true>
495 static constexpr
bool
498 #if __cplusplus <= 201402L
499 return __and_<__bool_constant<_No_realloc>,
500 is_nothrow_copy_constructible<_Hash>,
501 is_nothrow_copy_constructible<_Equal>>::value;
503 if constexpr (_No_realloc)
504 if constexpr (is_nothrow_copy_constructible<_Hash>())
505 return is_nothrow_copy_constructible<_Equal>();
510 _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a,
512 noexcept(_S_nothrow_move());
514 _Hashtable(_Hashtable&&, __node_alloc_type&&,
517 template<
typename _InputIterator>
518 _Hashtable(_InputIterator __first, _InputIterator __last,
519 size_type __bkt_count_hint,
520 const _Hash&,
const _Equal&,
const allocator_type&,
523 template<
typename _InputIterator>
524 _Hashtable(_InputIterator __first, _InputIterator __last,
525 size_type __bkt_count_hint,
526 const _Hash&,
const _Equal&,
const allocator_type&,
531 _Hashtable() =
default;
533 _Hashtable(
const _Hashtable&);
535 _Hashtable(
const _Hashtable&,
const allocator_type&);
538 _Hashtable(size_type __bkt_count_hint,
539 const _Hash& __hf = _Hash(),
540 const key_equal& __eql = key_equal(),
541 const allocator_type& __a = allocator_type());
544 _Hashtable(_Hashtable&& __ht)
545 noexcept(_S_nothrow_move())
546 : _Hashtable(
std::
move(__ht),
std::
move(__ht._M_node_allocator()),
550 _Hashtable(_Hashtable&& __ht,
const allocator_type& __a)
551 noexcept(_S_nothrow_move<__node_alloc_traits::_S_always_equal()>())
552 : _Hashtable(
std::
move(__ht), __node_alloc_type(__a),
553 typename __node_alloc_traits::is_always_equal{})
557 _Hashtable(
const allocator_type& __a)
558 : __hashtable_alloc(__node_alloc_type(__a)),
559 __enable_default_ctor(_Enable_default_constructor_tag{})
562 template<
typename _InputIterator>
563 _Hashtable(_InputIterator __f, _InputIterator __l,
564 size_type __bkt_count_hint = 0,
565 const _Hash& __hf = _Hash(),
566 const key_equal& __eql = key_equal(),
567 const allocator_type& __a = allocator_type())
568 : _Hashtable(__f, __l, __bkt_count_hint, __hf, __eql, __a,
572 _Hashtable(initializer_list<value_type> __l,
573 size_type __bkt_count_hint = 0,
574 const _Hash& __hf = _Hash(),
575 const key_equal& __eql = key_equal(),
576 const allocator_type& __a = allocator_type())
577 : _Hashtable(__l.
begin(), __l.
end(), __bkt_count_hint,
578 __hf, __eql, __a, __unique_keys{})
582 operator=(
const _Hashtable& __ht);
585 operator=(_Hashtable&& __ht)
586 noexcept(__node_alloc_traits::_S_nothrow_move()
587 && is_nothrow_move_assignable<_Hash>::value
588 && is_nothrow_move_assignable<_Equal>::value)
590 constexpr
bool __move_storage =
591 __node_alloc_traits::_S_propagate_on_move_assign()
592 || __node_alloc_traits::_S_always_equal();
593 _M_move_assign(
std::move(__ht), __bool_constant<__move_storage>());
598 operator=(initializer_list<value_type> __l)
600 __reuse_or_alloc_node_gen_t __roan(_M_begin(), *
this);
601 _M_before_begin._M_nxt =
nullptr;
605 auto __l_bkt_count = _M_rehash_policy._M_bkt_for_elements(__l.size());
608 if (_M_bucket_count < __l_bkt_count)
609 rehash(__l_bkt_count);
611 this->_M_insert_range(__l.begin(), __l.end(), __roan, __unique_keys{});
615 ~_Hashtable() noexcept;
619 noexcept(__and_<__is_nothrow_swappable<_Hash>,
620 __is_nothrow_swappable<_Equal>>::value);
625 {
return iterator(_M_begin()); }
628 begin() const noexcept
629 {
return const_iterator(_M_begin()); }
633 {
return iterator(
nullptr); }
637 {
return const_iterator(
nullptr); }
641 {
return const_iterator(_M_begin()); }
644 cend() const noexcept
645 {
return const_iterator(
nullptr); }
648 size() const noexcept
649 {
return _M_element_count; }
651 _GLIBCXX_NODISCARD
bool
652 empty() const noexcept
653 {
return size() == 0; }
656 get_allocator() const noexcept
657 {
return allocator_type(this->_M_node_allocator()); }
660 max_size() const noexcept
661 {
return __node_alloc_traits::max_size(this->_M_node_allocator()); }
666 {
return this->_M_eq(); }
672 bucket_count() const noexcept
673 {
return _M_bucket_count; }
676 max_bucket_count() const noexcept
677 {
return max_size(); }
680 bucket_size(size_type __bkt)
const
684 bucket(
const key_type& __k)
const
685 {
return _M_bucket_index(this->_M_hash_code(__k)); }
688 begin(size_type __bkt)
690 return local_iterator(*
this, _M_bucket_begin(__bkt),
691 __bkt, _M_bucket_count);
696 {
return local_iterator(*
this,
nullptr, __bkt, _M_bucket_count); }
699 begin(size_type __bkt)
const
701 return const_local_iterator(*
this, _M_bucket_begin(__bkt),
702 __bkt, _M_bucket_count);
706 end(size_type __bkt)
const
707 {
return const_local_iterator(*
this,
nullptr, __bkt, _M_bucket_count); }
711 cbegin(size_type __bkt)
const
713 return const_local_iterator(*
this, _M_bucket_begin(__bkt),
714 __bkt, _M_bucket_count);
718 cend(size_type __bkt)
const
719 {
return const_local_iterator(*
this,
nullptr, __bkt, _M_bucket_count); }
722 load_factor() const noexcept
724 return static_cast<float>(
size()) /
static_cast<float>(bucket_count());
733 __rehash_policy()
const
734 {
return _M_rehash_policy; }
737 __rehash_policy(
const _RehashPolicy& __pol)
738 { _M_rehash_policy = __pol; }
742 find(
const key_type& __k);
745 find(
const key_type& __k)
const;
748 count(
const key_type& __k)
const;
751 equal_range(
const key_type& __k);
754 equal_range(
const key_type& __k)
const;
756 #if __cplusplus >= 202002L
757 #define __cpp_lib_generic_unordered_lookup 201811L
759 template<
typename _Kt,
760 typename = __has_is_transparent_t<_Hash, _Kt>,
761 typename = __has_is_transparent_t<_Equal, _Kt>>
763 _M_find_tr(
const _Kt& __k);
765 template<
typename _Kt,
766 typename = __has_is_transparent_t<_Hash, _Kt>,
767 typename = __has_is_transparent_t<_Equal, _Kt>>
769 _M_find_tr(
const _Kt& __k)
const;
771 template<
typename _Kt,
772 typename = __has_is_transparent_t<_Hash, _Kt>,
773 typename = __has_is_transparent_t<_Equal, _Kt>>
775 _M_count_tr(
const _Kt& __k)
const;
777 template<
typename _Kt,
778 typename = __has_is_transparent_t<_Hash, _Kt>,
779 typename = __has_is_transparent_t<_Equal, _Kt>>
780 pair<iterator, iterator>
781 _M_equal_range_tr(
const _Kt& __k);
783 template<
typename _Kt,
784 typename = __has_is_transparent_t<_Hash, _Kt>,
785 typename = __has_is_transparent_t<_Equal, _Kt>>
786 pair<const_iterator, const_iterator>
787 _M_equal_range_tr(
const _Kt& __k)
const;
793 _M_bucket_index(
const __node_value_type& __n)
const noexcept
794 {
return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); }
797 _M_bucket_index(__hash_code __c)
const
798 {
return __hash_code_base::_M_bucket_index(__c, _M_bucket_count); }
801 _M_find_before_node(
const key_type&);
806 _M_find_before_node(size_type,
const key_type&, __hash_code)
const;
808 template<
typename _Kt>
810 _M_find_before_node_tr(size_type,
const _Kt&, __hash_code)
const;
813 _M_find_node(size_type __bkt,
const key_type& __key,
814 __hash_code __c)
const
816 __node_base_ptr __before_n = _M_find_before_node(__bkt, __key, __c);
818 return static_cast<__node_ptr
>(__before_n->_M_nxt);
822 template<
typename _Kt>
824 _M_find_node_tr(size_type __bkt,
const _Kt& __key,
825 __hash_code __c)
const
827 auto __before_n = _M_find_before_node_tr(__bkt, __key, __c);
829 return static_cast<__node_ptr
>(__before_n->_M_nxt);
835 _M_insert_bucket_begin(size_type, __node_ptr);
839 _M_remove_bucket_begin(size_type __bkt, __node_ptr __next_n,
840 size_type __next_bkt);
844 _M_get_previous_node(size_type __bkt, __node_ptr __n);
846 pair<const_iterator, __hash_code>
847 _M_compute_hash_code(const_iterator __hint,
const key_type& __k)
const;
853 _M_insert_unique_node(size_type __bkt, __hash_code,
854 __node_ptr __n, size_type __n_elt = 1);
859 _M_insert_multi_node(__node_ptr __hint,
860 __hash_code __code, __node_ptr __n);
862 template<
typename... _Args>
864 _M_emplace(
true_type __uks, _Args&&... __args);
866 template<
typename... _Args>
868 _M_emplace(
false_type __uks, _Args&&... __args)
869 {
return _M_emplace(
cend(), __uks, std::forward<_Args>(__args)...); }
872 template<
typename... _Args>
874 _M_emplace(const_iterator,
true_type __uks, _Args&&... __args)
875 {
return _M_emplace(__uks, std::forward<_Args>(__args)...).first; }
877 template<
typename... _Args>
879 _M_emplace(const_iterator,
false_type __uks, _Args&&... __args);
881 template<
typename _Kt,
typename _Arg,
typename _NodeGenerator>
883 _M_insert_unique(_Kt&&, _Arg&&,
const _NodeGenerator&);
885 template<
typename _Kt>
886 static __conditional_t<
887 __and_<__is_nothrow_invocable<_Hash&, const key_type&>,
888 __not_<__is_nothrow_invocable<_Hash&, _Kt>>>::value,
890 _S_forward_key(_Kt&& __k)
891 {
return std::forward<_Kt>(__k); }
893 static const key_type&
894 _S_forward_key(
const key_type& __k)
898 _S_forward_key(key_type&& __k)
901 template<
typename _Arg,
typename _NodeGenerator>
903 _M_insert(_Arg&& __arg,
const _NodeGenerator& __node_gen,
906 return _M_insert_unique(
907 _S_forward_key(_ExtractKey{}(std::forward<_Arg>(__arg))),
908 std::forward<_Arg>(__arg), __node_gen);
911 template<
typename _Arg,
typename _NodeGenerator>
913 _M_insert(_Arg&& __arg,
const _NodeGenerator& __node_gen,
916 return _M_insert(
cend(), std::forward<_Arg>(__arg), __node_gen,
921 template<
typename _Arg,
typename _NodeGenerator>
923 _M_insert(const_iterator, _Arg&& __arg,
924 const _NodeGenerator& __node_gen,
true_type __uks)
927 _M_insert(std::forward<_Arg>(__arg), __node_gen, __uks).first;
931 template<
typename _Arg,
typename _NodeGenerator>
933 _M_insert(const_iterator, _Arg&&,
937 _M_erase(
true_type __uks,
const key_type&);
943 _M_erase(size_type __bkt, __node_base_ptr __prev_n, __node_ptr __n);
947 template<
typename... _Args>
949 emplace(_Args&&... __args)
950 {
return _M_emplace(__unique_keys{}, std::forward<_Args>(__args)...); }
952 template<
typename... _Args>
954 emplace_hint(const_iterator __hint, _Args&&... __args)
956 return _M_emplace(__hint, __unique_keys{},
957 std::forward<_Args>(__args)...);
964 erase(const_iterator);
969 {
return erase(const_iterator(__it)); }
972 erase(
const key_type& __k)
973 {
return _M_erase(__unique_keys{}, __k); }
976 erase(const_iterator, const_iterator);
983 void rehash(size_type __bkt_count);
988 #if __cplusplus > 201402L
991 _M_reinsert_node(node_type&& __nh)
993 insert_return_type __ret;
995 __ret.position =
end();
998 __glibcxx_assert(get_allocator() == __nh.get_allocator());
1000 const key_type& __k = __nh._M_key();
1001 __hash_code __code = this->_M_hash_code(__k);
1002 size_type __bkt = _M_bucket_index(__code);
1003 if (__node_ptr __n = _M_find_node(__bkt, __k, __code))
1006 __ret.position = iterator(__n);
1007 __ret.inserted =
false;
1012 = _M_insert_unique_node(__bkt, __code, __nh._M_ptr);
1013 __nh._M_ptr =
nullptr;
1014 __ret.inserted =
true;
1022 _M_reinsert_node_multi(const_iterator __hint, node_type&& __nh)
1027 __glibcxx_assert(get_allocator() == __nh.get_allocator());
1029 const key_type& __k = __nh._M_key();
1030 auto __code = this->_M_hash_code(__k);
1032 = _M_insert_multi_node(__hint._M_cur, __code, __nh._M_ptr);
1033 __nh._M_ptr =
nullptr;
1039 _M_extract_node(
size_t __bkt, __node_base_ptr __prev_n)
1041 __node_ptr __n =
static_cast<__node_ptr
>(__prev_n->_M_nxt);
1042 if (__prev_n == _M_buckets[__bkt])
1043 _M_remove_bucket_begin(__bkt, __n->_M_next(),
1044 __n->_M_nxt ? _M_bucket_index(*__n->_M_next()) : 0);
1045 else if (__n->_M_nxt)
1047 size_type __next_bkt = _M_bucket_index(*__n->_M_next());
1048 if (__next_bkt != __bkt)
1049 _M_buckets[__next_bkt] = __prev_n;
1052 __prev_n->_M_nxt = __n->_M_nxt;
1053 __n->_M_nxt =
nullptr;
1055 return { __n, this->_M_node_allocator() };
1061 extract(const_iterator __pos)
1063 size_t __bkt = _M_bucket_index(*__pos._M_cur);
1064 return _M_extract_node(__bkt,
1065 _M_get_previous_node(__bkt, __pos._M_cur));
1070 extract(
const _Key& __k)
1073 __hash_code __code = this->_M_hash_code(__k);
1074 std::size_t __bkt = _M_bucket_index(__code);
1075 if (__node_base_ptr __prev_node = _M_find_before_node(__bkt, __k, __code))
1076 __nh = _M_extract_node(__bkt, __prev_node);
1081 template<
typename _Compatible_Hashtable>
1083 _M_merge_unique(_Compatible_Hashtable& __src)
1085 static_assert(is_same_v<
typename _Compatible_Hashtable::node_type,
1086 node_type>,
"Node types are compatible");
1087 __glibcxx_assert(get_allocator() == __src.get_allocator());
1089 auto __n_elt = __src.size();
1090 for (
auto __i = __src.cbegin(), __end = __src.cend(); __i != __end;)
1093 const key_type& __k = _ExtractKey{}(*__pos);
1095 = this->_M_hash_code(__src.hash_function(), *__pos._M_cur);
1096 size_type __bkt = _M_bucket_index(__code);
1097 if (_M_find_node(__bkt, __k, __code) ==
nullptr)
1099 auto __nh = __src.extract(__pos);
1100 _M_insert_unique_node(__bkt, __code, __nh._M_ptr, __n_elt);
1101 __nh._M_ptr =
nullptr;
1104 else if (__n_elt != 1)
1110 template<
typename _Compatible_Hashtable>
1112 _M_merge_multi(_Compatible_Hashtable& __src)
1114 static_assert(is_same_v<
typename _Compatible_Hashtable::node_type,
1115 node_type>,
"Node types are compatible");
1116 __glibcxx_assert(get_allocator() == __src.get_allocator());
1118 __node_ptr __hint =
nullptr;
1119 this->reserve(
size() + __src.size());
1120 for (
auto __i = __src.cbegin(), __end = __src.cend(); __i != __end;)
1124 = this->_M_hash_code(__src.hash_function(), *__pos._M_cur);
1125 auto __nh = __src.extract(__pos);
1126 __hint = _M_insert_multi_node(__hint, __code, __nh._M_ptr)._M_cur;
1127 __nh._M_ptr =
nullptr;
1134 void _M_rehash_aux(size_type __bkt_count,
true_type __uks);
1137 void _M_rehash_aux(size_type __bkt_count,
false_type __uks);
1141 void _M_rehash(size_type __bkt_count,
const __rehash_state& __state);
1145 template<
typename _Key,
typename _Value,
typename _Alloc,
1146 typename _ExtractKey,
typename _Equal,
1147 typename _Hash,
typename _RangeHash,
typename _Unused,
1148 typename _RehashPolicy,
typename _Traits>
1150 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1151 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1152 _M_bucket_begin(size_type __bkt)
const
1155 __node_base_ptr __n = _M_buckets[__bkt];
1156 return __n ?
static_cast<__node_ptr
>(__n->_M_nxt) :
nullptr;
1159 template<
typename _Key,
typename _Value,
typename _Alloc,
1160 typename _ExtractKey,
typename _Equal,
1161 typename _Hash,
typename _RangeHash,
typename _Unused,
1162 typename _RehashPolicy,
typename _Traits>
1163 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1164 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1165 _Hashtable(size_type __bkt_count_hint,
1166 const _Hash& __h,
const _Equal& __eq,
const allocator_type& __a)
1167 : _Hashtable(__h, __eq, __a)
1169 auto __bkt_count = _M_rehash_policy._M_next_bkt(__bkt_count_hint);
1170 if (__bkt_count > _M_bucket_count)
1172 _M_buckets = _M_allocate_buckets(__bkt_count);
1173 _M_bucket_count = __bkt_count;
1177 template<
typename _Key,
typename _Value,
typename _Alloc,
1178 typename _ExtractKey,
typename _Equal,
1179 typename _Hash,
typename _RangeHash,
typename _Unused,
1180 typename _RehashPolicy,
typename _Traits>
1181 template<
typename _InputIterator>
1182 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1183 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1184 _Hashtable(_InputIterator __f, _InputIterator __l,
1185 size_type __bkt_count_hint,
1186 const _Hash& __h,
const _Equal& __eq,
1188 : _Hashtable(__bkt_count_hint, __h, __eq, __a)
1190 for (; __f != __l; ++__f)
1194 template<
typename _Key,
typename _Value,
typename _Alloc,
1195 typename _ExtractKey,
typename _Equal,
1196 typename _Hash,
typename _RangeHash,
typename _Unused,
1197 typename _RehashPolicy,
typename _Traits>
1198 template<
typename _InputIterator>
1199 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1200 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1201 _Hashtable(_InputIterator __f, _InputIterator __l,
1202 size_type __bkt_count_hint,
1203 const _Hash& __h,
const _Equal& __eq,
1205 : _Hashtable(__h, __eq, __a)
1207 auto __nb_elems = __detail::__distance_fw(__f, __l);
1209 _M_rehash_policy._M_next_bkt(
1210 std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems),
1213 if (__bkt_count > _M_bucket_count)
1215 _M_buckets = _M_allocate_buckets(__bkt_count);
1216 _M_bucket_count = __bkt_count;
1219 for (; __f != __l; ++__f)
1223 template<
typename _Key,
typename _Value,
typename _Alloc,
1224 typename _ExtractKey,
typename _Equal,
1225 typename _Hash,
typename _RangeHash,
typename _Unused,
1226 typename _RehashPolicy,
typename _Traits>
1228 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1229 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1230 operator=(
const _Hashtable& __ht)
1236 if (__node_alloc_traits::_S_propagate_on_copy_assign())
1238 auto& __this_alloc = this->_M_node_allocator();
1239 auto& __that_alloc = __ht._M_node_allocator();
1240 if (!__node_alloc_traits::_S_always_equal()
1241 && __this_alloc != __that_alloc)
1244 this->_M_deallocate_nodes(_M_begin());
1245 _M_before_begin._M_nxt =
nullptr;
1246 _M_deallocate_buckets();
1247 _M_buckets =
nullptr;
1248 std::__alloc_on_copy(__this_alloc, __that_alloc);
1249 __hashtable_base::operator=(__ht);
1250 _M_bucket_count = __ht._M_bucket_count;
1251 _M_element_count = __ht._M_element_count;
1252 _M_rehash_policy = __ht._M_rehash_policy;
1253 __alloc_node_gen_t __alloc_node_gen(*
this);
1256 _M_assign(__ht, __alloc_node_gen);
1263 __throw_exception_again;
1267 std::__alloc_on_copy(__this_alloc, __that_alloc);
1271 _M_assign_elements(__ht);
1275 template<
typename _Key,
typename _Value,
typename _Alloc,
1276 typename _ExtractKey,
typename _Equal,
1277 typename _Hash,
typename _RangeHash,
typename _Unused,
1278 typename _RehashPolicy,
typename _Traits>
1279 template<
typename _Ht>
1281 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1282 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1283 _M_assign_elements(_Ht&& __ht)
1285 __buckets_ptr __former_buckets =
nullptr;
1286 std::size_t __former_bucket_count = _M_bucket_count;
1287 const __rehash_state& __former_state = _M_rehash_policy._M_state();
1289 if (_M_bucket_count != __ht._M_bucket_count)
1291 __former_buckets = _M_buckets;
1292 _M_buckets = _M_allocate_buckets(__ht._M_bucket_count);
1293 _M_bucket_count = __ht._M_bucket_count;
1296 __builtin_memset(_M_buckets, 0,
1297 _M_bucket_count *
sizeof(__node_base_ptr));
1301 __hashtable_base::operator=(std::forward<_Ht>(__ht));
1302 _M_element_count = __ht._M_element_count;
1303 _M_rehash_policy = __ht._M_rehash_policy;
1304 __reuse_or_alloc_node_gen_t __roan(_M_begin(), *
this);
1305 _M_before_begin._M_nxt =
nullptr;
1306 _M_assign(std::forward<_Ht>(__ht), __roan);
1307 if (__former_buckets)
1308 _M_deallocate_buckets(__former_buckets, __former_bucket_count);
1312 if (__former_buckets)
1315 _M_deallocate_buckets();
1316 _M_rehash_policy._M_reset(__former_state);
1317 _M_buckets = __former_buckets;
1318 _M_bucket_count = __former_bucket_count;
1320 __builtin_memset(_M_buckets, 0,
1321 _M_bucket_count *
sizeof(__node_base_ptr));
1322 __throw_exception_again;
1326 template<
typename _Key,
typename _Value,
typename _Alloc,
1327 typename _ExtractKey,
typename _Equal,
1328 typename _Hash,
typename _RangeHash,
typename _Unused,
1329 typename _RehashPolicy,
typename _Traits>
1330 template<
typename _Ht,
typename _NodeGenerator>
1332 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1333 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1334 _M_assign(_Ht&& __ht,
const _NodeGenerator& __node_gen)
1336 __buckets_ptr __buckets =
nullptr;
1338 _M_buckets = __buckets = _M_allocate_buckets(_M_bucket_count);
1342 if (!__ht._M_before_begin._M_nxt)
1347 __node_ptr __ht_n = __ht._M_begin();
1349 = __node_gen(__fwd_value_for<_Ht>(__ht_n->_M_v()));
1350 this->_M_copy_code(*__this_n, *__ht_n);
1351 _M_update_bbegin(__this_n);
1354 __node_ptr __prev_n = __this_n;
1355 for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next())
1357 __this_n = __node_gen(__fwd_value_for<_Ht>(__ht_n->_M_v()));
1358 __prev_n->_M_nxt = __this_n;
1359 this->_M_copy_code(*__this_n, *__ht_n);
1360 size_type __bkt = _M_bucket_index(*__this_n);
1361 if (!_M_buckets[__bkt])
1362 _M_buckets[__bkt] = __prev_n;
1363 __prev_n = __this_n;
1370 _M_deallocate_buckets();
1371 __throw_exception_again;
1375 template<
typename _Key,
typename _Value,
typename _Alloc,
1376 typename _ExtractKey,
typename _Equal,
1377 typename _Hash,
typename _RangeHash,
typename _Unused,
1378 typename _RehashPolicy,
typename _Traits>
1380 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1381 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1384 _M_rehash_policy._M_reset();
1385 _M_bucket_count = 1;
1386 _M_single_bucket =
nullptr;
1387 _M_buckets = &_M_single_bucket;
1388 _M_before_begin._M_nxt =
nullptr;
1389 _M_element_count = 0;
1392 template<
typename _Key,
typename _Value,
typename _Alloc,
1393 typename _ExtractKey,
typename _Equal,
1394 typename _Hash,
typename _RangeHash,
typename _Unused,
1395 typename _RehashPolicy,
typename _Traits>
1397 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1398 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1399 _M_move_assign(_Hashtable&& __ht,
true_type)
1404 this->_M_deallocate_nodes(_M_begin());
1405 _M_deallocate_buckets();
1406 __hashtable_base::operator=(
std::move(__ht));
1407 _M_rehash_policy = __ht._M_rehash_policy;
1408 if (!__ht._M_uses_single_bucket())
1409 _M_buckets = __ht._M_buckets;
1412 _M_buckets = &_M_single_bucket;
1413 _M_single_bucket = __ht._M_single_bucket;
1416 _M_bucket_count = __ht._M_bucket_count;
1417 _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt;
1418 _M_element_count = __ht._M_element_count;
1419 std::__alloc_on_move(this->_M_node_allocator(), __ht._M_node_allocator());
1426 template<
typename _Key,
typename _Value,
typename _Alloc,
1427 typename _ExtractKey,
typename _Equal,
1428 typename _Hash,
typename _RangeHash,
typename _Unused,
1429 typename _RehashPolicy,
typename _Traits>
1431 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1432 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1433 _M_move_assign(_Hashtable&& __ht,
false_type)
1435 if (__ht._M_node_allocator() == this->_M_node_allocator())
1445 template<
typename _Key,
typename _Value,
typename _Alloc,
1446 typename _ExtractKey,
typename _Equal,
1447 typename _Hash,
typename _RangeHash,
typename _Unused,
1448 typename _RehashPolicy,
typename _Traits>
1449 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1450 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1451 _Hashtable(
const _Hashtable& __ht)
1452 : __hashtable_base(__ht),
1454 __rehash_base(__ht),
1456 __node_alloc_traits::_S_select_on_copy(__ht._M_node_allocator())),
1457 __enable_default_ctor(__ht),
1458 _M_buckets(nullptr),
1459 _M_bucket_count(__ht._M_bucket_count),
1460 _M_element_count(__ht._M_element_count),
1461 _M_rehash_policy(__ht._M_rehash_policy)
1463 __alloc_node_gen_t __alloc_node_gen(*
this);
1464 _M_assign(__ht, __alloc_node_gen);
1467 template<
typename _Key,
typename _Value,
typename _Alloc,
1468 typename _ExtractKey,
typename _Equal,
1469 typename _Hash,
typename _RangeHash,
typename _Unused,
1470 typename _RehashPolicy,
typename _Traits>
1471 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1472 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1473 _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a,
1475 noexcept(_S_nothrow_move())
1476 : __hashtable_base(__ht),
1478 __rehash_base(__ht),
1479 __hashtable_alloc(
std::move(__a)),
1480 __enable_default_ctor(__ht),
1481 _M_buckets(__ht._M_buckets),
1482 _M_bucket_count(__ht._M_bucket_count),
1483 _M_before_begin(__ht._M_before_begin._M_nxt),
1484 _M_element_count(__ht._M_element_count),
1485 _M_rehash_policy(__ht._M_rehash_policy)
1488 if (__ht._M_uses_single_bucket())
1490 _M_buckets = &_M_single_bucket;
1491 _M_single_bucket = __ht._M_single_bucket;
1500 template<
typename _Key,
typename _Value,
typename _Alloc,
1501 typename _ExtractKey,
typename _Equal,
1502 typename _Hash,
typename _RangeHash,
typename _Unused,
1503 typename _RehashPolicy,
typename _Traits>
1504 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1505 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1506 _Hashtable(
const _Hashtable& __ht,
const allocator_type& __a)
1507 : __hashtable_base(__ht),
1509 __rehash_base(__ht),
1510 __hashtable_alloc(__node_alloc_type(__a)),
1511 __enable_default_ctor(__ht),
1513 _M_bucket_count(__ht._M_bucket_count),
1514 _M_element_count(__ht._M_element_count),
1515 _M_rehash_policy(__ht._M_rehash_policy)
1517 __alloc_node_gen_t __alloc_node_gen(*
this);
1518 _M_assign(__ht, __alloc_node_gen);
1521 template<
typename _Key,
typename _Value,
typename _Alloc,
1522 typename _ExtractKey,
typename _Equal,
1523 typename _Hash,
typename _RangeHash,
typename _Unused,
1524 typename _RehashPolicy,
typename _Traits>
1525 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1526 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1527 _Hashtable(_Hashtable&& __ht, __node_alloc_type&& __a,
1529 : __hashtable_base(__ht),
1531 __rehash_base(__ht),
1532 __hashtable_alloc(
std::move(__a)),
1533 __enable_default_ctor(__ht),
1534 _M_buckets(nullptr),
1535 _M_bucket_count(__ht._M_bucket_count),
1536 _M_element_count(__ht._M_element_count),
1537 _M_rehash_policy(__ht._M_rehash_policy)
1539 if (__ht._M_node_allocator() == this->_M_node_allocator())
1541 if (__ht._M_uses_single_bucket())
1543 _M_buckets = &_M_single_bucket;
1544 _M_single_bucket = __ht._M_single_bucket;
1547 _M_buckets = __ht._M_buckets;
1551 _M_update_bbegin(__ht._M_begin());
1557 __alloc_node_gen_t __alloc_gen(*
this);
1559 using _Fwd_Ht = __conditional_t<
1560 __move_if_noexcept_cond<value_type>::value,
1561 const _Hashtable&, _Hashtable&&>;
1562 _M_assign(std::forward<_Fwd_Ht>(__ht), __alloc_gen);
1567 template<
typename _Key,
typename _Value,
typename _Alloc,
1568 typename _ExtractKey,
typename _Equal,
1569 typename _Hash,
typename _RangeHash,
typename _Unused,
1570 typename _RehashPolicy,
typename _Traits>
1571 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1572 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1573 ~_Hashtable() noexcept
1578 static_assert(noexcept(declval<const __hash_code_base_access&>()
1579 ._M_bucket_index(declval<const __node_value_type&>(),
1581 "Cache the hash code or qualify your functors involved"
1582 " in hash code and bucket index computation with noexcept");
1585 _M_deallocate_buckets();
1588 template<
typename _Key,
typename _Value,
typename _Alloc,
1589 typename _ExtractKey,
typename _Equal,
1590 typename _Hash,
typename _RangeHash,
typename _Unused,
1591 typename _RehashPolicy,
typename _Traits>
1593 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1594 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>
::
1595 swap(_Hashtable& __x)
1596 noexcept(__and_<__is_nothrow_swappable<_Hash>,
1597 __is_nothrow_swappable<_Equal>>::value)
1604 std::__alloc_on_swap(this->_M_node_allocator(), __x._M_node_allocator());
1605 std::swap(_M_rehash_policy, __x._M_rehash_policy);
1608 if (this->_M_uses_single_bucket())
1610 if (!__x._M_uses_single_bucket())
1612 _M_buckets = __x._M_buckets;
1613 __x._M_buckets = &__x._M_single_bucket;
1616 else if (__x._M_uses_single_bucket())
1618 __x._M_buckets = _M_buckets;
1619 _M_buckets = &_M_single_bucket;
1624 std::swap(_M_bucket_count, __x._M_bucket_count);
1625 std::swap(_M_before_begin._M_nxt, __x._M_before_begin._M_nxt);
1626 std::swap(_M_element_count, __x._M_element_count);
1627 std::swap(_M_single_bucket, __x._M_single_bucket);
1632 __x._M_update_bbegin();
1635 template<
typename _Key,
typename _Value,
typename _Alloc,
1636 typename _ExtractKey,
typename _Equal,
1637 typename _Hash,
typename _RangeHash,
typename _Unused,
1638 typename _RehashPolicy,
typename _Traits>
1640 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1641 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1642 find(
const key_type& __k)
1645 if (size() <= __small_size_threshold())
1647 for (
auto __it =
begin(); __it !=
end(); ++__it)
1648 if (this->_M_key_equals(__k, *__it._M_cur))
1653 __hash_code __code = this->_M_hash_code(__k);
1654 std::size_t __bkt = _M_bucket_index(__code);
1655 return iterator(_M_find_node(__bkt, __k, __code));
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 find(
const key_type& __k)
const
1668 if (size() <= __small_size_threshold())
1670 for (
auto __it =
begin(); __it !=
end(); ++__it)
1671 if (this->_M_key_equals(__k, *__it._M_cur))
1676 __hash_code __code = this->_M_hash_code(__k);
1677 std::size_t __bkt = _M_bucket_index(__code);
1678 return const_iterator(_M_find_node(__bkt, __k, __code));
1681 #if __cplusplus > 201703L
1682 template<
typename _Key,
typename _Value,
typename _Alloc,
1683 typename _ExtractKey,
typename _Equal,
1684 typename _Hash,
typename _RangeHash,
typename _Unused,
1685 typename _RehashPolicy,
typename _Traits>
1686 template<
typename _Kt,
typename,
typename>
1688 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1689 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1690 _M_find_tr(
const _Kt& __k)
1693 __hash_code __code = this->_M_hash_code_tr(__k);
1694 std::size_t __bkt = _M_bucket_index(__code);
1695 return iterator(_M_find_node_tr(__bkt, __k, __code));
1698 template<
typename _Key,
typename _Value,
typename _Alloc,
1699 typename _ExtractKey,
typename _Equal,
1700 typename _Hash,
typename _RangeHash,
typename _Unused,
1701 typename _RehashPolicy,
typename _Traits>
1702 template<
typename _Kt,
typename,
typename>
1704 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1705 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1706 _M_find_tr(
const _Kt& __k)
const
1709 __hash_code __code = this->_M_hash_code_tr(__k);
1710 std::size_t __bkt = _M_bucket_index(__code);
1711 return const_iterator(_M_find_node_tr(__bkt, __k, __code));
1715 template<
typename _Key,
typename _Value,
typename _Alloc,
1716 typename _ExtractKey,
typename _Equal,
1717 typename _Hash,
typename _RangeHash,
typename _Unused,
1718 typename _RehashPolicy,
typename _Traits>
1720 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1721 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1722 count(
const key_type& __k)
const
1725 auto __it = find(__k);
1729 if (__unique_keys::value)
1735 size_type __result = 1;
1736 for (
auto __ref = __it++;
1737 __it._M_cur && this->_M_node_equals(*__ref._M_cur, *__it._M_cur);
1744 #if __cplusplus > 201703L
1745 template<
typename _Key,
typename _Value,
typename _Alloc,
1746 typename _ExtractKey,
typename _Equal,
1747 typename _Hash,
typename _RangeHash,
typename _Unused,
1748 typename _RehashPolicy,
typename _Traits>
1749 template<
typename _Kt,
typename,
typename>
1751 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1752 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1753 _M_count_tr(
const _Kt& __k)
const
1756 __hash_code __code = this->_M_hash_code_tr(__k);
1757 std::size_t __bkt = _M_bucket_index(__code);
1758 auto __n = _M_find_node_tr(__bkt, __k, __code);
1766 size_type __result = 1;
1768 __it._M_cur && this->_M_equals_tr(__k, __code, *__it._M_cur);
1776 template<
typename _Key,
typename _Value,
typename _Alloc,
1777 typename _ExtractKey,
typename _Equal,
1778 typename _Hash,
typename _RangeHash,
typename _Unused,
1779 typename _RehashPolicy,
typename _Traits>
1781 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1782 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1783 equal_range(
const key_type& __k)
1784 -> pair<iterator, iterator>
1786 auto __ite = find(__k);
1788 return { __ite, __ite };
1790 auto __beg = __ite++;
1791 if (__unique_keys::value)
1792 return { __beg, __ite };
1797 while (__ite._M_cur && this->_M_node_equals(*__beg._M_cur, *__ite._M_cur))
1800 return { __beg, __ite };
1803 template<
typename _Key,
typename _Value,
typename _Alloc,
1804 typename _ExtractKey,
typename _Equal,
1805 typename _Hash,
typename _RangeHash,
typename _Unused,
1806 typename _RehashPolicy,
typename _Traits>
1808 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1809 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1810 equal_range(
const key_type& __k)
const
1811 -> pair<const_iterator, const_iterator>
1813 auto __ite = find(__k);
1815 return { __ite, __ite };
1817 auto __beg = __ite++;
1818 if (__unique_keys::value)
1819 return { __beg, __ite };
1824 while (__ite._M_cur && this->_M_node_equals(*__beg._M_cur, *__ite._M_cur))
1827 return { __beg, __ite };
1830 #if __cplusplus > 201703L
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 template<
typename _Kt,
typename,
typename>
1837 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1838 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1839 _M_equal_range_tr(
const _Kt& __k)
1840 -> pair<iterator, iterator>
1842 __hash_code __code = this->_M_hash_code_tr(__k);
1843 std::size_t __bkt = _M_bucket_index(__code);
1844 auto __n = _M_find_node_tr(__bkt, __k, __code);
1845 iterator __ite(__n);
1847 return { __ite, __ite };
1852 auto __beg = __ite++;
1853 while (__ite._M_cur && this->_M_equals_tr(__k, __code, *__ite._M_cur))
1856 return { __beg, __ite };
1859 template<
typename _Key,
typename _Value,
typename _Alloc,
1860 typename _ExtractKey,
typename _Equal,
1861 typename _Hash,
typename _RangeHash,
typename _Unused,
1862 typename _RehashPolicy,
typename _Traits>
1863 template<
typename _Kt,
typename,
typename>
1865 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1866 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1867 _M_equal_range_tr(
const _Kt& __k)
const
1868 -> pair<const_iterator, const_iterator>
1870 __hash_code __code = this->_M_hash_code_tr(__k);
1871 std::size_t __bkt = _M_bucket_index(__code);
1872 auto __n = _M_find_node_tr(__bkt, __k, __code);
1873 const_iterator __ite(__n);
1875 return { __ite, __ite };
1880 auto __beg = __ite++;
1881 while (__ite._M_cur && this->_M_equals_tr(__k, __code, *__ite._M_cur))
1884 return { __beg, __ite };
1890 template<
typename _Key,
typename _Value,
typename _Alloc,
1891 typename _ExtractKey,
typename _Equal,
1892 typename _Hash,
typename _RangeHash,
typename _Unused,
1893 typename _RehashPolicy,
typename _Traits>
1895 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1896 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1897 _M_find_before_node(
const key_type& __k)
1900 __node_base_ptr __prev_p = &_M_before_begin;
1901 if (!__prev_p->_M_nxt)
1904 for (__node_ptr __p =
static_cast<__node_ptr
>(__prev_p->_M_nxt);
1906 __p = __p->_M_next())
1908 if (this->_M_key_equals(__k, *__p))
1919 template<
typename _Key,
typename _Value,
typename _Alloc,
1920 typename _ExtractKey,
typename _Equal,
1921 typename _Hash,
typename _RangeHash,
typename _Unused,
1922 typename _RehashPolicy,
typename _Traits>
1924 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1925 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1926 _M_find_before_node(size_type __bkt,
const key_type& __k,
1927 __hash_code __code)
const
1930 __node_base_ptr __prev_p = _M_buckets[__bkt];
1934 for (__node_ptr __p =
static_cast<__node_ptr
>(__prev_p->_M_nxt);;
1935 __p = __p->_M_next())
1937 if (this->_M_equals(__k, __code, *__p))
1940 if (!__p->_M_nxt || _M_bucket_index(*__p->_M_next()) != __bkt)
1948 template<
typename _Key,
typename _Value,
typename _Alloc,
1949 typename _ExtractKey,
typename _Equal,
1950 typename _Hash,
typename _RangeHash,
typename _Unused,
1951 typename _RehashPolicy,
typename _Traits>
1952 template<
typename _Kt>
1954 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1955 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1956 _M_find_before_node_tr(size_type __bkt,
const _Kt& __k,
1957 __hash_code __code)
const
1960 __node_base_ptr __prev_p = _M_buckets[__bkt];
1964 for (__node_ptr __p =
static_cast<__node_ptr
>(__prev_p->_M_nxt);;
1965 __p = __p->_M_next())
1967 if (this->_M_equals_tr(__k, __code, *__p))
1970 if (!__p->_M_nxt || _M_bucket_index(*__p->_M_next()) != __bkt)
1978 template<
typename _Key,
typename _Value,
typename _Alloc,
1979 typename _ExtractKey,
typename _Equal,
1980 typename _Hash,
typename _RangeHash,
typename _Unused,
1981 typename _RehashPolicy,
typename _Traits>
1983 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1984 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
1985 _M_insert_bucket_begin(size_type __bkt, __node_ptr __node)
1987 if (_M_buckets[__bkt])
1991 __node->_M_nxt = _M_buckets[__bkt]->_M_nxt;
1992 _M_buckets[__bkt]->_M_nxt = __node;
1999 __node->_M_nxt = _M_before_begin._M_nxt;
2000 _M_before_begin._M_nxt = __node;
2005 _M_buckets[_M_bucket_index(*__node->_M_next())] = __node;
2007 _M_buckets[__bkt] = &_M_before_begin;
2011 template<
typename _Key,
typename _Value,
typename _Alloc,
2012 typename _ExtractKey,
typename _Equal,
2013 typename _Hash,
typename _RangeHash,
typename _Unused,
2014 typename _RehashPolicy,
typename _Traits>
2016 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2017 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2018 _M_remove_bucket_begin(size_type __bkt, __node_ptr __next,
2019 size_type __next_bkt)
2021 if (!__next || __next_bkt != __bkt)
2026 _M_buckets[__next_bkt] = _M_buckets[__bkt];
2029 if (&_M_before_begin == _M_buckets[__bkt])
2030 _M_before_begin._M_nxt = __next;
2031 _M_buckets[__bkt] =
nullptr;
2035 template<
typename _Key,
typename _Value,
typename _Alloc,
2036 typename _ExtractKey,
typename _Equal,
2037 typename _Hash,
typename _RangeHash,
typename _Unused,
2038 typename _RehashPolicy,
typename _Traits>
2040 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2041 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2042 _M_get_previous_node(size_type __bkt, __node_ptr __n)
2045 __node_base_ptr __prev_n = _M_buckets[__bkt];
2046 while (__prev_n->_M_nxt != __n)
2047 __prev_n = __prev_n->_M_nxt;
2051 template<
typename _Key,
typename _Value,
typename _Alloc,
2052 typename _ExtractKey,
typename _Equal,
2053 typename _Hash,
typename _RangeHash,
typename _Unused,
2054 typename _RehashPolicy,
typename _Traits>
2055 template<
typename... _Args>
2057 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2058 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2059 _M_emplace(
true_type , _Args&&... __args)
2060 -> pair<iterator, bool>
2063 _Scoped_node __node {
this, std::forward<_Args>(__args)... };
2064 const key_type& __k = _ExtractKey{}(__node._M_node->_M_v());
2065 if (size() <= __small_size_threshold())
2067 for (
auto __it =
begin(); __it !=
end(); ++__it)
2068 if (this->_M_key_equals(__k, *__it._M_cur))
2070 return { __it,
false };
2073 __hash_code __code = this->_M_hash_code(__k);
2074 size_type __bkt = _M_bucket_index(__code);
2075 if (size() > __small_size_threshold())
2076 if (__node_ptr __p = _M_find_node(__bkt, __k, __code))
2078 return { iterator(__p),
false };
2081 auto __pos = _M_insert_unique_node(__bkt, __code, __node._M_node);
2082 __node._M_node =
nullptr;
2083 return { __pos,
true };
2086 template<
typename _Key,
typename _Value,
typename _Alloc,
2087 typename _ExtractKey,
typename _Equal,
2088 typename _Hash,
typename _RangeHash,
typename _Unused,
2089 typename _RehashPolicy,
typename _Traits>
2090 template<
typename... _Args>
2092 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2093 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2094 _M_emplace(const_iterator __hint,
false_type ,
2099 _Scoped_node __node {
this, std::forward<_Args>(__args)... };
2100 const key_type& __k = _ExtractKey{}(__node._M_node->_M_v());
2102 auto __res = this->_M_compute_hash_code(__hint, __k);
2104 = _M_insert_multi_node(__res.first._M_cur, __res.second,
2106 __node._M_node =
nullptr;
2110 template<
typename _Key,
typename _Value,
typename _Alloc,
2111 typename _ExtractKey,
typename _Equal,
2112 typename _Hash,
typename _RangeHash,
typename _Unused,
2113 typename _RehashPolicy,
typename _Traits>
2115 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2116 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2117 _M_compute_hash_code(const_iterator __hint,
const key_type& __k)
const
2118 -> pair<const_iterator, __hash_code>
2120 if (size() <= __small_size_threshold())
2122 if (__hint != cend())
2124 for (
auto __it = __hint; __it != cend(); ++__it)
2125 if (this->_M_key_equals(__k, *__it._M_cur))
2126 return { __it, this->_M_hash_code(*__it._M_cur) };
2129 for (
auto __it = cbegin(); __it != __hint; ++__it)
2130 if (this->_M_key_equals(__k, *__it._M_cur))
2131 return { __it, this->_M_hash_code(*__it._M_cur) };
2134 return { __hint, this->_M_hash_code(__k) };
2137 template<
typename _Key,
typename _Value,
typename _Alloc,
2138 typename _ExtractKey,
typename _Equal,
2139 typename _Hash,
typename _RangeHash,
typename _Unused,
2140 typename _RehashPolicy,
typename _Traits>
2142 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2143 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2144 _M_insert_unique_node(size_type __bkt, __hash_code __code,
2145 __node_ptr __node, size_type __n_elt)
2148 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
2150 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count,
2153 if (__do_rehash.
first)
2155 _M_rehash(__do_rehash.
second, __saved_state);
2156 __bkt = _M_bucket_index(__code);
2159 this->_M_store_code(*__node, __code);
2162 _M_insert_bucket_begin(__bkt, __node);
2164 return iterator(__node);
2167 template<
typename _Key,
typename _Value,
typename _Alloc,
2168 typename _ExtractKey,
typename _Equal,
2169 typename _Hash,
typename _RangeHash,
typename _Unused,
2170 typename _RehashPolicy,
typename _Traits>
2172 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2173 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2174 _M_insert_multi_node(__node_ptr __hint,
2175 __hash_code __code, __node_ptr __node)
2178 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
2180 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
2182 if (__do_rehash.
first)
2183 _M_rehash(__do_rehash.
second, __saved_state);
2185 this->_M_store_code(*__node, __code);
2186 const key_type& __k = _ExtractKey{}(__node->_M_v());
2187 size_type __bkt = _M_bucket_index(__code);
2191 __node_base_ptr __prev
2192 = __builtin_expect(__hint !=
nullptr,
false)
2193 && this->_M_equals(__k, __code, *__hint)
2195 : _M_find_before_node(__bkt, __k, __code);
2200 __node->_M_nxt = __prev->_M_nxt;
2201 __prev->_M_nxt = __node;
2202 if (__builtin_expect(__prev == __hint,
false))
2206 && !this->_M_equals(__k, __code, *__node->_M_next()))
2208 size_type __next_bkt = _M_bucket_index(*__node->_M_next());
2209 if (__next_bkt != __bkt)
2210 _M_buckets[__next_bkt] = __node;
2217 _M_insert_bucket_begin(__bkt, __node);
2219 return iterator(__node);
2223 template<
typename _Key,
typename _Value,
typename _Alloc,
2224 typename _ExtractKey,
typename _Equal,
2225 typename _Hash,
typename _RangeHash,
typename _Unused,
2226 typename _RehashPolicy,
typename _Traits>
2227 template<
typename _Kt,
typename _Arg,
typename _NodeGenerator>
2229 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2230 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2231 _M_insert_unique(_Kt&& __k, _Arg&& __v,
2232 const _NodeGenerator& __node_gen)
2233 -> pair<iterator, bool>
2235 if (size() <= __small_size_threshold())
2236 for (
auto __it =
begin(); __it !=
end(); ++__it)
2237 if (this->_M_key_equals_tr(__k, *__it._M_cur))
2238 return { __it,
false };
2240 __hash_code __code = this->_M_hash_code_tr(__k);
2241 size_type __bkt = _M_bucket_index(__code);
2243 if (size() > __small_size_threshold())
2244 if (__node_ptr __node = _M_find_node_tr(__bkt, __k, __code))
2245 return { iterator(__node),
false };
2247 _Scoped_node __node {
2248 __node_builder_t::_S_build(std::forward<_Kt>(__k),
2249 std::forward<_Arg>(__v),
2254 = _M_insert_unique_node(__bkt, __code, __node._M_node);
2255 __node._M_node =
nullptr;
2256 return { __pos,
true };
2260 template<
typename _Key,
typename _Value,
typename _Alloc,
2261 typename _ExtractKey,
typename _Equal,
2262 typename _Hash,
typename _RangeHash,
typename _Unused,
2263 typename _RehashPolicy,
typename _Traits>
2264 template<
typename _Arg,
typename _NodeGenerator>
2266 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2267 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2268 _M_insert(const_iterator __hint, _Arg&& __v,
2269 const _NodeGenerator& __node_gen,
2274 _Scoped_node __node{ __node_gen(std::forward<_Arg>(__v)),
this };
2277 auto __res = this->_M_compute_hash_code(
2278 __hint, _ExtractKey{}(__node._M_node->_M_v()));
2281 = _M_insert_multi_node(__res.first._M_cur, __res.second,
2283 __node._M_node =
nullptr;
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 erase(const_iterator __it)
2297 __node_ptr __n = __it._M_cur;
2298 std::size_t __bkt = _M_bucket_index(*__n);
2303 __node_base_ptr __prev_n = _M_get_previous_node(__bkt, __n);
2304 return _M_erase(__bkt, __prev_n, __n);
2307 template<
typename _Key,
typename _Value,
typename _Alloc,
2308 typename _ExtractKey,
typename _Equal,
2309 typename _Hash,
typename _RangeHash,
typename _Unused,
2310 typename _RehashPolicy,
typename _Traits>
2312 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2313 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2314 _M_erase(size_type __bkt, __node_base_ptr __prev_n, __node_ptr __n)
2317 if (__prev_n == _M_buckets[__bkt])
2318 _M_remove_bucket_begin(__bkt, __n->_M_next(),
2319 __n->_M_nxt ? _M_bucket_index(*__n->_M_next()) : 0);
2320 else if (__n->_M_nxt)
2322 size_type __next_bkt = _M_bucket_index(*__n->_M_next());
2323 if (__next_bkt != __bkt)
2324 _M_buckets[__next_bkt] = __prev_n;
2327 __prev_n->_M_nxt = __n->_M_nxt;
2328 iterator __result(__n->_M_next());
2329 this->_M_deallocate_node(__n);
2335 template<
typename _Key,
typename _Value,
typename _Alloc,
2336 typename _ExtractKey,
typename _Equal,
2337 typename _Hash,
typename _RangeHash,
typename _Unused,
2338 typename _RehashPolicy,
typename _Traits>
2340 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2341 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2342 _M_erase(
true_type ,
const key_type& __k)
2345 __node_base_ptr __prev_n;
2348 if (size() <= __small_size_threshold())
2350 __prev_n = _M_find_before_node(__k);
2355 __n =
static_cast<__node_ptr
>(__prev_n->_M_nxt);
2356 __bkt = _M_bucket_index(*__n);
2360 __hash_code __code = this->_M_hash_code(__k);
2361 __bkt = _M_bucket_index(__code);
2364 __prev_n = _M_find_before_node(__bkt, __k, __code);
2369 __n =
static_cast<__node_ptr
>(__prev_n->_M_nxt);
2372 _M_erase(__bkt, __prev_n, __n);
2376 template<
typename _Key,
typename _Value,
typename _Alloc,
2377 typename _ExtractKey,
typename _Equal,
2378 typename _Hash,
typename _RangeHash,
typename _Unused,
2379 typename _RehashPolicy,
typename _Traits>
2381 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2382 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2387 __node_base_ptr __prev_n;
2389 if (size() <= __small_size_threshold())
2391 __prev_n = _M_find_before_node(__k);
2396 __n =
static_cast<__node_ptr
>(__prev_n->_M_nxt);
2397 __bkt = _M_bucket_index(*__n);
2401 __hash_code __code = this->_M_hash_code(__k);
2402 __bkt = _M_bucket_index(__code);
2405 __prev_n = _M_find_before_node(__bkt, __k, __code);
2409 __n =
static_cast<__node_ptr
>(__prev_n->_M_nxt);
2418 __node_ptr __n_last = __n->_M_next();
2419 while (__n_last && this->_M_node_equals(*__n, *__n_last))
2420 __n_last = __n_last->_M_next();
2422 std::size_t __n_last_bkt = __n_last ? _M_bucket_index(*__n_last) : __bkt;
2425 size_type __result = 0;
2428 __node_ptr __p = __n->_M_next();
2429 this->_M_deallocate_node(__n);
2433 while (__n != __n_last);
2435 _M_element_count -= __result;
2436 if (__prev_n == _M_buckets[__bkt])
2437 _M_remove_bucket_begin(__bkt, __n_last, __n_last_bkt);
2438 else if (__n_last_bkt != __bkt)
2439 _M_buckets[__n_last_bkt] = __prev_n;
2440 __prev_n->_M_nxt = __n_last;
2444 template<
typename _Key,
typename _Value,
typename _Alloc,
2445 typename _ExtractKey,
typename _Equal,
2446 typename _Hash,
typename _RangeHash,
typename _Unused,
2447 typename _RehashPolicy,
typename _Traits>
2449 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2450 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2451 erase(const_iterator __first, const_iterator __last)
2454 __node_ptr __n = __first._M_cur;
2455 __node_ptr __last_n = __last._M_cur;
2456 if (__n == __last_n)
2457 return iterator(__n);
2459 std::size_t __bkt = _M_bucket_index(*__n);
2461 __node_base_ptr __prev_n = _M_get_previous_node(__bkt, __n);
2462 bool __is_bucket_begin = __n == _M_bucket_begin(__bkt);
2463 std::size_t __n_bkt = __bkt;
2468 __node_ptr __tmp = __n;
2469 __n = __n->_M_next();
2470 this->_M_deallocate_node(__tmp);
2474 __n_bkt = _M_bucket_index(*__n);
2476 while (__n != __last_n && __n_bkt == __bkt);
2477 if (__is_bucket_begin)
2478 _M_remove_bucket_begin(__bkt, __n, __n_bkt);
2479 if (__n == __last_n)
2481 __is_bucket_begin =
true;
2485 if (__n && (__n_bkt != __bkt || __is_bucket_begin))
2486 _M_buckets[__n_bkt] = __prev_n;
2487 __prev_n->_M_nxt = __n;
2488 return iterator(__n);
2491 template<
typename _Key,
typename _Value,
typename _Alloc,
2492 typename _ExtractKey,
typename _Equal,
2493 typename _Hash,
typename _RangeHash,
typename _Unused,
2494 typename _RehashPolicy,
typename _Traits>
2496 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2497 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2500 this->_M_deallocate_nodes(_M_begin());
2501 __builtin_memset(_M_buckets, 0,
2502 _M_bucket_count *
sizeof(__node_base_ptr));
2503 _M_element_count = 0;
2504 _M_before_begin._M_nxt =
nullptr;
2507 template<
typename _Key,
typename _Value,
typename _Alloc,
2508 typename _ExtractKey,
typename _Equal,
2509 typename _Hash,
typename _RangeHash,
typename _Unused,
2510 typename _RehashPolicy,
typename _Traits>
2512 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2513 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2514 rehash(size_type __bkt_count)
2516 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
2518 =
std::max(_M_rehash_policy._M_bkt_for_elements(_M_element_count + 1),
2520 __bkt_count = _M_rehash_policy._M_next_bkt(__bkt_count);
2522 if (__bkt_count != _M_bucket_count)
2523 _M_rehash(__bkt_count, __saved_state);
2527 _M_rehash_policy._M_reset(__saved_state);
2530 template<
typename _Key,
typename _Value,
typename _Alloc,
2531 typename _ExtractKey,
typename _Equal,
2532 typename _Hash,
typename _RangeHash,
typename _Unused,
2533 typename _RehashPolicy,
typename _Traits>
2535 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2536 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2537 _M_rehash(size_type __bkt_count,
const __rehash_state& __state)
2541 _M_rehash_aux(__bkt_count, __unique_keys{});
2547 _M_rehash_policy._M_reset(__state);
2548 __throw_exception_again;
2553 template<
typename _Key,
typename _Value,
typename _Alloc,
2554 typename _ExtractKey,
typename _Equal,
2555 typename _Hash,
typename _RangeHash,
typename _Unused,
2556 typename _RehashPolicy,
typename _Traits>
2558 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2559 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
2560 _M_rehash_aux(size_type __bkt_count,
true_type )
2562 __buckets_ptr __new_buckets = _M_allocate_buckets(__bkt_count);
2563 __node_ptr __p = _M_begin();
2564 _M_before_begin._M_nxt =
nullptr;
2565 std::size_t __bbegin_bkt = 0;
2568 __node_ptr __next = __p->_M_next();
2570 = __hash_code_base::_M_bucket_index(*__p, __bkt_count);
2571 if (!__new_buckets[__bkt])
2573 __p->_M_nxt = _M_before_begin._M_nxt;
2574 _M_before_begin._M_nxt = __p;
2575 __new_buckets[__bkt] = &_M_before_begin;
2577 __new_buckets[__bbegin_bkt] = __p;
2578 __bbegin_bkt = __bkt;
2582 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2583 __new_buckets[__bkt]->_M_nxt = __p;
2589 _M_deallocate_buckets();
2590 _M_bucket_count = __bkt_count;
2591 _M_buckets = __new_buckets;
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 _M_rehash_aux(size_type __bkt_count,
false_type )
2605 __buckets_ptr __new_buckets = _M_allocate_buckets(__bkt_count);
2606 __node_ptr __p = _M_begin();
2607 _M_before_begin._M_nxt =
nullptr;
2608 std::size_t __bbegin_bkt = 0;
2609 std::size_t __prev_bkt = 0;
2610 __node_ptr __prev_p =
nullptr;
2611 bool __check_bucket =
false;
2615 __node_ptr __next = __p->_M_next();
2617 = __hash_code_base::_M_bucket_index(*__p, __bkt_count);
2619 if (__prev_p && __prev_bkt == __bkt)
2624 __p->_M_nxt = __prev_p->_M_nxt;
2625 __prev_p->_M_nxt = __p;
2632 __check_bucket =
true;
2640 if (__prev_p->_M_nxt)
2642 std::size_t __next_bkt
2643 = __hash_code_base::_M_bucket_index(
2644 *__prev_p->_M_next(), __bkt_count);
2645 if (__next_bkt != __prev_bkt)
2646 __new_buckets[__next_bkt] = __prev_p;
2648 __check_bucket =
false;
2651 if (!__new_buckets[__bkt])
2653 __p->_M_nxt = _M_before_begin._M_nxt;
2654 _M_before_begin._M_nxt = __p;
2655 __new_buckets[__bkt] = &_M_before_begin;
2657 __new_buckets[__bbegin_bkt] = __p;
2658 __bbegin_bkt = __bkt;
2662 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2663 __new_buckets[__bkt]->_M_nxt = __p;
2671 if (__check_bucket && __prev_p->_M_nxt)
2673 std::size_t __next_bkt
2674 = __hash_code_base::_M_bucket_index(*__prev_p->_M_next(),
2676 if (__next_bkt != __prev_bkt)
2677 __new_buckets[__next_bkt] = __prev_p;
2680 _M_deallocate_buckets();
2681 _M_bucket_count = __bkt_count;
2682 _M_buckets = __new_buckets;
2685 #if __cplusplus > 201402L
2686 template<
typename,
typename,
typename>
class _Hash_merge_helper { };
2689 #if __cpp_deduction_guides >= 201606
2691 template<
typename _Hash>
2692 using _RequireNotAllocatorOrIntegral
2693 = __enable_if_t<!__or_<is_integral<_Hash>, __is_allocator<_Hash>>::value>;
2697 _GLIBCXX_END_NAMESPACE_VERSION
integral_constant< bool, true > true_type
The type used as a compile-time boolean with true value.
integral_constant< bool, false > false_type
The type used as a compile-time boolean with false value.
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
constexpr _Tp && forward(typename std::remove_reference< _Tp >::type &__t) noexcept
Forward an lvalue.
void swap(any &__x, any &__y) noexcept
Exchange the states of two any objects.
_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.
void swap(shared_lock< _Mutex > &__x, shared_lock< _Mutex > &__y) noexcept
Swap specialization for shared_lock.
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.
constexpr const _Tp * begin(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to the first element of the initializer_list.
constexpr const _Tp * end(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to one past the last element of the initializer_list.
Struct holding two objects of arbitrary type.
_T1 first
The first member.
_T2 second
The second member.