31 #define _HASHTABLE_H 1
33 #pragma GCC system_header
37 namespace std _GLIBCXX_VISIBILITY(default)
39 _GLIBCXX_BEGIN_NAMESPACE_VERSION
41 template<
typename _Tp,
typename _Hash>
44 __is_fast_hash<_Hash>,
47 is_default_constructible<_Hash>,
48 is_copy_assignable<_Hash>,
50 __detail::__is_noexcept_hash<_Tp, _Hash>>>;
170 template<
typename _Key,
typename _Value,
typename _Alloc,
171 typename _ExtractKey,
typename _Equal,
172 typename _H1,
typename _H2,
typename _Hash,
173 typename _RehashPolicy,
typename _Traits>
176 _H1, _H2, _Hash, _Traits>,
178 _H1, _H2, _Hash, _RehashPolicy, _Traits>,
180 _H1, _H2, _Hash, _RehashPolicy, _Traits>,
182 _H1, _H2, _Hash, _RehashPolicy, _Traits>,
184 _H1, _H2, _Hash, _RehashPolicy, _Traits>
187 typedef typename _Alloc_traits::template rebind_alloc<_Value>
192 typedef _Key key_type;
193 typedef _Value value_type;
194 typedef _Alloc allocator_type;
195 typedef _Equal key_equal;
199 typedef typename _Value_alloc_traits::pointer pointer;
200 typedef typename _Value_alloc_traits::const_pointer const_pointer;
201 typedef value_type& reference;
202 typedef const value_type& const_reference;
205 using __rehash_type = _RehashPolicy;
206 using __rehash_state =
typename __rehash_type::_State;
208 using __traits_type = _Traits;
209 using __hash_cached =
typename __traits_type::__hash_cached;
210 using __constant_iterators =
typename __traits_type::__constant_iterators;
211 using __unique_keys =
typename __traits_type::__unique_keys;
213 using __key_extract =
typename std::conditional<
214 __constant_iterators::value,
216 __detail::_Select1st>::type;
220 _Equal, _H1, _H2, _Hash, _Traits>;
223 using __hash_code =
typename __hashtable_base::__hash_code;
224 using __node_type =
typename __hashtable_base::__node_type;
227 using __ireturn_type =
typename __hashtable_base::__ireturn_type;
230 _Equal, _H1, _H2, _Hash,
231 _RehashPolicy, _Traits>;
236 _RehashPolicy, _Traits>;
239 _Equal, _H1, _H2, _Hash,
240 _RehashPolicy, _Traits>;
243 template<
typename _Cond>
244 using __if_hash_cached = __or_<__not_<__hash_cached>, _Cond>;
246 template<
typename _Cond>
247 using __if_hash_not_cached = __or_<__hash_cached, _Cond>;
253 static_assert(noexcept(declval<const _Hashtable&>()
254 ._M_bucket_index((
const __node_type*)
nullptr,
256 "Cache the hash code or qualify your functors involved"
257 " in hash code and bucket index computation with noexcept");
264 static_assert(__if_hash_cached<is_default_constructible<_H2>>::value,
265 "Functor used to map hash code to bucket index"
266 " must be default constructible");
271 static_assert(__if_hash_not_cached<
272 is_default_constructible<
276 "Cache the hash code or make functors involved in hash code"
277 " and bucket index computation default constructible");
282 static_assert(__if_hash_not_cached<
283 is_copy_assignable<__hash_code_base>>::value,
284 "Cache the hash code or make functors involved in hash code"
285 " and bucket index computation copy assignable");
288 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
289 typename _ExtractKeya,
typename _Equala,
290 typename _H1a,
typename _H2a,
typename _Hasha,
291 typename _RehashPolicya,
typename _Traitsa,
295 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
296 typename _ExtractKeya,
typename _Equala,
297 typename _H1a,
typename _H2a,
typename _Hasha,
298 typename _RehashPolicya,
typename _Traitsa>
301 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
302 typename _ExtractKeya,
typename _Equala,
303 typename _H1a,
typename _H2a,
typename _Hasha,
304 typename _RehashPolicya,
typename _Traitsa,
305 bool _Constant_iteratorsa,
bool _Unique_keysa>
308 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
309 typename _ExtractKeya,
typename _Equala,
310 typename _H1a,
typename _H2a,
typename _Hasha,
311 typename _RehashPolicya,
typename _Traitsa,
312 bool _IsCopyAssignable>
315 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
316 typename _ExtractKeya,
typename _Equala,
317 typename _H1a,
typename _H2a,
typename _Hasha,
318 typename _RehashPolicya,
typename _Traitsa,
319 bool _IsMoveAssignable>
322 using size_type =
typename __hashtable_base::size_type;
323 using difference_type =
typename __hashtable_base::difference_type;
333 typedef typename _Alloc_traits::template rebind_alloc<__node_type>
339 typename _Alloc_traits::template rebind_alloc<__bucket_type>
345 __bucket_type* _M_buckets;
346 size_type _M_bucket_count;
348 size_type _M_element_count;
349 _RehashPolicy _M_rehash_policy;
353 {
return _M_bbegin; }
355 const _Node_alloc_type&
356 _M_node_allocator()
const
357 {
return _M_bbegin; }
361 {
return _M_bbegin._M_node; }
364 _M_before_begin()
const
365 {
return _M_bbegin._M_node; }
367 template<
typename... _Args>
369 _M_allocate_node(_Args&&... __args);
372 _M_deallocate_node(__node_type* __n);
376 _M_deallocate_nodes(__node_type* __n);
379 _M_allocate_buckets(size_type __n);
382 _M_deallocate_buckets(__bucket_type*, size_type __n);
385 _M_deallocate_buckets()
386 { _M_deallocate_buckets(_M_buckets, _M_bucket_count); }
391 _M_bucket_begin(size_type __bkt)
const;
395 {
return static_cast<__node_type*
>(_M_before_begin()._M_nxt); }
397 template<
typename _UnaryOp>
399 _M_assign(
const _Hashtable&,
const _UnaryOp&);
413 const _H1&,
const _H2&,
const _Hash&,
414 const _Equal&,
const _ExtractKey&,
415 const allocator_type&);
417 template<
typename _InputIterator>
418 _Hashtable(_InputIterator __first, _InputIterator __last,
419 size_type __bucket_hint,
420 const _H1&,
const _H2&,
const _Hash&,
421 const _Equal&,
const _ExtractKey&,
422 const allocator_type&);
437 __key_extract(), __a)
442 const _H1& __hf = _H1(),
443 const key_equal& __eql = key_equal(),
444 const allocator_type& __a = allocator_type())
447 __key_extract(), __a)
450 template<
typename _InputIterator>
451 _Hashtable(_InputIterator __f, _InputIterator __l,
453 const _H1& __hf = _H1(),
454 const key_equal& __eql = key_equal(),
455 const allocator_type& __a = allocator_type())
458 __key_extract(), __a)
463 const _H1& __hf = _H1(),
464 const key_equal& __eql = key_equal(),
465 const allocator_type& __a = allocator_type())
466 :
_Hashtable(__l.begin(), __l.end(), __n, __hf,
469 __key_extract(), __a)
477 noexcept(_Node_alloc_traits::_S_nothrow_move())
479 constexpr
bool __move_storage =
480 _Node_alloc_traits::_S_propagate_on_move_assign()
481 || _Node_alloc_traits::_S_always_equal();
482 _M_move_assign(std::move(__ht),
491 this->insert(__l.begin(), __l.end());
499 noexcept(_Node_alloc_traits::_S_nothrow_swap());
504 {
return iterator(_M_begin()); }
507 begin()
const noexcept
508 {
return const_iterator(_M_begin()); }
512 {
return iterator(
nullptr); }
516 {
return const_iterator(
nullptr); }
519 cbegin()
const noexcept
520 {
return const_iterator(_M_begin()); }
523 cend()
const noexcept
524 {
return const_iterator(
nullptr); }
527 size()
const noexcept
528 {
return _M_element_count; }
531 empty()
const noexcept
532 {
return size() == 0; }
535 get_allocator()
const noexcept
536 {
return allocator_type(_M_node_allocator()); }
539 max_size()
const noexcept
545 {
return this->_M_eq(); }
551 bucket_count()
const noexcept
552 {
return _M_bucket_count; }
555 max_bucket_count()
const noexcept
556 {
return max_size(); }
559 bucket_size(size_type __n)
const
563 bucket(
const key_type& __k)
const
564 {
return _M_bucket_index(__k, this->_M_hash_code(__k)); }
569 return local_iterator(*
this, _M_bucket_begin(__n),
570 __n, _M_bucket_count);
575 {
return local_iterator(*
this,
nullptr, __n, _M_bucket_count); }
578 begin(size_type __n)
const
580 return const_local_iterator(*
this, _M_bucket_begin(__n),
581 __n, _M_bucket_count);
585 end(size_type __n)
const
586 {
return const_local_iterator(*
this,
nullptr, __n, _M_bucket_count); }
590 cbegin(size_type __n)
const
592 return const_local_iterator(*
this, _M_bucket_begin(__n),
593 __n, _M_bucket_count);
597 cend(size_type __n)
const
598 {
return const_local_iterator(*
this,
nullptr, __n, _M_bucket_count); }
601 load_factor()
const noexcept
603 return static_cast<float>(
size()) / static_cast<float>(bucket_count());
612 __rehash_policy()
const
613 {
return _M_rehash_policy; }
616 __rehash_policy(
const _RehashPolicy&);
620 find(
const key_type& __k);
623 find(
const key_type& __k)
const;
626 count(
const key_type& __k)
const;
629 equal_range(
const key_type& __k);
632 equal_range(
const key_type& __k)
const;
637 _M_bucket_index(__node_type* __n)
const noexcept
638 {
return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); }
641 _M_bucket_index(
const key_type& __k, __hash_code __c)
const
642 {
return __hash_code_base::_M_bucket_index(__k, __c, _M_bucket_count); }
647 _M_find_before_node(size_type,
const key_type&, __hash_code)
const;
650 _M_find_node(size_type __bkt,
const key_type& __key,
651 __hash_code __c)
const
653 __node_base* __before_n = _M_find_before_node(__bkt, __key, __c);
655 return static_cast<__node_type*
>(__before_n->_M_nxt);
661 _M_insert_bucket_begin(size_type, __node_type*);
665 _M_remove_bucket_begin(size_type __bkt, __node_type* __next_n,
666 size_type __next_bkt);
670 _M_get_previous_node(size_type __bkt, __node_base* __n);
676 _M_insert_unique_node(size_type __bkt, __hash_code __code,
682 _M_insert_multi_node(__node_type* __hint,
683 __hash_code __code, __node_type* __n);
685 template<
typename... _Args>
689 template<
typename... _Args>
692 {
return _M_emplace(cend(), __uk, std::forward<_Args>(__args)...); }
695 template<
typename... _Args>
697 _M_emplace(const_iterator,
std::true_type __uk, _Args&&... __args)
698 {
return _M_emplace(__uk, std::forward<_Args>(__args)...).first; }
700 template<
typename... _Args>
704 template<
typename _Arg>
708 template<
typename _Arg>
711 {
return _M_insert(cend(), std::forward<_Arg>(__arg), __uk); }
714 template<
typename _Arg>
717 {
return _M_insert(std::forward<_Arg>(__arg), __uk).
first; }
720 template<
typename _Arg>
731 _M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n);
735 template<
typename... _Args>
737 emplace(_Args&&... __args)
738 {
return _M_emplace(__unique_keys(), std::forward<_Args>(__args)...); }
740 template<
typename... _Args>
742 emplace_hint(const_iterator __hint, _Args&&... __args)
744 return _M_emplace(__hint, __unique_keys(),
745 std::forward<_Args>(__args)...);
752 erase(const_iterator);
757 {
return erase(const_iterator(__it)); }
760 erase(
const key_type& __k)
762 if (__builtin_expect(_M_bucket_count == 0,
false))
764 return _M_erase(__unique_keys(), __k);
768 erase(const_iterator, const_iterator);
774 void rehash(size_type __n);
788 void _M_rehash(size_type __n,
const __rehash_state& __state);
793 template<
typename _Key,
typename _Value,
794 typename _Alloc,
typename _ExtractKey,
typename _Equal,
795 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
797 template<
typename... _Args>
798 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
799 _H1, _H2, _Hash, _RehashPolicy, _Traits>::__node_type*
800 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
801 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
802 _M_allocate_node(_Args&&... __args)
804 auto __nptr = _Node_alloc_traits::allocate(_M_node_allocator(), 1);
808 _Value_alloc_type __a(_M_node_allocator());
809 ::new ((
void*)__n) __node_type();
810 _Value_alloc_traits::construct(__a, __n->_M_valptr(),
811 std::
forward<_Args>(__args)...);
816 _Node_alloc_traits::deallocate(_M_node_allocator(), __nptr, 1);
817 __throw_exception_again;
821 template<
typename _Key,
typename _Value,
822 typename _Alloc,
typename _ExtractKey,
typename _Equal,
823 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
826 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
827 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
828 _M_deallocate_node(__node_type* __n)
830 typedef typename _Node_alloc_traits::pointer _Ptr;
832 _Value_alloc_type __a(_M_node_allocator());
833 _Value_alloc_traits::destroy(__a, __n->_M_valptr());
835 _Node_alloc_traits::deallocate(_M_node_allocator(), __ptr, 1);
838 template<
typename _Key,
typename _Value,
839 typename _Alloc,
typename _ExtractKey,
typename _Equal,
840 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
843 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
844 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
845 _M_deallocate_nodes(__node_type* __n)
849 __node_type* __tmp = __n;
850 __n = __n->_M_next();
851 _M_deallocate_node(__tmp);
855 template<
typename _Key,
typename _Value,
856 typename _Alloc,
typename _ExtractKey,
typename _Equal,
857 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
859 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
860 _H1, _H2, _Hash, _RehashPolicy, _Traits>::__bucket_type*
861 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
862 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
863 _M_allocate_buckets(size_type __n)
865 _Bucket_alloc_type __alloc(_M_node_allocator());
867 auto __ptr = _Bucket_alloc_traits::allocate(__alloc, __n);
869 __builtin_memset(__p, 0, __n *
sizeof(__bucket_type));
873 template<
typename _Key,
typename _Value,
874 typename _Alloc,
typename _ExtractKey,
typename _Equal,
875 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
878 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
879 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
880 _M_deallocate_buckets(__bucket_type* __bkts, size_type __n)
882 typedef typename _Bucket_alloc_traits::pointer _Ptr;
884 _Bucket_alloc_type __alloc(_M_node_allocator());
885 _Bucket_alloc_traits::deallocate(__alloc, __ptr, __n);
888 template<
typename _Key,
typename _Value,
889 typename _Alloc,
typename _ExtractKey,
typename _Equal,
890 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
892 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
893 _Equal, _H1, _H2, _Hash, _RehashPolicy,
894 _Traits>::__node_type*
895 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
896 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
897 _M_bucket_begin(size_type __bkt)
const
899 __node_base* __n = _M_buckets[__bkt];
900 return __n ?
static_cast<__node_type*
>(__n->_M_nxt) :
nullptr;
903 template<
typename _Key,
typename _Value,
904 typename _Alloc,
typename _ExtractKey,
typename _Equal,
905 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
907 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
908 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
909 _Hashtable(size_type __bucket_hint,
910 const _H1& __h1,
const _H2& __h2,
const _Hash& __h,
911 const _Equal& __eq,
const _ExtractKey& __exk,
912 const allocator_type& __a)
913 : __hashtable_base(__exk, __h1, __h2, __h, __eq),
920 _M_bucket_count = _M_rehash_policy._M_next_bkt(__bucket_hint);
921 _M_buckets = _M_allocate_buckets(_M_bucket_count);
924 template<
typename _Key,
typename _Value,
925 typename _Alloc,
typename _ExtractKey,
typename _Equal,
926 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
928 template<
typename _InputIterator>
929 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
930 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
931 _Hashtable(_InputIterator __f, _InputIterator __l,
932 size_type __bucket_hint,
933 const _H1& __h1,
const _H2& __h2,
const _Hash& __h,
934 const _Equal& __eq,
const _ExtractKey& __exk,
935 const allocator_type& __a)
936 : __hashtable_base(__exk, __h1, __h2, __h, __eq),
943 auto __nb_elems = __detail::__distance_fw(__f, __l);
945 _M_rehash_policy._M_next_bkt(
946 std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems),
949 _M_buckets = _M_allocate_buckets(_M_bucket_count);
952 for (; __f != __l; ++__f)
958 _M_deallocate_buckets();
959 __throw_exception_again;
963 template<
typename _Key,
typename _Value,
964 typename _Alloc,
typename _ExtractKey,
typename _Equal,
965 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
967 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
968 _H1, _H2, _Hash, _RehashPolicy, _Traits>&
969 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
970 _H1, _H2, _Hash, _RehashPolicy, _Traits>::operator=(
971 const _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
972 _H1, _H2, _Hash, _RehashPolicy, _Traits>& __ht)
977 if (_Node_alloc_traits::_S_propagate_on_copy_assign())
979 auto& __this_alloc = this->_M_node_allocator();
980 auto& __that_alloc = __ht._M_node_allocator();
981 if (!_Node_alloc_traits::_S_always_equal()
982 && __this_alloc != __that_alloc)
985 _M_deallocate_nodes(_M_begin());
986 if (__builtin_expect(_M_bucket_count != 0,
true))
987 _M_deallocate_buckets();
989 std::__alloc_on_copy(__this_alloc, __that_alloc);
990 __hashtable_base::operator=(__ht);
991 _M_bucket_count = __ht._M_bucket_count;
992 _M_element_count = __ht._M_element_count;
993 _M_rehash_policy = __ht._M_rehash_policy;
997 [
this](
const __node_type* __n)
998 {
return _M_allocate_node(__n->_M_v()); });
1005 __throw_exception_again;
1009 std::__alloc_on_copy(__this_alloc, __that_alloc);
1013 __bucket_type* __former_buckets =
nullptr;
1014 std::size_t __former_bucket_count = _M_bucket_count;
1015 const __rehash_state& __former_state = _M_rehash_policy._M_state();
1017 if (_M_bucket_count != __ht._M_bucket_count)
1019 __former_buckets = _M_buckets;
1020 _M_buckets = _M_allocate_buckets(__ht._M_bucket_count);
1021 _M_bucket_count = __ht._M_bucket_count;
1024 __builtin_memset(_M_buckets, 0,
1025 _M_bucket_count *
sizeof(__bucket_type));
1029 __hashtable_base::operator=(__ht);
1030 _M_element_count = __ht._M_element_count;
1031 _M_rehash_policy = __ht._M_rehash_policy;
1032 __detail::_ReuseOrAllocNode<_Key, _Value, _Alloc, _ExtractKey,
1033 _Equal, _H1, _H2, _Hash,
1034 _RehashPolicy, _Traits>
1035 __roan(_M_begin(), *
this);
1036 _M_before_begin()._M_nxt =
nullptr;
1037 _M_assign(__ht, __roan);
1038 if (__former_buckets)
1039 _M_deallocate_buckets(__former_buckets, __former_bucket_count);
1043 if (__former_buckets)
1046 _M_deallocate_buckets();
1047 _M_rehash_policy._M_reset(__former_state);
1048 _M_buckets = __former_buckets;
1049 _M_bucket_count = __former_bucket_count;
1051 __builtin_memset(_M_buckets, 0,
1052 _M_bucket_count *
sizeof(__bucket_type));
1053 __throw_exception_again;
1058 template<
typename _Key,
typename _Value,
1059 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1060 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1062 template<
typename _UnaryOp>
1064 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1065 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1066 _M_assign(
const _Hashtable& __ht,
const _UnaryOp& __node_getter)
1068 __bucket_type* __buckets =
nullptr;
1070 _M_buckets = __buckets = _M_allocate_buckets(_M_bucket_count);
1074 if (!__ht._M_before_begin()._M_nxt)
1079 __node_type* __ht_n = __ht._M_begin();
1080 __node_type* __this_n = __node_getter(__ht_n);
1081 this->_M_copy_code(__this_n, __ht_n);
1082 _M_before_begin()._M_nxt = __this_n;
1083 _M_buckets[_M_bucket_index(__this_n)] = &_M_before_begin();
1086 __node_base* __prev_n = __this_n;
1087 for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next())
1089 __this_n = __node_getter(__ht_n);
1090 __prev_n->_M_nxt = __this_n;
1091 this->_M_copy_code(__this_n, __ht_n);
1092 size_type __bkt = _M_bucket_index(__this_n);
1093 if (!_M_buckets[__bkt])
1094 _M_buckets[__bkt] = __prev_n;
1095 __prev_n = __this_n;
1102 _M_deallocate_buckets();
1103 __throw_exception_again;
1107 template<
typename _Key,
typename _Value,
1108 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1109 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1112 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1113 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1116 _M_rehash_policy._M_reset();
1117 _M_bucket_count = 0;
1118 _M_buckets =
nullptr;
1119 _M_before_begin()._M_nxt =
nullptr;
1120 _M_element_count = 0;
1123 template<
typename _Key,
typename _Value,
1124 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1125 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1128 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1129 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1132 _M_deallocate_nodes(_M_begin());
1133 if (__builtin_expect(_M_bucket_count != 0,
true))
1134 _M_deallocate_buckets();
1136 __hashtable_base::operator=(std::move(__ht));
1137 _M_rehash_policy = __ht._M_rehash_policy;
1138 _M_buckets = __ht._M_buckets;
1139 _M_bucket_count = __ht._M_bucket_count;
1140 _M_before_begin()._M_nxt = __ht._M_before_begin()._M_nxt;
1141 _M_element_count = __ht._M_element_count;
1142 std::__alloc_on_move(_M_node_allocator(), __ht._M_node_allocator());
1147 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin();
1151 template<
typename _Key,
typename _Value,
1152 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1153 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1156 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1157 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1160 if (__ht._M_node_allocator() == _M_node_allocator())
1165 __bucket_type* __former_buckets =
nullptr;
1166 size_type __former_bucket_count = _M_bucket_count;
1167 const __rehash_state& __former_state = _M_rehash_policy._M_state();
1169 if (_M_bucket_count != __ht._M_bucket_count)
1171 __former_buckets = _M_buckets;
1172 _M_buckets = _M_allocate_buckets(__ht._M_bucket_count);
1173 _M_bucket_count = __ht._M_bucket_count;
1176 __builtin_memset(_M_buckets, 0,
1177 _M_bucket_count *
sizeof(__bucket_type));
1181 __hashtable_base::operator=(std::move(__ht));
1182 _M_element_count = __ht._M_element_count;
1183 _M_rehash_policy = __ht._M_rehash_policy;
1184 __detail::_MoveReuseOrAllocNode<_Key, _Value, _Alloc, _ExtractKey,
1185 _Equal, _H1, _H2, _Hash,
1186 _RehashPolicy, _Traits>
1187 __mroan(_M_begin(), *
this);
1188 _M_before_begin()._M_nxt =
nullptr;
1189 _M_assign(__ht, __mroan);
1194 if (__former_buckets)
1196 _M_deallocate_buckets();
1197 _M_rehash_policy._M_reset(__former_state);
1198 _M_buckets = __former_buckets;
1199 _M_bucket_count = __former_bucket_count;
1201 __builtin_memset(_M_buckets, 0,
1202 _M_bucket_count *
sizeof(__bucket_type));
1203 __throw_exception_again;
1208 template<
typename _Key,
typename _Value,
1209 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1210 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1212 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1213 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1214 _Hashtable(
const _Hashtable& __ht)
1215 : __hashtable_base(__ht),
1217 __rehash_base(__ht),
1219 _M_bucket_count(__ht._M_bucket_count),
1220 _M_bbegin(_Node_alloc_traits::_S_select_on_copy(
1221 __ht._M_node_allocator())),
1222 _M_element_count(__ht._M_element_count),
1223 _M_rehash_policy(__ht._M_rehash_policy)
1226 [
this](
const __node_type* __n)
1227 {
return _M_allocate_node(__n->_M_v()); });
1230 template<
typename _Key,
typename _Value,
1231 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1232 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1234 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1235 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1236 _Hashtable(_Hashtable&& __ht) noexcept
1237 : __hashtable_base(__ht),
1239 __rehash_base(__ht),
1240 _M_buckets(__ht._M_buckets),
1241 _M_bucket_count(__ht._M_bucket_count),
1242 _M_bbegin(std::move(__ht._M_bbegin)),
1243 _M_element_count(__ht._M_element_count),
1244 _M_rehash_policy(__ht._M_rehash_policy)
1249 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin();
1253 template<
typename _Key,
typename _Value,
1254 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1255 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1257 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1258 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1259 _Hashtable(
const _Hashtable& __ht,
const allocator_type& __a)
1260 : __hashtable_base(__ht),
1262 __rehash_base(__ht),
1264 _M_bucket_count(__ht._M_bucket_count),
1265 _M_bbegin(_Node_alloc_type(__a)),
1266 _M_element_count(__ht._M_element_count),
1267 _M_rehash_policy(__ht._M_rehash_policy)
1270 [
this](
const __node_type* __n)
1271 {
return _M_allocate_node(__n->_M_v()); });
1274 template<
typename _Key,
typename _Value,
1275 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1276 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1278 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1279 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1280 _Hashtable(_Hashtable&& __ht,
const allocator_type& __a)
1281 : __hashtable_base(__ht),
1283 __rehash_base(__ht),
1285 _M_bucket_count(__ht._M_bucket_count),
1286 _M_bbegin(_Node_alloc_type(__a)),
1287 _M_element_count(__ht._M_element_count),
1288 _M_rehash_policy(__ht._M_rehash_policy)
1290 if (__ht._M_node_allocator() == _M_node_allocator())
1292 _M_buckets = __ht._M_buckets;
1293 _M_before_begin()._M_nxt = __ht._M_before_begin()._M_nxt;
1297 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin();
1303 [
this](__node_type* __n)
1305 return _M_allocate_node(
1312 template<
typename _Key,
typename _Value,
1313 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1314 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1316 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1317 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1318 ~_Hashtable() noexcept
1322 _M_deallocate_buckets();
1325 template<
typename _Key,
typename _Value,
1326 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1327 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1330 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1331 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1332 swap(_Hashtable& __x)
1333 noexcept(_Node_alloc_traits::_S_nothrow_swap())
1340 std::__alloc_on_swap(_M_node_allocator(), __x._M_node_allocator());
1341 std::swap(_M_rehash_policy, __x._M_rehash_policy);
1342 std::swap(_M_buckets, __x._M_buckets);
1343 std::swap(_M_bucket_count, __x._M_bucket_count);
1344 std::swap(_M_before_begin()._M_nxt, __x._M_before_begin()._M_nxt);
1345 std::swap(_M_element_count, __x._M_element_count);
1350 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin();
1352 __x._M_buckets[__x._M_bucket_index(__x._M_begin())]
1353 = &(__x._M_before_begin());
1356 template<
typename _Key,
typename _Value,
1357 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1358 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1361 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1362 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1363 __rehash_policy(
const _RehashPolicy& __pol)
1365 size_type __n_bkt = __pol._M_bkt_for_elements(_M_element_count);
1366 __n_bkt = __pol._M_next_bkt(__n_bkt);
1367 if (__n_bkt != _M_bucket_count)
1368 _M_rehash(__n_bkt, _M_rehash_policy._M_state());
1369 _M_rehash_policy = __pol;
1372 template<
typename _Key,
typename _Value,
1373 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1374 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1376 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1377 _H1, _H2, _Hash, _RehashPolicy,
1379 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1380 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1381 find(
const key_type& __k)
1383 if (__builtin_expect(_M_bucket_count == 0,
false))
1386 __hash_code __code = this->_M_hash_code(__k);
1387 std::size_t __n = _M_bucket_index(__k, __code);
1388 __node_type* __p = _M_find_node(__n, __k, __code);
1389 return __p ? iterator(__p) :
end();
1392 template<
typename _Key,
typename _Value,
1393 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1394 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1396 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1397 _H1, _H2, _Hash, _RehashPolicy,
1398 _Traits>::const_iterator
1399 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1400 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1401 find(
const key_type& __k)
const
1403 if (__builtin_expect(_M_bucket_count == 0,
false))
1406 __hash_code __code = this->_M_hash_code(__k);
1407 std::size_t __n = _M_bucket_index(__k, __code);
1408 __node_type* __p = _M_find_node(__n, __k, __code);
1409 return __p ? const_iterator(__p) :
end();
1412 template<
typename _Key,
typename _Value,
1413 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1414 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1416 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1417 _H1, _H2, _Hash, _RehashPolicy,
1419 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1420 _H1, _H2, _Hash, _RehashPolicy, _Traits>
::
1421 count(
const key_type& __k)
const
1423 if (__builtin_expect(_M_bucket_count == 0,
false))
1426 __hash_code __code = this->_M_hash_code(__k);
1427 std::size_t __n = _M_bucket_index(__k, __code);
1428 __node_type* __p = _M_bucket_begin(__n);
1432 std::size_t __result = 0;
1433 for (;; __p = __p->_M_next())
1435 if (this->_M_equals(__k, __code, __p))
1442 if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
1448 template<
typename _Key,
typename _Value,
1449 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1450 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1452 std::pair<
typename _Hashtable<_Key, _Value, _Alloc,
1453 _ExtractKey, _Equal, _H1,
1454 _H2, _Hash, _RehashPolicy,
1456 typename _Hashtable<_Key, _Value, _Alloc,
1457 _ExtractKey, _Equal, _H1,
1458 _H2, _Hash, _RehashPolicy,
1460 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1461 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1462 equal_range(
const key_type& __k)
1464 if (__builtin_expect(_M_bucket_count == 0,
false))
1467 __hash_code __code = this->_M_hash_code(__k);
1468 std::size_t __n = _M_bucket_index(__k, __code);
1469 __node_type* __p = _M_find_node(__n, __k, __code);
1473 __node_type* __p1 = __p->_M_next();
1474 while (__p1 && _M_bucket_index(__p1) == __n
1475 && this->_M_equals(__k, __code, __p1))
1476 __p1 = __p1->_M_next();
1484 template<
typename _Key,
typename _Value,
1485 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1486 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1488 std::pair<
typename _Hashtable<_Key, _Value, _Alloc,
1489 _ExtractKey, _Equal, _H1,
1490 _H2, _Hash, _RehashPolicy,
1491 _Traits>::const_iterator,
1492 typename _Hashtable<_Key, _Value, _Alloc,
1493 _ExtractKey, _Equal, _H1,
1494 _H2, _Hash, _RehashPolicy,
1495 _Traits>::const_iterator>
1496 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1497 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1498 equal_range(
const key_type& __k)
const
1500 if (__builtin_expect(_M_bucket_count == 0,
false))
1503 __hash_code __code = this->_M_hash_code(__k);
1504 std::size_t __n = _M_bucket_index(__k, __code);
1505 __node_type* __p = _M_find_node(__n, __k, __code);
1509 __node_type* __p1 = __p->_M_next();
1510 while (__p1 && _M_bucket_index(__p1) == __n
1511 && this->_M_equals(__k, __code, __p1))
1512 __p1 = __p1->_M_next();
1514 return std::make_pair(const_iterator(__p), const_iterator(__p1));
1522 template<
typename _Key,
typename _Value,
1523 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1524 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1526 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
1527 _Equal, _H1, _H2, _Hash, _RehashPolicy,
1528 _Traits>::__node_base*
1529 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1530 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1531 _M_find_before_node(size_type __n,
const key_type& __k,
1532 __hash_code __code)
const
1534 __node_base* __prev_p = _M_buckets[__n];
1537 __node_type* __p =
static_cast<__node_type*
>(__prev_p->_M_nxt);
1538 for (;; __p = __p->_M_next())
1540 if (this->_M_equals(__k, __code, __p))
1542 if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
1549 template<
typename _Key,
typename _Value,
1550 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1551 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1554 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1555 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1556 _M_insert_bucket_begin(size_type __bkt, __node_type* __node)
1558 if (_M_buckets[__bkt])
1562 __node->_M_nxt = _M_buckets[__bkt]->_M_nxt;
1563 _M_buckets[__bkt]->_M_nxt = __node;
1570 __node->_M_nxt = _M_before_begin()._M_nxt;
1571 _M_before_begin()._M_nxt = __node;
1575 _M_buckets[_M_bucket_index(__node->_M_next())] = __node;
1576 _M_buckets[__bkt] = &_M_before_begin();
1580 template<
typename _Key,
typename _Value,
1581 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1582 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1585 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1586 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1587 _M_remove_bucket_begin(size_type __bkt, __node_type* __next,
1588 size_type __next_bkt)
1590 if (!__next || __next_bkt != __bkt)
1595 _M_buckets[__next_bkt] = _M_buckets[__bkt];
1598 if (&_M_before_begin() == _M_buckets[__bkt])
1599 _M_before_begin()._M_nxt = __next;
1600 _M_buckets[__bkt] =
nullptr;
1604 template<
typename _Key,
typename _Value,
1605 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1606 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1608 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
1609 _Equal, _H1, _H2, _Hash, _RehashPolicy,
1610 _Traits>::__node_base*
1611 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1612 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1613 _M_get_previous_node(size_type __bkt, __node_base* __n)
1615 __node_base* __prev_n = _M_buckets[__bkt];
1616 while (__prev_n->_M_nxt != __n)
1617 __prev_n = __prev_n->_M_nxt;
1621 template<
typename _Key,
typename _Value,
1622 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1623 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1625 template<
typename... _Args>
1626 std::pair<
typename _Hashtable<_Key, _Value, _Alloc,
1627 _ExtractKey, _Equal, _H1,
1628 _H2, _Hash, _RehashPolicy,
1629 _Traits>::iterator,
bool>
1630 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1631 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1635 __node_type* __node = _M_allocate_node(std::forward<_Args>(__args)...);
1636 const key_type& __k = this->_M_extract()(__node->_M_v());
1640 __code = this->_M_hash_code(__k);
1644 _M_deallocate_node(__node);
1645 __throw_exception_again;
1648 size_type __bkt = _M_bucket_index(__k, __code);
1649 if (__node_type* __p = _M_find_node(__bkt, __k, __code))
1652 _M_deallocate_node(__node);
1657 return std::make_pair(_M_insert_unique_node(__bkt, __code, __node),
1661 template<
typename _Key,
typename _Value,
1662 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1663 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1665 template<
typename... _Args>
1666 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1667 _H1, _H2, _Hash, _RehashPolicy,
1669 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1670 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1674 __node_type* __node = _M_allocate_node(std::forward<_Args>(__args)...);
1679 __code = this->_M_hash_code(this->_M_extract()(__node->_M_v()));
1683 _M_deallocate_node(__node);
1684 __throw_exception_again;
1687 return _M_insert_multi_node(__hint._M_cur, __code, __node);
1690 template<
typename _Key,
typename _Value,
1691 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1692 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1694 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1695 _H1, _H2, _Hash, _RehashPolicy,
1697 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1698 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1699 _M_insert_unique_node(size_type __bkt, __hash_code __code,
1700 __node_type* __node)
1702 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
1704 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
1708 if (__do_rehash.
first)
1710 _M_rehash(__do_rehash.
second, __saved_state);
1711 __bkt = _M_bucket_index(this->_M_extract()(__node->_M_v()), __code);
1714 this->_M_store_code(__node, __code);
1717 _M_insert_bucket_begin(__bkt, __node);
1719 return iterator(__node);
1723 _M_deallocate_node(__node);
1724 __throw_exception_again;
1730 template<
typename _Key,
typename _Value,
1731 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1732 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1734 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1735 _H1, _H2, _Hash, _RehashPolicy,
1737 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1738 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1739 _M_insert_multi_node(__node_type* __hint, __hash_code __code,
1740 __node_type* __node)
1742 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
1744 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
1748 if (__do_rehash.
first)
1749 _M_rehash(__do_rehash.
second, __saved_state);
1751 this->_M_store_code(__node, __code);
1752 const key_type& __k = this->_M_extract()(__node->_M_v());
1753 size_type __bkt = _M_bucket_index(__k, __code);
1758 = __builtin_expect(__hint !=
nullptr,
false)
1759 && this->_M_equals(__k, __code, __hint)
1761 : _M_find_before_node(__bkt, __k, __code);
1765 __node->_M_nxt = __prev->_M_nxt;
1766 __prev->_M_nxt = __node;
1767 if (__builtin_expect(__prev == __hint,
false))
1771 && !this->_M_equals(__k, __code, __node->_M_next()))
1773 size_type __next_bkt = _M_bucket_index(__node->_M_next());
1774 if (__next_bkt != __bkt)
1775 _M_buckets[__next_bkt] = __node;
1783 _M_insert_bucket_begin(__bkt, __node);
1785 return iterator(__node);
1789 _M_deallocate_node(__node);
1790 __throw_exception_again;
1795 template<
typename _Key,
typename _Value,
1796 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1797 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1799 template<
typename _Arg>
1800 std::pair<
typename _Hashtable<_Key, _Value, _Alloc,
1801 _ExtractKey, _Equal, _H1,
1802 _H2, _Hash, _RehashPolicy,
1803 _Traits>::iterator,
bool>
1804 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1805 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1808 const key_type& __k = this->_M_extract()(__v);
1809 __hash_code __code = this->_M_hash_code(__k);
1810 size_type __bkt = _M_bucket_index(__k, __code);
1812 __node_type* __n = _M_find_node(__bkt, __k, __code);
1816 __n = _M_allocate_node(std::forward<_Arg>(__v));
1817 return std::make_pair(_M_insert_unique_node(__bkt, __code, __n),
true);
1821 template<
typename _Key,
typename _Value,
1822 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1823 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1825 template<
typename _Arg>
1826 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1827 _H1, _H2, _Hash, _RehashPolicy,
1829 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1830 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1835 __hash_code __code = this->_M_hash_code(this->_M_extract()(__v));
1838 __node_type* __node = _M_allocate_node(std::forward<_Arg>(__v));
1840 return _M_insert_multi_node(__hint._M_cur, __code, __node);
1843 template<
typename _Key,
typename _Value,
1844 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1845 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1847 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1848 _H1, _H2, _Hash, _RehashPolicy,
1850 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1851 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1852 erase(const_iterator __it)
1854 __node_type* __n = __it._M_cur;
1855 std::size_t __bkt = _M_bucket_index(__n);
1860 __node_base* __prev_n = _M_get_previous_node(__bkt, __n);
1861 return _M_erase(__bkt, __prev_n, __n);
1864 template<
typename _Key,
typename _Value,
1865 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1866 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1868 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1869 _H1, _H2, _Hash, _RehashPolicy,
1871 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1872 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1873 _M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n)
1875 if (__prev_n == _M_buckets[__bkt])
1876 _M_remove_bucket_begin(__bkt, __n->_M_next(),
1877 __n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0);
1878 else if (__n->_M_nxt)
1880 size_type __next_bkt = _M_bucket_index(__n->_M_next());
1881 if (__next_bkt != __bkt)
1882 _M_buckets[__next_bkt] = __prev_n;
1885 __prev_n->_M_nxt = __n->_M_nxt;
1886 iterator __result(__n->_M_next());
1887 _M_deallocate_node(__n);
1893 template<
typename _Key,
typename _Value,
1894 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1895 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1897 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1898 _H1, _H2, _Hash, _RehashPolicy,
1900 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1901 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1904 __hash_code __code = this->_M_hash_code(__k);
1905 std::size_t __bkt = _M_bucket_index(__k, __code);
1908 __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code);
1913 __node_type* __n =
static_cast<__node_type*
>(__prev_n->_M_nxt);
1914 _M_erase(__bkt, __prev_n, __n);
1918 template<
typename _Key,
typename _Value,
1919 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1920 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1922 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1923 _H1, _H2, _Hash, _RehashPolicy,
1925 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1926 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1929 __hash_code __code = this->_M_hash_code(__k);
1930 std::size_t __bkt = _M_bucket_index(__k, __code);
1933 __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code);
1943 __node_type* __n =
static_cast<__node_type*
>(__prev_n->_M_nxt);
1944 __node_type* __n_last = __n;
1945 std::size_t __n_last_bkt = __bkt;
1948 __n_last = __n_last->_M_next();
1951 __n_last_bkt = _M_bucket_index(__n_last);
1953 while (__n_last_bkt == __bkt && this->_M_equals(__k, __code, __n_last));
1956 size_type __result = 0;
1959 __node_type* __p = __n->_M_next();
1960 _M_deallocate_node(__n);
1965 while (__n != __n_last);
1967 if (__prev_n == _M_buckets[__bkt])
1968 _M_remove_bucket_begin(__bkt, __n_last, __n_last_bkt);
1969 else if (__n_last && __n_last_bkt != __bkt)
1970 _M_buckets[__n_last_bkt] = __prev_n;
1971 __prev_n->_M_nxt = __n_last;
1975 template<
typename _Key,
typename _Value,
1976 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1977 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1979 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1980 _H1, _H2, _Hash, _RehashPolicy,
1982 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1983 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1984 erase(const_iterator __first, const_iterator __last)
1986 __node_type* __n = __first._M_cur;
1987 __node_type* __last_n = __last._M_cur;
1988 if (__n == __last_n)
1989 return iterator(__n);
1991 std::size_t __bkt = _M_bucket_index(__n);
1993 __node_base* __prev_n = _M_get_previous_node(__bkt, __n);
1994 bool __is_bucket_begin = __n == _M_bucket_begin(__bkt);
1995 std::size_t __n_bkt = __bkt;
2000 __node_type* __tmp = __n;
2001 __n = __n->_M_next();
2002 _M_deallocate_node(__tmp);
2006 __n_bkt = _M_bucket_index(__n);
2008 while (__n != __last_n && __n_bkt == __bkt);
2009 if (__is_bucket_begin)
2010 _M_remove_bucket_begin(__bkt, __n, __n_bkt);
2011 if (__n == __last_n)
2013 __is_bucket_begin =
true;
2017 if (__n && (__n_bkt != __bkt || __is_bucket_begin))
2018 _M_buckets[__n_bkt] = __prev_n;
2019 __prev_n->_M_nxt = __n;
2020 return iterator(__n);
2023 template<
typename _Key,
typename _Value,
2024 typename _Alloc,
typename _ExtractKey,
typename _Equal,
2025 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
2028 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2029 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2032 _M_deallocate_nodes(_M_begin());
2033 __builtin_memset(_M_buckets, 0, _M_bucket_count *
sizeof(__bucket_type));
2034 _M_element_count = 0;
2035 _M_before_begin()._M_nxt =
nullptr;
2038 template<
typename _Key,
typename _Value,
2039 typename _Alloc,
typename _ExtractKey,
typename _Equal,
2040 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
2043 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2044 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2045 rehash(size_type __n)
2047 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
2048 std::size_t __buckets
2049 =
std::max(_M_rehash_policy._M_bkt_for_elements(_M_element_count + 1),
2051 __buckets = _M_rehash_policy._M_next_bkt(__buckets);
2053 if (__buckets != _M_bucket_count)
2054 _M_rehash(__buckets, __saved_state);
2057 _M_rehash_policy._M_reset(__saved_state);
2060 template<
typename _Key,
typename _Value,
2061 typename _Alloc,
typename _ExtractKey,
typename _Equal,
2062 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
2065 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2066 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2067 _M_rehash(size_type __n,
const __rehash_state& __state)
2071 _M_rehash_aux(__n, __unique_keys());
2077 _M_rehash_policy._M_reset(__state);
2078 __throw_exception_again;
2083 template<
typename _Key,
typename _Value,
2084 typename _Alloc,
typename _ExtractKey,
typename _Equal,
2085 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
2088 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2089 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2092 __bucket_type* __new_buckets = _M_allocate_buckets(__n);
2093 __node_type* __p = _M_begin();
2094 _M_before_begin()._M_nxt =
nullptr;
2095 std::size_t __bbegin_bkt = 0;
2098 __node_type* __next = __p->_M_next();
2099 std::size_t __bkt = __hash_code_base::_M_bucket_index(__p, __n);
2100 if (!__new_buckets[__bkt])
2102 __p->_M_nxt = _M_before_begin()._M_nxt;
2103 _M_before_begin()._M_nxt = __p;
2104 __new_buckets[__bkt] = &_M_before_begin();
2106 __new_buckets[__bbegin_bkt] = __p;
2107 __bbegin_bkt = __bkt;
2111 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2112 __new_buckets[__bkt]->_M_nxt = __p;
2117 if (__builtin_expect(_M_bucket_count != 0,
true))
2118 _M_deallocate_buckets();
2119 _M_bucket_count = __n;
2120 _M_buckets = __new_buckets;
2125 template<
typename _Key,
typename _Value,
2126 typename _Alloc,
typename _ExtractKey,
typename _Equal,
2127 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
2130 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2131 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2134 __bucket_type* __new_buckets = _M_allocate_buckets(__n);
2136 __node_type* __p = _M_begin();
2137 _M_before_begin()._M_nxt =
nullptr;
2138 std::size_t __bbegin_bkt = 0;
2139 std::size_t __prev_bkt = 0;
2140 __node_type* __prev_p =
nullptr;
2141 bool __check_bucket =
false;
2145 __node_type* __next = __p->_M_next();
2146 std::size_t __bkt = __hash_code_base::_M_bucket_index(__p, __n);
2148 if (__prev_p && __prev_bkt == __bkt)
2153 __p->_M_nxt = __prev_p->_M_nxt;
2154 __prev_p->_M_nxt = __p;
2161 __check_bucket =
true;
2169 if (__prev_p->_M_nxt)
2171 std::size_t __next_bkt
2172 = __hash_code_base::_M_bucket_index(__prev_p->_M_next(),
2174 if (__next_bkt != __prev_bkt)
2175 __new_buckets[__next_bkt] = __prev_p;
2177 __check_bucket =
false;
2180 if (!__new_buckets[__bkt])
2182 __p->_M_nxt = _M_before_begin()._M_nxt;
2183 _M_before_begin()._M_nxt = __p;
2184 __new_buckets[__bkt] = &_M_before_begin();
2186 __new_buckets[__bbegin_bkt] = __p;
2187 __bbegin_bkt = __bkt;
2191 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2192 __new_buckets[__bkt]->_M_nxt = __p;
2200 if (__check_bucket && __prev_p->_M_nxt)
2202 std::size_t __next_bkt
2203 = __hash_code_base::_M_bucket_index(__prev_p->_M_next(), __n);
2204 if (__next_bkt != __prev_bkt)
2205 __new_buckets[__next_bkt] = __prev_p;
2208 if (__builtin_expect(_M_bucket_count != 0,
true))
2209 _M_deallocate_buckets();
2210 _M_bucket_count = __n;
2211 _M_buckets = __new_buckets;
2214 _GLIBCXX_END_NAMESPACE_VERSION
2217 #endif // _HASHTABLE_H