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>;
242 using __reuse_or_alloc_node_type =
243 __detail::_ReuseOrAllocNode<_Key, _Value, _Alloc,
244 _ExtractKey, _Equal, _H1, _H2, _Hash,
245 _RehashPolicy, _Traits>;
248 template<
typename _Cond>
249 using __if_hash_cached = __or_<__not_<__hash_cached>, _Cond>;
251 template<
typename _Cond>
252 using __if_hash_not_cached = __or_<__hash_cached, _Cond>;
258 static_assert(noexcept(declval<const _Hashtable&>()
259 ._M_bucket_index((
const __node_type*)
nullptr,
261 "Cache the hash code or qualify your functors involved"
262 " in hash code and bucket index computation with noexcept");
269 static_assert(__if_hash_cached<is_default_constructible<_H2>>::value,
270 "Functor used to map hash code to bucket index"
271 " must be default constructible");
276 static_assert(__if_hash_not_cached<
277 is_default_constructible<
281 "Cache the hash code or make functors involved in hash code"
282 " and bucket index computation default constructible");
287 static_assert(__if_hash_not_cached<
288 is_copy_assignable<__hash_code_base>>::value,
289 "Cache the hash code or make functors involved in hash code"
290 " and bucket index computation copy assignable");
292 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
293 typename _ExtractKeya,
typename _Equala,
294 typename _H1a,
typename _H2a,
typename _Hasha,
295 typename _RehashPolicya,
typename _Traitsa,
299 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
300 typename _ExtractKeya,
typename _Equala,
301 typename _H1a,
typename _H2a,
typename _Hasha,
302 typename _RehashPolicya,
typename _Traitsa>
305 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
306 typename _ExtractKeya,
typename _Equala,
307 typename _H1a,
typename _H2a,
typename _Hasha,
308 typename _RehashPolicya,
typename _Traitsa,
309 bool _Constant_iteratorsa,
bool _Unique_keysa>
312 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
313 typename _ExtractKeya,
typename _Equala,
314 typename _H1a,
typename _H2a,
typename _Hasha,
315 typename _RehashPolicya,
typename _Traitsa>
316 friend struct __detail::_ReuseOrAllocNode;
318 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
319 typename _ExtractKeya,
typename _Equala,
320 typename _H1a,
typename _H2a,
typename _Hasha,
321 typename _RehashPolicya,
typename _Traitsa>
322 friend struct __detail::_AllocNode;
325 using size_type =
typename __hashtable_base::size_type;
326 using difference_type =
typename __hashtable_base::difference_type;
336 typedef typename _Alloc_traits::template rebind_alloc<__node_type>
342 typename _Alloc_traits::template rebind_alloc<__bucket_type>
348 __bucket_type* _M_buckets;
349 size_type _M_bucket_count;
351 size_type _M_element_count;
352 _RehashPolicy _M_rehash_policy;
356 {
return _M_bbegin; }
358 const _Node_alloc_type&
359 _M_node_allocator()
const
360 {
return _M_bbegin; }
364 {
return _M_bbegin._M_node; }
367 _M_before_begin()
const
368 {
return _M_bbegin._M_node; }
370 template<
typename... _Args>
372 _M_allocate_node(_Args&&... __args);
375 _M_deallocate_node(__node_type* __n);
379 _M_deallocate_nodes(__node_type* __n);
382 _M_allocate_buckets(size_type __n);
385 _M_deallocate_buckets(__bucket_type*, size_type __n);
388 _M_deallocate_buckets()
389 { _M_deallocate_buckets(_M_buckets, _M_bucket_count); }
394 _M_bucket_begin(size_type __bkt)
const;
398 {
return static_cast<__node_type*
>(_M_before_begin()._M_nxt); }
400 template<
typename _NodeGenerator>
402 _M_assign(
const _Hashtable&,
const _NodeGenerator&);
416 const _H1&,
const _H2&,
const _Hash&,
417 const _Equal&,
const _ExtractKey&,
418 const allocator_type&);
420 template<
typename _InputIterator>
421 _Hashtable(_InputIterator __first, _InputIterator __last,
422 size_type __bucket_hint,
423 const _H1&,
const _H2&,
const _Hash&,
424 const _Equal&,
const _ExtractKey&,
425 const allocator_type&);
440 __key_extract(), __a)
445 const _H1& __hf = _H1(),
446 const key_equal& __eql = key_equal(),
447 const allocator_type& __a = allocator_type())
450 __key_extract(), __a)
453 template<
typename _InputIterator>
454 _Hashtable(_InputIterator __f, _InputIterator __l,
456 const _H1& __hf = _H1(),
457 const key_equal& __eql = key_equal(),
458 const allocator_type& __a = allocator_type())
461 __key_extract(), __a)
466 const _H1& __hf = _H1(),
467 const key_equal& __eql = key_equal(),
468 const allocator_type& __a = allocator_type())
469 :
_Hashtable(__l.begin(), __l.end(), __n, __hf,
472 __key_extract(), __a)
480 noexcept(_Node_alloc_traits::_S_nothrow_move())
482 constexpr
bool __move_storage =
483 _Node_alloc_traits::_S_propagate_on_move_assign()
484 || _Node_alloc_traits::_S_always_equal();
485 _M_move_assign(std::move(__ht),
493 __reuse_or_alloc_node_type __roan(_M_begin(), *
this);
494 _M_before_begin()._M_nxt =
nullptr;
496 this->_M_insert_range(__l.begin(), __l.end(), __roan);
504 noexcept(_Node_alloc_traits::_S_nothrow_swap());
509 {
return iterator(_M_begin()); }
512 begin()
const noexcept
513 {
return const_iterator(_M_begin()); }
517 {
return iterator(
nullptr); }
521 {
return const_iterator(
nullptr); }
524 cbegin()
const noexcept
525 {
return const_iterator(_M_begin()); }
528 cend()
const noexcept
529 {
return const_iterator(
nullptr); }
532 size()
const noexcept
533 {
return _M_element_count; }
536 empty()
const noexcept
537 {
return size() == 0; }
540 get_allocator()
const noexcept
541 {
return allocator_type(_M_node_allocator()); }
544 max_size()
const noexcept
550 {
return this->_M_eq(); }
556 bucket_count()
const noexcept
557 {
return _M_bucket_count; }
560 max_bucket_count()
const noexcept
561 {
return max_size(); }
564 bucket_size(size_type __n)
const
568 bucket(
const key_type& __k)
const
569 {
return _M_bucket_index(__k, this->_M_hash_code(__k)); }
574 return local_iterator(*
this, _M_bucket_begin(__n),
575 __n, _M_bucket_count);
580 {
return local_iterator(*
this,
nullptr, __n, _M_bucket_count); }
583 begin(size_type __n)
const
585 return const_local_iterator(*
this, _M_bucket_begin(__n),
586 __n, _M_bucket_count);
590 end(size_type __n)
const
591 {
return const_local_iterator(*
this,
nullptr, __n, _M_bucket_count); }
595 cbegin(size_type __n)
const
597 return const_local_iterator(*
this, _M_bucket_begin(__n),
598 __n, _M_bucket_count);
602 cend(size_type __n)
const
603 {
return const_local_iterator(*
this,
nullptr, __n, _M_bucket_count); }
606 load_factor()
const noexcept
608 return static_cast<float>(
size()) / static_cast<float>(bucket_count());
617 __rehash_policy()
const
618 {
return _M_rehash_policy; }
621 __rehash_policy(
const _RehashPolicy&);
625 find(
const key_type& __k);
628 find(
const key_type& __k)
const;
631 count(
const key_type& __k)
const;
634 equal_range(
const key_type& __k);
637 equal_range(
const key_type& __k)
const;
642 _M_bucket_index(__node_type* __n)
const noexcept
643 {
return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); }
646 _M_bucket_index(
const key_type& __k, __hash_code __c)
const
647 {
return __hash_code_base::_M_bucket_index(__k, __c, _M_bucket_count); }
652 _M_find_before_node(size_type,
const key_type&, __hash_code)
const;
655 _M_find_node(size_type __bkt,
const key_type& __key,
656 __hash_code __c)
const
658 __node_base* __before_n = _M_find_before_node(__bkt, __key, __c);
660 return static_cast<__node_type*
>(__before_n->_M_nxt);
666 _M_insert_bucket_begin(size_type, __node_type*);
670 _M_remove_bucket_begin(size_type __bkt, __node_type* __next_n,
671 size_type __next_bkt);
675 _M_get_previous_node(size_type __bkt, __node_base* __n);
681 _M_insert_unique_node(size_type __bkt, __hash_code __code,
687 _M_insert_multi_node(__node_type* __hint,
688 __hash_code __code, __node_type* __n);
690 template<
typename... _Args>
694 template<
typename... _Args>
697 {
return _M_emplace(cend(), __uk, std::forward<_Args>(__args)...); }
700 template<
typename... _Args>
702 _M_emplace(const_iterator,
std::true_type __uk, _Args&&... __args)
703 {
return _M_emplace(__uk, std::forward<_Args>(__args)...).first; }
705 template<
typename... _Args>
709 template<
typename _Arg,
typename _NodeGenerator>
713 template<
typename _Arg,
typename _NodeGenerator>
715 _M_insert(_Arg&& __arg,
const _NodeGenerator& __node_gen,
718 return _M_insert(cend(), std::forward<_Arg>(__arg), __node_gen,
723 template<
typename _Arg,
typename _NodeGenerator>
725 _M_insert(const_iterator, _Arg&& __arg,
const _NodeGenerator& __node_gen,
729 _M_insert(std::forward<_Arg>(__arg), __node_gen, __uk).
first;
733 template<
typename _Arg,
typename _NodeGenerator>
735 _M_insert(const_iterator, _Arg&&,
const _NodeGenerator&,
std::false_type);
744 _M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n);
748 template<
typename... _Args>
750 emplace(_Args&&... __args)
751 {
return _M_emplace(__unique_keys(), std::forward<_Args>(__args)...); }
753 template<
typename... _Args>
755 emplace_hint(const_iterator __hint, _Args&&... __args)
757 return _M_emplace(__hint, __unique_keys(),
758 std::forward<_Args>(__args)...);
765 erase(const_iterator);
770 {
return erase(const_iterator(__it)); }
773 erase(
const key_type& __k)
775 if (__builtin_expect(_M_bucket_count == 0,
false))
777 return _M_erase(__unique_keys(), __k);
781 erase(const_iterator, const_iterator);
787 void rehash(size_type __n);
801 void _M_rehash(size_type __n,
const __rehash_state& __state);
806 template<
typename _Key,
typename _Value,
807 typename _Alloc,
typename _ExtractKey,
typename _Equal,
808 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
810 template<
typename... _Args>
811 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
812 _H1, _H2, _Hash, _RehashPolicy, _Traits>::__node_type*
813 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
814 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
815 _M_allocate_node(_Args&&... __args)
817 auto __nptr = _Node_alloc_traits::allocate(_M_node_allocator(), 1);
821 _Value_alloc_type __a(_M_node_allocator());
822 ::new ((
void*)__n) __node_type();
823 _Value_alloc_traits::construct(__a, __n->_M_valptr(),
824 std::
forward<_Args>(__args)...);
829 _Node_alloc_traits::deallocate(_M_node_allocator(), __nptr, 1);
830 __throw_exception_again;
834 template<
typename _Key,
typename _Value,
835 typename _Alloc,
typename _ExtractKey,
typename _Equal,
836 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
839 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
840 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
841 _M_deallocate_node(__node_type* __n)
843 typedef typename _Node_alloc_traits::pointer _Ptr;
845 _Value_alloc_type __a(_M_node_allocator());
846 _Value_alloc_traits::destroy(__a, __n->_M_valptr());
848 _Node_alloc_traits::deallocate(_M_node_allocator(), __ptr, 1);
851 template<
typename _Key,
typename _Value,
852 typename _Alloc,
typename _ExtractKey,
typename _Equal,
853 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
856 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
857 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
858 _M_deallocate_nodes(__node_type* __n)
862 __node_type* __tmp = __n;
863 __n = __n->_M_next();
864 _M_deallocate_node(__tmp);
868 template<
typename _Key,
typename _Value,
869 typename _Alloc,
typename _ExtractKey,
typename _Equal,
870 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
872 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
873 _H1, _H2, _Hash, _RehashPolicy, _Traits>::__bucket_type*
874 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
875 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
876 _M_allocate_buckets(size_type __n)
878 _Bucket_alloc_type __alloc(_M_node_allocator());
880 auto __ptr = _Bucket_alloc_traits::allocate(__alloc, __n);
882 __builtin_memset(__p, 0, __n *
sizeof(__bucket_type));
886 template<
typename _Key,
typename _Value,
887 typename _Alloc,
typename _ExtractKey,
typename _Equal,
888 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
891 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
892 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
893 _M_deallocate_buckets(__bucket_type* __bkts, size_type __n)
895 typedef typename _Bucket_alloc_traits::pointer _Ptr;
897 _Bucket_alloc_type __alloc(_M_node_allocator());
898 _Bucket_alloc_traits::deallocate(__alloc, __ptr, __n);
901 template<
typename _Key,
typename _Value,
902 typename _Alloc,
typename _ExtractKey,
typename _Equal,
903 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
905 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
906 _Equal, _H1, _H2, _Hash, _RehashPolicy,
907 _Traits>::__node_type*
908 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
909 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
910 _M_bucket_begin(size_type __bkt)
const
912 __node_base* __n = _M_buckets[__bkt];
913 return __n ?
static_cast<__node_type*
>(__n->_M_nxt) :
nullptr;
916 template<
typename _Key,
typename _Value,
917 typename _Alloc,
typename _ExtractKey,
typename _Equal,
918 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
920 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
921 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
922 _Hashtable(size_type __bucket_hint,
923 const _H1& __h1,
const _H2& __h2,
const _Hash& __h,
924 const _Equal& __eq,
const _ExtractKey& __exk,
925 const allocator_type& __a)
926 : __hashtable_base(__exk, __h1, __h2, __h, __eq),
933 _M_bucket_count = _M_rehash_policy._M_next_bkt(__bucket_hint);
934 _M_buckets = _M_allocate_buckets(_M_bucket_count);
937 template<
typename _Key,
typename _Value,
938 typename _Alloc,
typename _ExtractKey,
typename _Equal,
939 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
941 template<
typename _InputIterator>
942 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
943 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
944 _Hashtable(_InputIterator __f, _InputIterator __l,
945 size_type __bucket_hint,
946 const _H1& __h1,
const _H2& __h2,
const _Hash& __h,
947 const _Equal& __eq,
const _ExtractKey& __exk,
948 const allocator_type& __a)
949 : __hashtable_base(__exk, __h1, __h2, __h, __eq),
956 auto __nb_elems = __detail::__distance_fw(__f, __l);
958 _M_rehash_policy._M_next_bkt(
959 std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems),
962 _M_buckets = _M_allocate_buckets(_M_bucket_count);
965 for (; __f != __l; ++__f)
971 _M_deallocate_buckets();
972 __throw_exception_again;
976 template<
typename _Key,
typename _Value,
977 typename _Alloc,
typename _ExtractKey,
typename _Equal,
978 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
980 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
981 _H1, _H2, _Hash, _RehashPolicy, _Traits>&
982 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
983 _H1, _H2, _Hash, _RehashPolicy, _Traits>::operator=(
984 const _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
985 _H1, _H2, _Hash, _RehashPolicy, _Traits>& __ht)
990 if (_Node_alloc_traits::_S_propagate_on_copy_assign())
992 auto& __this_alloc = this->_M_node_allocator();
993 auto& __that_alloc = __ht._M_node_allocator();
994 if (!_Node_alloc_traits::_S_always_equal()
995 && __this_alloc != __that_alloc)
998 _M_deallocate_nodes(_M_begin());
999 if (__builtin_expect(_M_bucket_count != 0,
true))
1000 _M_deallocate_buckets();
1002 std::__alloc_on_copy(__this_alloc, __that_alloc);
1003 __hashtable_base::operator=(__ht);
1004 _M_bucket_count = __ht._M_bucket_count;
1005 _M_element_count = __ht._M_element_count;
1006 _M_rehash_policy = __ht._M_rehash_policy;
1010 [
this](
const __node_type* __n)
1011 {
return _M_allocate_node(__n->_M_v()); });
1018 __throw_exception_again;
1022 std::__alloc_on_copy(__this_alloc, __that_alloc);
1026 __bucket_type* __former_buckets =
nullptr;
1027 std::size_t __former_bucket_count = _M_bucket_count;
1028 const __rehash_state& __former_state = _M_rehash_policy._M_state();
1030 if (_M_bucket_count != __ht._M_bucket_count)
1032 __former_buckets = _M_buckets;
1033 _M_buckets = _M_allocate_buckets(__ht._M_bucket_count);
1034 _M_bucket_count = __ht._M_bucket_count;
1037 __builtin_memset(_M_buckets, 0,
1038 _M_bucket_count *
sizeof(__bucket_type));
1042 __hashtable_base::operator=(__ht);
1043 _M_element_count = __ht._M_element_count;
1044 _M_rehash_policy = __ht._M_rehash_policy;
1045 __reuse_or_alloc_node_type __roan(_M_begin(), *
this);
1046 _M_before_begin()._M_nxt =
nullptr;
1048 [&__roan](
const __node_type* __n)
1049 {
return __roan(__n->_M_v()); });
1050 if (__former_buckets)
1051 _M_deallocate_buckets(__former_buckets, __former_bucket_count);
1055 if (__former_buckets)
1058 _M_deallocate_buckets();
1059 _M_rehash_policy._M_reset(__former_state);
1060 _M_buckets = __former_buckets;
1061 _M_bucket_count = __former_bucket_count;
1063 __builtin_memset(_M_buckets, 0,
1064 _M_bucket_count *
sizeof(__bucket_type));
1065 __throw_exception_again;
1070 template<
typename _Key,
typename _Value,
1071 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1072 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1074 template<
typename _NodeGenerator>
1076 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1077 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1078 _M_assign(
const _Hashtable& __ht,
const _NodeGenerator& __node_gen)
1080 __bucket_type* __buckets =
nullptr;
1082 _M_buckets = __buckets = _M_allocate_buckets(_M_bucket_count);
1086 if (!__ht._M_before_begin()._M_nxt)
1091 __node_type* __ht_n = __ht._M_begin();
1092 __node_type* __this_n = __node_gen(__ht_n);
1093 this->_M_copy_code(__this_n, __ht_n);
1094 _M_before_begin()._M_nxt = __this_n;
1095 _M_buckets[_M_bucket_index(__this_n)] = &_M_before_begin();
1098 __node_base* __prev_n = __this_n;
1099 for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next())
1101 __this_n = __node_gen(__ht_n);
1102 __prev_n->_M_nxt = __this_n;
1103 this->_M_copy_code(__this_n, __ht_n);
1104 size_type __bkt = _M_bucket_index(__this_n);
1105 if (!_M_buckets[__bkt])
1106 _M_buckets[__bkt] = __prev_n;
1107 __prev_n = __this_n;
1114 _M_deallocate_buckets();
1115 __throw_exception_again;
1119 template<
typename _Key,
typename _Value,
1120 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1121 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1124 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1125 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1128 _M_rehash_policy._M_reset();
1129 _M_bucket_count = 0;
1130 _M_buckets =
nullptr;
1131 _M_before_begin()._M_nxt =
nullptr;
1132 _M_element_count = 0;
1135 template<
typename _Key,
typename _Value,
1136 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1137 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1140 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1141 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1144 _M_deallocate_nodes(_M_begin());
1145 if (__builtin_expect(_M_bucket_count != 0,
true))
1146 _M_deallocate_buckets();
1148 __hashtable_base::operator=(std::move(__ht));
1149 _M_rehash_policy = __ht._M_rehash_policy;
1150 _M_buckets = __ht._M_buckets;
1151 _M_bucket_count = __ht._M_bucket_count;
1152 _M_before_begin()._M_nxt = __ht._M_before_begin()._M_nxt;
1153 _M_element_count = __ht._M_element_count;
1154 std::__alloc_on_move(_M_node_allocator(), __ht._M_node_allocator());
1159 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin();
1163 template<
typename _Key,
typename _Value,
1164 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1165 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1168 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1169 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1172 if (__ht._M_node_allocator() == _M_node_allocator())
1177 __bucket_type* __former_buckets =
nullptr;
1178 size_type __former_bucket_count = _M_bucket_count;
1179 const __rehash_state& __former_state = _M_rehash_policy._M_state();
1181 if (_M_bucket_count != __ht._M_bucket_count)
1183 __former_buckets = _M_buckets;
1184 _M_buckets = _M_allocate_buckets(__ht._M_bucket_count);
1185 _M_bucket_count = __ht._M_bucket_count;
1188 __builtin_memset(_M_buckets, 0,
1189 _M_bucket_count *
sizeof(__bucket_type));
1193 __hashtable_base::operator=(std::move(__ht));
1194 _M_element_count = __ht._M_element_count;
1195 _M_rehash_policy = __ht._M_rehash_policy;
1196 __reuse_or_alloc_node_type __roan(_M_begin(), *
this);
1197 _M_before_begin()._M_nxt =
nullptr;
1199 [&__roan](__node_type* __n)
1205 if (__former_buckets)
1207 _M_deallocate_buckets();
1208 _M_rehash_policy._M_reset(__former_state);
1209 _M_buckets = __former_buckets;
1210 _M_bucket_count = __former_bucket_count;
1212 __builtin_memset(_M_buckets, 0,
1213 _M_bucket_count *
sizeof(__bucket_type));
1214 __throw_exception_again;
1219 template<
typename _Key,
typename _Value,
1220 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1221 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1223 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1224 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1225 _Hashtable(
const _Hashtable& __ht)
1226 : __hashtable_base(__ht),
1228 __rehash_base(__ht),
1230 _M_bucket_count(__ht._M_bucket_count),
1231 _M_bbegin(_Node_alloc_traits::_S_select_on_copy(
1232 __ht._M_node_allocator())),
1233 _M_element_count(__ht._M_element_count),
1234 _M_rehash_policy(__ht._M_rehash_policy)
1237 [
this](
const __node_type* __n)
1238 {
return _M_allocate_node(__n->_M_v()); });
1241 template<
typename _Key,
typename _Value,
1242 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1243 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1245 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1246 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1247 _Hashtable(_Hashtable&& __ht) noexcept
1248 : __hashtable_base(__ht),
1250 __rehash_base(__ht),
1251 _M_buckets(__ht._M_buckets),
1252 _M_bucket_count(__ht._M_bucket_count),
1253 _M_bbegin(std::move(__ht._M_bbegin)),
1254 _M_element_count(__ht._M_element_count),
1255 _M_rehash_policy(__ht._M_rehash_policy)
1260 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin();
1264 template<
typename _Key,
typename _Value,
1265 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1266 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1268 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1269 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1270 _Hashtable(
const _Hashtable& __ht,
const allocator_type& __a)
1271 : __hashtable_base(__ht),
1273 __rehash_base(__ht),
1275 _M_bucket_count(__ht._M_bucket_count),
1276 _M_bbegin(_Node_alloc_type(__a)),
1277 _M_element_count(__ht._M_element_count),
1278 _M_rehash_policy(__ht._M_rehash_policy)
1281 [
this](
const __node_type* __n)
1282 {
return _M_allocate_node(__n->_M_v()); });
1285 template<
typename _Key,
typename _Value,
1286 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1287 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1289 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1290 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1291 _Hashtable(_Hashtable&& __ht,
const allocator_type& __a)
1292 : __hashtable_base(__ht),
1294 __rehash_base(__ht),
1296 _M_bucket_count(__ht._M_bucket_count),
1297 _M_bbegin(_Node_alloc_type(__a)),
1298 _M_element_count(__ht._M_element_count),
1299 _M_rehash_policy(__ht._M_rehash_policy)
1301 if (__ht._M_node_allocator() == _M_node_allocator())
1303 _M_buckets = __ht._M_buckets;
1304 _M_before_begin()._M_nxt = __ht._M_before_begin()._M_nxt;
1308 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin();
1314 [
this](__node_type* __n)
1316 return _M_allocate_node(
1323 template<
typename _Key,
typename _Value,
1324 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1325 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1327 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1328 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1329 ~_Hashtable() noexcept
1333 _M_deallocate_buckets();
1336 template<
typename _Key,
typename _Value,
1337 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1338 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1341 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1342 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1343 swap(_Hashtable& __x)
1344 noexcept(_Node_alloc_traits::_S_nothrow_swap())
1351 std::__alloc_on_swap(_M_node_allocator(), __x._M_node_allocator());
1352 std::swap(_M_rehash_policy, __x._M_rehash_policy);
1353 std::swap(_M_buckets, __x._M_buckets);
1354 std::swap(_M_bucket_count, __x._M_bucket_count);
1355 std::swap(_M_before_begin()._M_nxt, __x._M_before_begin()._M_nxt);
1356 std::swap(_M_element_count, __x._M_element_count);
1361 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin();
1363 __x._M_buckets[__x._M_bucket_index(__x._M_begin())]
1364 = &(__x._M_before_begin());
1367 template<
typename _Key,
typename _Value,
1368 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1369 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1372 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1373 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1374 __rehash_policy(
const _RehashPolicy& __pol)
1376 size_type __n_bkt = __pol._M_bkt_for_elements(_M_element_count);
1377 __n_bkt = __pol._M_next_bkt(__n_bkt);
1378 if (__n_bkt != _M_bucket_count)
1379 _M_rehash(__n_bkt, _M_rehash_policy._M_state());
1380 _M_rehash_policy = __pol;
1383 template<
typename _Key,
typename _Value,
1384 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1385 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1387 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1388 _H1, _H2, _Hash, _RehashPolicy,
1390 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1391 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1392 find(
const key_type& __k)
1394 if (__builtin_expect(_M_bucket_count == 0,
false))
1397 __hash_code __code = this->_M_hash_code(__k);
1398 std::size_t __n = _M_bucket_index(__k, __code);
1399 __node_type* __p = _M_find_node(__n, __k, __code);
1400 return __p ? iterator(__p) :
end();
1403 template<
typename _Key,
typename _Value,
1404 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1405 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1407 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1408 _H1, _H2, _Hash, _RehashPolicy,
1409 _Traits>::const_iterator
1410 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1411 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1412 find(
const key_type& __k)
const
1414 if (__builtin_expect(_M_bucket_count == 0,
false))
1417 __hash_code __code = this->_M_hash_code(__k);
1418 std::size_t __n = _M_bucket_index(__k, __code);
1419 __node_type* __p = _M_find_node(__n, __k, __code);
1420 return __p ? const_iterator(__p) :
end();
1423 template<
typename _Key,
typename _Value,
1424 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1425 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1427 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1428 _H1, _H2, _Hash, _RehashPolicy,
1430 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1431 _H1, _H2, _Hash, _RehashPolicy, _Traits>
::
1432 count(
const key_type& __k)
const
1434 if (__builtin_expect(_M_bucket_count == 0,
false))
1437 __hash_code __code = this->_M_hash_code(__k);
1438 std::size_t __n = _M_bucket_index(__k, __code);
1439 __node_type* __p = _M_bucket_begin(__n);
1443 std::size_t __result = 0;
1444 for (;; __p = __p->_M_next())
1446 if (this->_M_equals(__k, __code, __p))
1453 if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
1459 template<
typename _Key,
typename _Value,
1460 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1461 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1463 std::pair<
typename _Hashtable<_Key, _Value, _Alloc,
1464 _ExtractKey, _Equal, _H1,
1465 _H2, _Hash, _RehashPolicy,
1467 typename _Hashtable<_Key, _Value, _Alloc,
1468 _ExtractKey, _Equal, _H1,
1469 _H2, _Hash, _RehashPolicy,
1471 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1472 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1473 equal_range(
const key_type& __k)
1475 if (__builtin_expect(_M_bucket_count == 0,
false))
1478 __hash_code __code = this->_M_hash_code(__k);
1479 std::size_t __n = _M_bucket_index(__k, __code);
1480 __node_type* __p = _M_find_node(__n, __k, __code);
1484 __node_type* __p1 = __p->_M_next();
1485 while (__p1 && _M_bucket_index(__p1) == __n
1486 && this->_M_equals(__k, __code, __p1))
1487 __p1 = __p1->_M_next();
1495 template<
typename _Key,
typename _Value,
1496 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1497 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1499 std::pair<
typename _Hashtable<_Key, _Value, _Alloc,
1500 _ExtractKey, _Equal, _H1,
1501 _H2, _Hash, _RehashPolicy,
1502 _Traits>::const_iterator,
1503 typename _Hashtable<_Key, _Value, _Alloc,
1504 _ExtractKey, _Equal, _H1,
1505 _H2, _Hash, _RehashPolicy,
1506 _Traits>::const_iterator>
1507 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1508 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1509 equal_range(
const key_type& __k)
const
1511 if (__builtin_expect(_M_bucket_count == 0,
false))
1514 __hash_code __code = this->_M_hash_code(__k);
1515 std::size_t __n = _M_bucket_index(__k, __code);
1516 __node_type* __p = _M_find_node(__n, __k, __code);
1520 __node_type* __p1 = __p->_M_next();
1521 while (__p1 && _M_bucket_index(__p1) == __n
1522 && this->_M_equals(__k, __code, __p1))
1523 __p1 = __p1->_M_next();
1525 return std::make_pair(const_iterator(__p), const_iterator(__p1));
1533 template<
typename _Key,
typename _Value,
1534 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1535 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1537 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
1538 _Equal, _H1, _H2, _Hash, _RehashPolicy,
1539 _Traits>::__node_base*
1540 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1541 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1542 _M_find_before_node(size_type __n,
const key_type& __k,
1543 __hash_code __code)
const
1545 __node_base* __prev_p = _M_buckets[__n];
1549 for (__node_type* __p = static_cast<__node_type*>(__prev_p->_M_nxt);;
1550 __p = __p->_M_next())
1552 if (this->_M_equals(__k, __code, __p))
1555 if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
1562 template<
typename _Key,
typename _Value,
1563 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1564 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1567 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1568 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1569 _M_insert_bucket_begin(size_type __bkt, __node_type* __node)
1571 if (_M_buckets[__bkt])
1575 __node->_M_nxt = _M_buckets[__bkt]->_M_nxt;
1576 _M_buckets[__bkt]->_M_nxt = __node;
1583 __node->_M_nxt = _M_before_begin()._M_nxt;
1584 _M_before_begin()._M_nxt = __node;
1588 _M_buckets[_M_bucket_index(__node->_M_next())] = __node;
1589 _M_buckets[__bkt] = &_M_before_begin();
1593 template<
typename _Key,
typename _Value,
1594 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1595 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1598 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1599 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1600 _M_remove_bucket_begin(size_type __bkt, __node_type* __next,
1601 size_type __next_bkt)
1603 if (!__next || __next_bkt != __bkt)
1608 _M_buckets[__next_bkt] = _M_buckets[__bkt];
1611 if (&_M_before_begin() == _M_buckets[__bkt])
1612 _M_before_begin()._M_nxt = __next;
1613 _M_buckets[__bkt] =
nullptr;
1617 template<
typename _Key,
typename _Value,
1618 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1619 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1621 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
1622 _Equal, _H1, _H2, _Hash, _RehashPolicy,
1623 _Traits>::__node_base*
1624 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1625 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1626 _M_get_previous_node(size_type __bkt, __node_base* __n)
1628 __node_base* __prev_n = _M_buckets[__bkt];
1629 while (__prev_n->_M_nxt != __n)
1630 __prev_n = __prev_n->_M_nxt;
1634 template<
typename _Key,
typename _Value,
1635 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1636 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1638 template<
typename... _Args>
1639 std::pair<
typename _Hashtable<_Key, _Value, _Alloc,
1640 _ExtractKey, _Equal, _H1,
1641 _H2, _Hash, _RehashPolicy,
1642 _Traits>::iterator,
bool>
1643 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1644 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1648 __node_type* __node = _M_allocate_node(std::forward<_Args>(__args)...);
1649 const key_type& __k = this->_M_extract()(__node->_M_v());
1653 __code = this->_M_hash_code(__k);
1657 _M_deallocate_node(__node);
1658 __throw_exception_again;
1661 size_type __bkt = _M_bucket_index(__k, __code);
1662 if (__node_type* __p = _M_find_node(__bkt, __k, __code))
1665 _M_deallocate_node(__node);
1670 return std::make_pair(_M_insert_unique_node(__bkt, __code, __node),
1674 template<
typename _Key,
typename _Value,
1675 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1676 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1678 template<
typename... _Args>
1679 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1680 _H1, _H2, _Hash, _RehashPolicy,
1682 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1683 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1687 __node_type* __node = _M_allocate_node(std::forward<_Args>(__args)...);
1692 __code = this->_M_hash_code(this->_M_extract()(__node->_M_v()));
1696 _M_deallocate_node(__node);
1697 __throw_exception_again;
1700 return _M_insert_multi_node(__hint._M_cur, __code, __node);
1703 template<
typename _Key,
typename _Value,
1704 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1705 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1707 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1708 _H1, _H2, _Hash, _RehashPolicy,
1710 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1711 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1712 _M_insert_unique_node(size_type __bkt, __hash_code __code,
1713 __node_type* __node)
1715 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
1717 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
1721 if (__do_rehash.
first)
1723 _M_rehash(__do_rehash.
second, __saved_state);
1724 __bkt = _M_bucket_index(this->_M_extract()(__node->_M_v()), __code);
1727 this->_M_store_code(__node, __code);
1730 _M_insert_bucket_begin(__bkt, __node);
1732 return iterator(__node);
1736 _M_deallocate_node(__node);
1737 __throw_exception_again;
1743 template<
typename _Key,
typename _Value,
1744 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1745 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1747 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1748 _H1, _H2, _Hash, _RehashPolicy,
1750 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1751 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1752 _M_insert_multi_node(__node_type* __hint, __hash_code __code,
1753 __node_type* __node)
1755 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
1757 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
1761 if (__do_rehash.
first)
1762 _M_rehash(__do_rehash.
second, __saved_state);
1764 this->_M_store_code(__node, __code);
1765 const key_type& __k = this->_M_extract()(__node->_M_v());
1766 size_type __bkt = _M_bucket_index(__k, __code);
1771 = __builtin_expect(__hint !=
nullptr,
false)
1772 && this->_M_equals(__k, __code, __hint)
1774 : _M_find_before_node(__bkt, __k, __code);
1778 __node->_M_nxt = __prev->_M_nxt;
1779 __prev->_M_nxt = __node;
1780 if (__builtin_expect(__prev == __hint,
false))
1784 && !this->_M_equals(__k, __code, __node->_M_next()))
1786 size_type __next_bkt = _M_bucket_index(__node->_M_next());
1787 if (__next_bkt != __bkt)
1788 _M_buckets[__next_bkt] = __node;
1796 _M_insert_bucket_begin(__bkt, __node);
1798 return iterator(__node);
1802 _M_deallocate_node(__node);
1803 __throw_exception_again;
1808 template<
typename _Key,
typename _Value,
1809 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1810 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1812 template<
typename _Arg,
typename _NodeGenerator>
1813 std::pair<
typename _Hashtable<_Key, _Value, _Alloc,
1814 _ExtractKey, _Equal, _H1,
1815 _H2, _Hash, _RehashPolicy,
1816 _Traits>::iterator,
bool>
1817 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1818 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1819 _M_insert(_Arg&& __v,
const _NodeGenerator& __node_gen,
std::true_type)
1821 const key_type& __k = this->_M_extract()(__v);
1822 __hash_code __code = this->_M_hash_code(__k);
1823 size_type __bkt = _M_bucket_index(__k, __code);
1825 __node_type* __n = _M_find_node(__bkt, __k, __code);
1829 __n = __node_gen(std::forward<_Arg>(__v));
1830 return std::make_pair(_M_insert_unique_node(__bkt, __code, __n),
true);
1834 template<
typename _Key,
typename _Value,
1835 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1836 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1838 template<
typename _Arg,
typename _NodeGenerator>
1839 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1840 _H1, _H2, _Hash, _RehashPolicy,
1842 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1843 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1844 _M_insert(const_iterator __hint, _Arg&& __v,
1845 const _NodeGenerator& __node_gen,
1850 __hash_code __code = this->_M_hash_code(this->_M_extract()(__v));
1853 __node_type* __node = __node_gen(std::forward<_Arg>(__v));
1855 return _M_insert_multi_node(__hint._M_cur, __code, __node);
1858 template<
typename _Key,
typename _Value,
1859 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1860 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1862 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1863 _H1, _H2, _Hash, _RehashPolicy,
1865 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1866 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1867 erase(const_iterator __it)
1869 __node_type* __n = __it._M_cur;
1870 std::size_t __bkt = _M_bucket_index(__n);
1875 __node_base* __prev_n = _M_get_previous_node(__bkt, __n);
1876 return _M_erase(__bkt, __prev_n, __n);
1879 template<
typename _Key,
typename _Value,
1880 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1881 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1883 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1884 _H1, _H2, _Hash, _RehashPolicy,
1886 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1887 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1888 _M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n)
1890 if (__prev_n == _M_buckets[__bkt])
1891 _M_remove_bucket_begin(__bkt, __n->_M_next(),
1892 __n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0);
1893 else if (__n->_M_nxt)
1895 size_type __next_bkt = _M_bucket_index(__n->_M_next());
1896 if (__next_bkt != __bkt)
1897 _M_buckets[__next_bkt] = __prev_n;
1900 __prev_n->_M_nxt = __n->_M_nxt;
1901 iterator __result(__n->_M_next());
1902 _M_deallocate_node(__n);
1908 template<
typename _Key,
typename _Value,
1909 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1910 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1912 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1913 _H1, _H2, _Hash, _RehashPolicy,
1915 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1916 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1919 __hash_code __code = this->_M_hash_code(__k);
1920 std::size_t __bkt = _M_bucket_index(__k, __code);
1923 __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code);
1928 __node_type* __n =
static_cast<__node_type*
>(__prev_n->_M_nxt);
1929 _M_erase(__bkt, __prev_n, __n);
1933 template<
typename _Key,
typename _Value,
1934 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1935 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1937 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1938 _H1, _H2, _Hash, _RehashPolicy,
1940 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1941 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1944 __hash_code __code = this->_M_hash_code(__k);
1945 std::size_t __bkt = _M_bucket_index(__k, __code);
1948 __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code);
1958 __node_type* __n =
static_cast<__node_type*
>(__prev_n->_M_nxt);
1959 __node_type* __n_last = __n;
1960 std::size_t __n_last_bkt = __bkt;
1963 __n_last = __n_last->_M_next();
1966 __n_last_bkt = _M_bucket_index(__n_last);
1968 while (__n_last_bkt == __bkt && this->_M_equals(__k, __code, __n_last));
1971 size_type __result = 0;
1974 __node_type* __p = __n->_M_next();
1975 _M_deallocate_node(__n);
1980 while (__n != __n_last);
1982 if (__prev_n == _M_buckets[__bkt])
1983 _M_remove_bucket_begin(__bkt, __n_last, __n_last_bkt);
1984 else if (__n_last && __n_last_bkt != __bkt)
1985 _M_buckets[__n_last_bkt] = __prev_n;
1986 __prev_n->_M_nxt = __n_last;
1990 template<
typename _Key,
typename _Value,
1991 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1992 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1994 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1995 _H1, _H2, _Hash, _RehashPolicy,
1997 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1998 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1999 erase(const_iterator __first, const_iterator __last)
2001 __node_type* __n = __first._M_cur;
2002 __node_type* __last_n = __last._M_cur;
2003 if (__n == __last_n)
2004 return iterator(__n);
2006 std::size_t __bkt = _M_bucket_index(__n);
2008 __node_base* __prev_n = _M_get_previous_node(__bkt, __n);
2009 bool __is_bucket_begin = __n == _M_bucket_begin(__bkt);
2010 std::size_t __n_bkt = __bkt;
2015 __node_type* __tmp = __n;
2016 __n = __n->_M_next();
2017 _M_deallocate_node(__tmp);
2021 __n_bkt = _M_bucket_index(__n);
2023 while (__n != __last_n && __n_bkt == __bkt);
2024 if (__is_bucket_begin)
2025 _M_remove_bucket_begin(__bkt, __n, __n_bkt);
2026 if (__n == __last_n)
2028 __is_bucket_begin =
true;
2032 if (__n && (__n_bkt != __bkt || __is_bucket_begin))
2033 _M_buckets[__n_bkt] = __prev_n;
2034 __prev_n->_M_nxt = __n;
2035 return iterator(__n);
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>::
2047 _M_deallocate_nodes(_M_begin());
2048 __builtin_memset(_M_buckets, 0, _M_bucket_count *
sizeof(__bucket_type));
2049 _M_element_count = 0;
2050 _M_before_begin()._M_nxt =
nullptr;
2053 template<
typename _Key,
typename _Value,
2054 typename _Alloc,
typename _ExtractKey,
typename _Equal,
2055 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
2058 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2059 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2060 rehash(size_type __n)
2062 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
2063 std::size_t __buckets
2064 =
std::max(_M_rehash_policy._M_bkt_for_elements(_M_element_count + 1),
2066 __buckets = _M_rehash_policy._M_next_bkt(__buckets);
2068 if (__buckets != _M_bucket_count)
2069 _M_rehash(__buckets, __saved_state);
2072 _M_rehash_policy._M_reset(__saved_state);
2075 template<
typename _Key,
typename _Value,
2076 typename _Alloc,
typename _ExtractKey,
typename _Equal,
2077 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
2080 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2081 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2082 _M_rehash(size_type __n,
const __rehash_state& __state)
2086 _M_rehash_aux(__n, __unique_keys());
2092 _M_rehash_policy._M_reset(__state);
2093 __throw_exception_again;
2098 template<
typename _Key,
typename _Value,
2099 typename _Alloc,
typename _ExtractKey,
typename _Equal,
2100 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
2103 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2104 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2107 __bucket_type* __new_buckets = _M_allocate_buckets(__n);
2108 __node_type* __p = _M_begin();
2109 _M_before_begin()._M_nxt =
nullptr;
2110 std::size_t __bbegin_bkt = 0;
2113 __node_type* __next = __p->_M_next();
2114 std::size_t __bkt = __hash_code_base::_M_bucket_index(__p, __n);
2115 if (!__new_buckets[__bkt])
2117 __p->_M_nxt = _M_before_begin()._M_nxt;
2118 _M_before_begin()._M_nxt = __p;
2119 __new_buckets[__bkt] = &_M_before_begin();
2121 __new_buckets[__bbegin_bkt] = __p;
2122 __bbegin_bkt = __bkt;
2126 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2127 __new_buckets[__bkt]->_M_nxt = __p;
2132 if (__builtin_expect(_M_bucket_count != 0,
true))
2133 _M_deallocate_buckets();
2134 _M_bucket_count = __n;
2135 _M_buckets = __new_buckets;
2140 template<
typename _Key,
typename _Value,
2141 typename _Alloc,
typename _ExtractKey,
typename _Equal,
2142 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
2145 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2146 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2149 __bucket_type* __new_buckets = _M_allocate_buckets(__n);
2151 __node_type* __p = _M_begin();
2152 _M_before_begin()._M_nxt =
nullptr;
2153 std::size_t __bbegin_bkt = 0;
2154 std::size_t __prev_bkt = 0;
2155 __node_type* __prev_p =
nullptr;
2156 bool __check_bucket =
false;
2160 __node_type* __next = __p->_M_next();
2161 std::size_t __bkt = __hash_code_base::_M_bucket_index(__p, __n);
2163 if (__prev_p && __prev_bkt == __bkt)
2168 __p->_M_nxt = __prev_p->_M_nxt;
2169 __prev_p->_M_nxt = __p;
2176 __check_bucket =
true;
2184 if (__prev_p->_M_nxt)
2186 std::size_t __next_bkt
2187 = __hash_code_base::_M_bucket_index(__prev_p->_M_next(),
2189 if (__next_bkt != __prev_bkt)
2190 __new_buckets[__next_bkt] = __prev_p;
2192 __check_bucket =
false;
2195 if (!__new_buckets[__bkt])
2197 __p->_M_nxt = _M_before_begin()._M_nxt;
2198 _M_before_begin()._M_nxt = __p;
2199 __new_buckets[__bkt] = &_M_before_begin();
2201 __new_buckets[__bbegin_bkt] = __p;
2202 __bbegin_bkt = __bkt;
2206 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2207 __new_buckets[__bkt]->_M_nxt = __p;
2215 if (__check_bucket && __prev_p->_M_nxt)
2217 std::size_t __next_bkt
2218 = __hash_code_base::_M_bucket_index(__prev_p->_M_next(), __n);
2219 if (__next_bkt != __prev_bkt)
2220 __new_buckets[__next_bkt] = __prev_p;
2223 if (__builtin_expect(_M_bucket_count != 0,
true))
2224 _M_deallocate_buckets();
2225 _M_bucket_count = __n;
2226 _M_buckets = __new_buckets;
2229 _GLIBCXX_END_NAMESPACE_VERSION
2232 #endif // _HASHTABLE_H