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>,
186 typename __alloctr_rebind<_Alloc,
187 __detail::_Hash_node<_Value,
188 _Traits::__hash_cached::value> >::__type>
190 using __traits_type = _Traits;
191 using __hash_cached =
typename __traits_type::__hash_cached;
193 using __node_alloc_type =
194 typename __alloctr_rebind<_Alloc, __node_type>::__type;
198 using __value_alloc_traits =
200 using __node_alloc_traits =
206 typedef _Key key_type;
207 typedef _Value value_type;
208 typedef _Alloc allocator_type;
209 typedef _Equal key_equal;
213 typedef typename __value_alloc_traits::pointer pointer;
214 typedef typename __value_alloc_traits::const_pointer const_pointer;
215 typedef value_type& reference;
216 typedef const value_type& const_reference;
219 using __rehash_type = _RehashPolicy;
220 using __rehash_state =
typename __rehash_type::_State;
222 using __constant_iterators =
typename __traits_type::__constant_iterators;
223 using __unique_keys =
typename __traits_type::__unique_keys;
225 using __key_extract =
typename std::conditional<
226 __constant_iterators::value,
228 __detail::_Select1st>::type;
232 _Equal, _H1, _H2, _Hash, _Traits>;
235 using __hash_code =
typename __hashtable_base::__hash_code;
236 using __ireturn_type =
typename __hashtable_base::__ireturn_type;
239 _Equal, _H1, _H2, _Hash,
240 _RehashPolicy, _Traits>;
245 _RehashPolicy, _Traits>;
248 _Equal, _H1, _H2, _Hash,
249 _RehashPolicy, _Traits>;
251 using __reuse_or_alloc_node_type =
252 __detail::_ReuseOrAllocNode<__node_alloc_type>;
255 template<
typename _Cond>
256 using __if_hash_cached = __or_<__not_<__hash_cached>, _Cond>;
258 template<
typename _Cond>
259 using __if_hash_not_cached = __or_<__hash_cached, _Cond>;
265 static_assert(noexcept(declval<const _Hashtable&>()
268 "Cache the hash code or qualify your functors involved"
269 " in hash code and bucket index computation with noexcept");
276 static_assert(__if_hash_cached<is_default_constructible<_H2>>::value,
277 "Functor used to map hash code to bucket index"
278 " must be default constructible");
282 struct __access_protected_ctor : __hash_code_base { };
287 static_assert(__if_hash_not_cached<
288 is_default_constructible<__access_protected_ctor>>::value,
289 "Cache the hash code or make functors involved in hash code"
290 " and bucket index computation default constructible");
295 static_assert(__if_hash_not_cached<
296 is_copy_assignable<__hash_code_base>>::value,
297 "Cache the hash code or make functors involved in hash code"
298 " and bucket index computation copy assignable");
300 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
301 typename _ExtractKeya,
typename _Equala,
302 typename _H1a,
typename _H2a,
typename _Hasha,
303 typename _RehashPolicya,
typename _Traitsa,
307 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
308 typename _ExtractKeya,
typename _Equala,
309 typename _H1a,
typename _H2a,
typename _Hasha,
310 typename _RehashPolicya,
typename _Traitsa>
313 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
314 typename _ExtractKeya,
typename _Equala,
315 typename _H1a,
typename _H2a,
typename _Hasha,
316 typename _RehashPolicya,
typename _Traitsa,
317 bool _Constant_iteratorsa,
bool _Unique_keysa>
321 using size_type =
typename __hashtable_base::size_type;
322 using difference_type =
typename __hashtable_base::difference_type;
332 __bucket_type* _M_buckets;
333 size_type _M_bucket_count;
334 __node_base _M_before_begin;
335 size_type _M_element_count;
336 _RehashPolicy _M_rehash_policy;
339 _M_base_alloc() {
return *
this; }
341 using __hashtable_alloc::_M_deallocate_buckets;
344 _M_deallocate_buckets()
345 { this->_M_deallocate_buckets(_M_buckets, _M_bucket_count); }
350 _M_bucket_begin(size_type __bkt)
const;
354 {
return static_cast<__node_type*
>(_M_before_begin._M_nxt); }
356 template<
typename _NodeGenerator>
358 _M_assign(
const _Hashtable&,
const _NodeGenerator&);
372 const _H1&,
const _H2&,
const _Hash&,
373 const _Equal&,
const _ExtractKey&,
374 const allocator_type&);
376 template<
typename _InputIterator>
377 _Hashtable(_InputIterator __first, _InputIterator __last,
378 size_type __bucket_hint,
379 const _H1&,
const _H2&,
const _Hash&,
380 const _Equal&,
const _ExtractKey&,
381 const allocator_type&);
396 __key_extract(), __a)
401 const _H1& __hf = _H1(),
402 const key_equal& __eql = key_equal(),
403 const allocator_type& __a = allocator_type())
406 __key_extract(), __a)
409 template<
typename _InputIterator>
410 _Hashtable(_InputIterator __f, _InputIterator __l,
412 const _H1& __hf = _H1(),
413 const key_equal& __eql = key_equal(),
414 const allocator_type& __a = allocator_type())
417 __key_extract(), __a)
422 const _H1& __hf = _H1(),
423 const key_equal& __eql = key_equal(),
424 const allocator_type& __a = allocator_type())
425 :
_Hashtable(__l.begin(), __l.end(), __n, __hf,
428 __key_extract(), __a)
436 noexcept(__node_alloc_traits::_S_nothrow_move())
438 constexpr
bool __move_storage =
439 __node_alloc_traits::_S_propagate_on_move_assign()
440 || __node_alloc_traits::_S_always_equal();
441 _M_move_assign(std::move(__ht),
449 __reuse_or_alloc_node_type __roan(_M_begin(), *
this);
450 _M_before_begin._M_nxt =
nullptr;
452 this->_M_insert_range(__l.begin(), __l.end(), __roan);
460 noexcept(__node_alloc_traits::_S_nothrow_swap());
465 {
return iterator(_M_begin()); }
468 begin()
const noexcept
469 {
return const_iterator(_M_begin()); }
473 {
return iterator(
nullptr); }
477 {
return const_iterator(
nullptr); }
480 cbegin()
const noexcept
481 {
return const_iterator(_M_begin()); }
484 cend()
const noexcept
485 {
return const_iterator(
nullptr); }
488 size()
const noexcept
489 {
return _M_element_count; }
492 empty()
const noexcept
493 {
return size() == 0; }
496 get_allocator()
const noexcept
497 {
return allocator_type(this->_M_node_allocator()); }
500 max_size()
const noexcept
501 {
return __node_alloc_traits::max_size(this->_M_node_allocator()); }
506 {
return this->_M_eq(); }
512 bucket_count()
const noexcept
513 {
return _M_bucket_count; }
516 max_bucket_count()
const noexcept
517 {
return max_size(); }
520 bucket_size(size_type __n)
const
524 bucket(
const key_type& __k)
const
525 {
return _M_bucket_index(__k, this->_M_hash_code(__k)); }
530 return local_iterator(*
this, _M_bucket_begin(__n),
531 __n, _M_bucket_count);
536 {
return local_iterator(*
this,
nullptr, __n, _M_bucket_count); }
539 begin(size_type __n)
const
541 return const_local_iterator(*
this, _M_bucket_begin(__n),
542 __n, _M_bucket_count);
546 end(size_type __n)
const
547 {
return const_local_iterator(*
this,
nullptr, __n, _M_bucket_count); }
551 cbegin(size_type __n)
const
553 return const_local_iterator(*
this, _M_bucket_begin(__n),
554 __n, _M_bucket_count);
558 cend(size_type __n)
const
559 {
return const_local_iterator(*
this,
nullptr, __n, _M_bucket_count); }
562 load_factor()
const noexcept
564 return static_cast<float>(
size()) / static_cast<float>(bucket_count());
573 __rehash_policy()
const
574 {
return _M_rehash_policy; }
577 __rehash_policy(
const _RehashPolicy&);
581 find(
const key_type& __k);
584 find(
const key_type& __k)
const;
587 count(
const key_type& __k)
const;
590 equal_range(
const key_type& __k);
593 equal_range(
const key_type& __k)
const;
599 {
return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); }
602 _M_bucket_index(
const key_type& __k, __hash_code __c)
const
603 {
return __hash_code_base::_M_bucket_index(__k, __c, _M_bucket_count); }
608 _M_find_before_node(size_type,
const key_type&, __hash_code)
const;
611 _M_find_node(size_type __bkt,
const key_type& __key,
612 __hash_code __c)
const
614 __node_base* __before_n = _M_find_before_node(__bkt, __key, __c);
616 return static_cast<__node_type*
>(__before_n->_M_nxt);
626 _M_remove_bucket_begin(size_type __bkt,
__node_type* __next_n,
627 size_type __next_bkt);
631 _M_get_previous_node(size_type __bkt, __node_base* __n);
637 _M_insert_unique_node(size_type __bkt, __hash_code __code,
646 template<
typename... _Args>
650 template<
typename... _Args>
653 {
return _M_emplace(cend(), __uk, std::forward<_Args>(__args)...); }
656 template<
typename... _Args>
658 _M_emplace(const_iterator,
std::true_type __uk, _Args&&... __args)
659 {
return _M_emplace(__uk, std::forward<_Args>(__args)...).first; }
661 template<
typename... _Args>
665 template<
typename _Arg,
typename _NodeGenerator>
669 template<
typename _Arg,
typename _NodeGenerator>
671 _M_insert(_Arg&& __arg,
const _NodeGenerator& __node_gen,
674 return _M_insert(cend(), std::forward<_Arg>(__arg), __node_gen,
679 template<
typename _Arg,
typename _NodeGenerator>
681 _M_insert(const_iterator, _Arg&& __arg,
const _NodeGenerator& __node_gen,
685 _M_insert(std::forward<_Arg>(__arg), __node_gen, __uk).
first;
689 template<
typename _Arg,
typename _NodeGenerator>
691 _M_insert(const_iterator, _Arg&&,
const _NodeGenerator&,
std::false_type);
700 _M_erase(size_type __bkt, __node_base* __prev_n,
__node_type* __n);
704 template<
typename... _Args>
706 emplace(_Args&&... __args)
707 {
return _M_emplace(__unique_keys(), std::forward<_Args>(__args)...); }
709 template<
typename... _Args>
711 emplace_hint(const_iterator __hint, _Args&&... __args)
713 return _M_emplace(__hint, __unique_keys(),
714 std::forward<_Args>(__args)...);
721 erase(const_iterator);
726 {
return erase(const_iterator(__it)); }
729 erase(
const key_type& __k)
731 if (__builtin_expect(_M_bucket_count == 0,
false))
733 return _M_erase(__unique_keys(), __k);
737 erase(const_iterator, const_iterator);
743 void rehash(size_type __n);
757 void _M_rehash(size_type __n,
const __rehash_state& __state);
762 template<
typename _Key,
typename _Value,
763 typename _Alloc,
typename _ExtractKey,
typename _Equal,
764 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
766 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
767 _Equal, _H1, _H2, _Hash, _RehashPolicy,
768 _Traits>::__node_type*
769 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
770 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
771 _M_bucket_begin(size_type __bkt)
const
773 __node_base* __n = _M_buckets[__bkt];
774 return __n ?
static_cast<__node_type*
>(__n->_M_nxt) :
nullptr;
777 template<
typename _Key,
typename _Value,
778 typename _Alloc,
typename _ExtractKey,
typename _Equal,
779 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
781 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
782 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
783 _Hashtable(size_type __bucket_hint,
784 const _H1& __h1,
const _H2& __h2,
const _Hash& __h,
785 const _Equal& __eq,
const _ExtractKey& __exk,
786 const allocator_type& __a)
787 : __hashtable_base(__exk, __h1, __h2, __h, __eq),
790 __hashtable_alloc(__node_alloc_type(__a)),
794 _M_bucket_count = _M_rehash_policy._M_next_bkt(__bucket_hint);
795 _M_buckets = this->_M_allocate_buckets(_M_bucket_count);
798 template<
typename _Key,
typename _Value,
799 typename _Alloc,
typename _ExtractKey,
typename _Equal,
800 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
802 template<
typename _InputIterator>
803 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
804 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
805 _Hashtable(_InputIterator __f, _InputIterator __l,
806 size_type __bucket_hint,
807 const _H1& __h1,
const _H2& __h2,
const _Hash& __h,
808 const _Equal& __eq,
const _ExtractKey& __exk,
809 const allocator_type& __a)
810 : __hashtable_base(__exk, __h1, __h2, __h, __eq),
813 __hashtable_alloc(__node_alloc_type(__a)),
817 auto __nb_elems = __detail::__distance_fw(__f, __l);
819 _M_rehash_policy._M_next_bkt(
820 std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems),
823 _M_buckets = this->_M_allocate_buckets(_M_bucket_count);
826 for (; __f != __l; ++__f)
832 _M_deallocate_buckets();
833 __throw_exception_again;
837 template<
typename _Key,
typename _Value,
838 typename _Alloc,
typename _ExtractKey,
typename _Equal,
839 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
841 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
842 _H1, _H2, _Hash, _RehashPolicy, _Traits>&
843 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
844 _H1, _H2, _Hash, _RehashPolicy, _Traits>::operator=(
845 const _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
846 _H1, _H2, _Hash, _RehashPolicy, _Traits>& __ht)
851 if (__node_alloc_traits::_S_propagate_on_copy_assign())
853 auto& __this_alloc = this->_M_node_allocator();
854 auto& __that_alloc = __ht._M_node_allocator();
855 if (!__node_alloc_traits::_S_always_equal()
856 && __this_alloc != __that_alloc)
859 this->_M_deallocate_nodes(_M_begin());
860 if (__builtin_expect(_M_bucket_count != 0,
true))
861 _M_deallocate_buckets();
863 std::__alloc_on_copy(__this_alloc, __that_alloc);
864 __hashtable_base::operator=(__ht);
865 _M_bucket_count = __ht._M_bucket_count;
866 _M_element_count = __ht._M_element_count;
867 _M_rehash_policy = __ht._M_rehash_policy;
871 [
this](
const __node_type* __n)
872 {
return this->_M_allocate_node(__n->_M_v()); });
879 __throw_exception_again;
883 std::__alloc_on_copy(__this_alloc, __that_alloc);
887 __bucket_type* __former_buckets =
nullptr;
888 std::size_t __former_bucket_count = _M_bucket_count;
889 const __rehash_state& __former_state = _M_rehash_policy._M_state();
891 if (_M_bucket_count != __ht._M_bucket_count)
893 __former_buckets = _M_buckets;
894 _M_buckets = this->_M_allocate_buckets(__ht._M_bucket_count);
895 _M_bucket_count = __ht._M_bucket_count;
898 __builtin_memset(_M_buckets, 0,
899 _M_bucket_count *
sizeof(__bucket_type));
903 __hashtable_base::operator=(__ht);
904 _M_element_count = __ht._M_element_count;
905 _M_rehash_policy = __ht._M_rehash_policy;
906 __reuse_or_alloc_node_type __roan(_M_begin(), *
this);
907 _M_before_begin._M_nxt =
nullptr;
909 [&__roan](
const __node_type* __n)
910 {
return __roan(__n->_M_v()); });
911 if (__former_buckets)
912 this->_M_deallocate_buckets(__former_buckets,
913 __former_bucket_count);
917 if (__former_buckets)
920 _M_deallocate_buckets();
921 _M_rehash_policy._M_reset(__former_state);
922 _M_buckets = __former_buckets;
923 _M_bucket_count = __former_bucket_count;
925 __builtin_memset(_M_buckets, 0,
926 _M_bucket_count *
sizeof(__bucket_type));
927 __throw_exception_again;
932 template<
typename _Key,
typename _Value,
933 typename _Alloc,
typename _ExtractKey,
typename _Equal,
934 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
936 template<
typename _NodeGenerator>
938 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
939 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
940 _M_assign(
const _Hashtable& __ht,
const _NodeGenerator& __node_gen)
942 __bucket_type* __buckets =
nullptr;
944 _M_buckets = __buckets = this->_M_allocate_buckets(_M_bucket_count);
948 if (!__ht._M_before_begin._M_nxt)
953 __node_type* __ht_n = __ht._M_begin();
954 __node_type* __this_n = __node_gen(__ht_n);
955 this->_M_copy_code(__this_n, __ht_n);
956 _M_before_begin._M_nxt = __this_n;
957 _M_buckets[_M_bucket_index(__this_n)] = &_M_before_begin;
960 __node_base* __prev_n = __this_n;
961 for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next())
963 __this_n = __node_gen(__ht_n);
964 __prev_n->_M_nxt = __this_n;
965 this->_M_copy_code(__this_n, __ht_n);
966 size_type __bkt = _M_bucket_index(__this_n);
967 if (!_M_buckets[__bkt])
968 _M_buckets[__bkt] = __prev_n;
976 _M_deallocate_buckets();
977 __throw_exception_again;
981 template<
typename _Key,
typename _Value,
982 typename _Alloc,
typename _ExtractKey,
typename _Equal,
983 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
986 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
987 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
990 _M_rehash_policy._M_reset();
992 _M_buckets =
nullptr;
993 _M_before_begin._M_nxt =
nullptr;
994 _M_element_count = 0;
997 template<
typename _Key,
typename _Value,
998 typename _Alloc,
typename _ExtractKey,
typename _Equal,
999 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1002 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1003 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1006 this->_M_deallocate_nodes(_M_begin());
1007 if (__builtin_expect(_M_bucket_count != 0,
true))
1008 _M_deallocate_buckets();
1010 __hashtable_base::operator=(std::move(__ht));
1011 _M_rehash_policy = __ht._M_rehash_policy;
1012 _M_buckets = __ht._M_buckets;
1013 _M_bucket_count = __ht._M_bucket_count;
1014 _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt;
1015 _M_element_count = __ht._M_element_count;
1016 std::__alloc_on_move(this->_M_node_allocator(), __ht._M_node_allocator());
1021 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
1025 template<
typename _Key,
typename _Value,
1026 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1027 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1030 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1031 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1034 if (__ht._M_node_allocator() == this->_M_node_allocator())
1039 __bucket_type* __former_buckets =
nullptr;
1040 size_type __former_bucket_count = _M_bucket_count;
1041 const __rehash_state& __former_state = _M_rehash_policy._M_state();
1043 if (_M_bucket_count != __ht._M_bucket_count)
1045 __former_buckets = _M_buckets;
1046 _M_buckets = this->_M_allocate_buckets(__ht._M_bucket_count);
1047 _M_bucket_count = __ht._M_bucket_count;
1050 __builtin_memset(_M_buckets, 0,
1051 _M_bucket_count *
sizeof(__bucket_type));
1055 __hashtable_base::operator=(std::move(__ht));
1056 _M_element_count = __ht._M_element_count;
1057 _M_rehash_policy = __ht._M_rehash_policy;
1058 __reuse_or_alloc_node_type __roan(_M_begin(), *
this);
1059 _M_before_begin._M_nxt =
nullptr;
1061 [&__roan](__node_type* __n)
1067 if (__former_buckets)
1069 _M_deallocate_buckets();
1070 _M_rehash_policy._M_reset(__former_state);
1071 _M_buckets = __former_buckets;
1072 _M_bucket_count = __former_bucket_count;
1074 __builtin_memset(_M_buckets, 0,
1075 _M_bucket_count *
sizeof(__bucket_type));
1076 __throw_exception_again;
1081 template<
typename _Key,
typename _Value,
1082 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1083 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1085 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1086 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1087 _Hashtable(
const _Hashtable& __ht)
1088 : __hashtable_base(__ht),
1090 __rehash_base(__ht),
1092 __node_alloc_traits::_S_select_on_copy(__ht._M_node_allocator())),
1094 _M_bucket_count(__ht._M_bucket_count),
1095 _M_element_count(__ht._M_element_count),
1096 _M_rehash_policy(__ht._M_rehash_policy)
1099 [
this](
const __node_type* __n)
1100 {
return this->_M_allocate_node(__n->_M_v()); });
1103 template<
typename _Key,
typename _Value,
1104 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1105 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1107 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1108 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1109 _Hashtable(_Hashtable&& __ht) noexcept
1110 : __hashtable_base(__ht),
1112 __rehash_base(__ht),
1113 __hashtable_alloc(std::move(__ht._M_base_alloc())),
1114 _M_buckets(__ht._M_buckets),
1115 _M_bucket_count(__ht._M_bucket_count),
1116 _M_before_begin(__ht._M_before_begin._M_nxt),
1117 _M_element_count(__ht._M_element_count),
1118 _M_rehash_policy(__ht._M_rehash_policy)
1123 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
1127 template<
typename _Key,
typename _Value,
1128 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1129 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1131 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1132 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1133 _Hashtable(
const _Hashtable& __ht,
const allocator_type& __a)
1134 : __hashtable_base(__ht),
1136 __rehash_base(__ht),
1137 __hashtable_alloc(__node_alloc_type(__a)),
1139 _M_bucket_count(__ht._M_bucket_count),
1140 _M_element_count(__ht._M_element_count),
1141 _M_rehash_policy(__ht._M_rehash_policy)
1144 [
this](
const __node_type* __n)
1145 {
return this->_M_allocate_node(__n->_M_v()); });
1148 template<
typename _Key,
typename _Value,
1149 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1150 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1152 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1153 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1154 _Hashtable(_Hashtable&& __ht,
const allocator_type& __a)
1155 : __hashtable_base(__ht),
1157 __rehash_base(__ht),
1158 __hashtable_alloc(__node_alloc_type(__a)),
1160 _M_bucket_count(__ht._M_bucket_count),
1161 _M_element_count(__ht._M_element_count),
1162 _M_rehash_policy(__ht._M_rehash_policy)
1164 if (__ht._M_node_allocator() == this->_M_node_allocator())
1166 _M_buckets = __ht._M_buckets;
1167 _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt;
1171 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
1177 [
this](__node_type* __n)
1179 return this->_M_allocate_node(
1186 template<
typename _Key,
typename _Value,
1187 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1188 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1190 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1191 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1192 ~_Hashtable() noexcept
1196 _M_deallocate_buckets();
1199 template<
typename _Key,
typename _Value,
1200 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1201 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1204 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1205 _H1, _H2, _Hash, _RehashPolicy, _Traits>
::
1206 swap(_Hashtable& __x)
1207 noexcept(__node_alloc_traits::_S_nothrow_swap())
1214 std::__alloc_on_swap(this->_M_node_allocator(), __x._M_node_allocator());
1215 std::swap(_M_rehash_policy, __x._M_rehash_policy);
1217 std::swap(_M_bucket_count, __x._M_bucket_count);
1218 std::swap(_M_before_begin._M_nxt, __x._M_before_begin._M_nxt);
1219 std::swap(_M_element_count, __x._M_element_count);
1224 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
1226 __x._M_buckets[__x._M_bucket_index(__x._M_begin())]
1227 = &__x._M_before_begin;
1230 template<
typename _Key,
typename _Value,
1231 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1232 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1235 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1236 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1237 __rehash_policy(
const _RehashPolicy& __pol)
1239 size_type __n_bkt = __pol._M_bkt_for_elements(_M_element_count);
1240 __n_bkt = __pol._M_next_bkt(__n_bkt);
1241 if (__n_bkt != _M_bucket_count)
1242 _M_rehash(__n_bkt, _M_rehash_policy._M_state());
1243 _M_rehash_policy = __pol;
1246 template<
typename _Key,
typename _Value,
1247 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1248 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1250 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1251 _H1, _H2, _Hash, _RehashPolicy,
1253 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1254 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1255 find(
const key_type& __k)
1257 if (__builtin_expect(_M_bucket_count == 0,
false))
1260 __hash_code __code = this->_M_hash_code(__k);
1261 std::size_t __n = _M_bucket_index(__k, __code);
1262 __node_type* __p = _M_find_node(__n, __k, __code);
1263 return __p ? iterator(__p) :
end();
1266 template<
typename _Key,
typename _Value,
1267 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1268 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1270 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1271 _H1, _H2, _Hash, _RehashPolicy,
1272 _Traits>::const_iterator
1273 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1274 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1275 find(
const key_type& __k)
const
1277 if (__builtin_expect(_M_bucket_count == 0,
false))
1280 __hash_code __code = this->_M_hash_code(__k);
1281 std::size_t __n = _M_bucket_index(__k, __code);
1282 __node_type* __p = _M_find_node(__n, __k, __code);
1283 return __p ? const_iterator(__p) :
end();
1286 template<
typename _Key,
typename _Value,
1287 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1288 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1290 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1291 _H1, _H2, _Hash, _RehashPolicy,
1293 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1294 _H1, _H2, _Hash, _RehashPolicy, _Traits>
::
1295 count(
const key_type& __k)
const
1297 if (__builtin_expect(_M_bucket_count == 0,
false))
1300 __hash_code __code = this->_M_hash_code(__k);
1301 std::size_t __n = _M_bucket_index(__k, __code);
1302 __node_type* __p = _M_bucket_begin(__n);
1306 std::size_t __result = 0;
1307 for (;; __p = __p->_M_next())
1309 if (this->_M_equals(__k, __code, __p))
1316 if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
1322 template<
typename _Key,
typename _Value,
1323 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1324 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1326 std::pair<
typename _Hashtable<_Key, _Value, _Alloc,
1327 _ExtractKey, _Equal, _H1,
1328 _H2, _Hash, _RehashPolicy,
1330 typename _Hashtable<_Key, _Value, _Alloc,
1331 _ExtractKey, _Equal, _H1,
1332 _H2, _Hash, _RehashPolicy,
1334 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1335 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1336 equal_range(
const key_type& __k)
1338 if (__builtin_expect(_M_bucket_count == 0,
false))
1341 __hash_code __code = this->_M_hash_code(__k);
1342 std::size_t __n = _M_bucket_index(__k, __code);
1343 __node_type* __p = _M_find_node(__n, __k, __code);
1347 __node_type* __p1 = __p->_M_next();
1348 while (__p1 && _M_bucket_index(__p1) == __n
1349 && this->_M_equals(__k, __code, __p1))
1350 __p1 = __p1->_M_next();
1358 template<
typename _Key,
typename _Value,
1359 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1360 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1362 std::pair<
typename _Hashtable<_Key, _Value, _Alloc,
1363 _ExtractKey, _Equal, _H1,
1364 _H2, _Hash, _RehashPolicy,
1365 _Traits>::const_iterator,
1366 typename _Hashtable<_Key, _Value, _Alloc,
1367 _ExtractKey, _Equal, _H1,
1368 _H2, _Hash, _RehashPolicy,
1369 _Traits>::const_iterator>
1370 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1371 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1372 equal_range(
const key_type& __k)
const
1374 if (__builtin_expect(_M_bucket_count == 0,
false))
1377 __hash_code __code = this->_M_hash_code(__k);
1378 std::size_t __n = _M_bucket_index(__k, __code);
1379 __node_type* __p = _M_find_node(__n, __k, __code);
1383 __node_type* __p1 = __p->_M_next();
1384 while (__p1 && _M_bucket_index(__p1) == __n
1385 && this->_M_equals(__k, __code, __p1))
1386 __p1 = __p1->_M_next();
1388 return std::make_pair(const_iterator(__p), const_iterator(__p1));
1396 template<
typename _Key,
typename _Value,
1397 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1398 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1400 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
1401 _Equal, _H1, _H2, _Hash, _RehashPolicy,
1402 _Traits>::__node_base*
1403 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1404 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1405 _M_find_before_node(size_type __n,
const key_type& __k,
1406 __hash_code __code)
const
1408 __node_base* __prev_p = _M_buckets[__n];
1412 for (__node_type* __p = static_cast<__node_type*>(__prev_p->_M_nxt);;
1413 __p = __p->_M_next())
1415 if (this->_M_equals(__k, __code, __p))
1418 if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
1425 template<
typename _Key,
typename _Value,
1426 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1427 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1430 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1431 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1432 _M_insert_bucket_begin(size_type __bkt, __node_type* __node)
1434 if (_M_buckets[__bkt])
1438 __node->_M_nxt = _M_buckets[__bkt]->_M_nxt;
1439 _M_buckets[__bkt]->_M_nxt = __node;
1446 __node->_M_nxt = _M_before_begin._M_nxt;
1447 _M_before_begin._M_nxt = __node;
1451 _M_buckets[_M_bucket_index(__node->_M_next())] = __node;
1452 _M_buckets[__bkt] = &_M_before_begin;
1456 template<
typename _Key,
typename _Value,
1457 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1458 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1461 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1462 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1463 _M_remove_bucket_begin(size_type __bkt, __node_type* __next,
1464 size_type __next_bkt)
1466 if (!__next || __next_bkt != __bkt)
1471 _M_buckets[__next_bkt] = _M_buckets[__bkt];
1474 if (&_M_before_begin == _M_buckets[__bkt])
1475 _M_before_begin._M_nxt = __next;
1476 _M_buckets[__bkt] =
nullptr;
1480 template<
typename _Key,
typename _Value,
1481 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1482 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1484 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
1485 _Equal, _H1, _H2, _Hash, _RehashPolicy,
1486 _Traits>::__node_base*
1487 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1488 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1489 _M_get_previous_node(size_type __bkt, __node_base* __n)
1491 __node_base* __prev_n = _M_buckets[__bkt];
1492 while (__prev_n->_M_nxt != __n)
1493 __prev_n = __prev_n->_M_nxt;
1497 template<
typename _Key,
typename _Value,
1498 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1499 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1501 template<
typename... _Args>
1502 std::pair<
typename _Hashtable<_Key, _Value, _Alloc,
1503 _ExtractKey, _Equal, _H1,
1504 _H2, _Hash, _RehashPolicy,
1505 _Traits>::iterator,
bool>
1506 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1507 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1511 __node_type* __node = this->_M_allocate_node(std::forward<_Args>(__args)...);
1512 const key_type& __k = this->_M_extract()(__node->_M_v());
1516 __code = this->_M_hash_code(__k);
1520 this->_M_deallocate_node(__node);
1521 __throw_exception_again;
1524 size_type __bkt = _M_bucket_index(__k, __code);
1525 if (__node_type* __p = _M_find_node(__bkt, __k, __code))
1528 this->_M_deallocate_node(__node);
1533 return std::make_pair(_M_insert_unique_node(__bkt, __code, __node),
1537 template<
typename _Key,
typename _Value,
1538 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1539 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1541 template<
typename... _Args>
1542 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1543 _H1, _H2, _Hash, _RehashPolicy,
1545 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1546 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1550 __node_type* __node =
1551 this->_M_allocate_node(std::forward<_Args>(__args)...);
1556 __code = this->_M_hash_code(this->_M_extract()(__node->_M_v()));
1560 this->_M_deallocate_node(__node);
1561 __throw_exception_again;
1564 return _M_insert_multi_node(__hint._M_cur, __code, __node);
1567 template<
typename _Key,
typename _Value,
1568 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1569 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1571 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1572 _H1, _H2, _Hash, _RehashPolicy,
1574 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1575 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1576 _M_insert_unique_node(size_type __bkt, __hash_code __code,
1577 __node_type* __node)
1579 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
1581 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
1585 if (__do_rehash.
first)
1587 _M_rehash(__do_rehash.
second, __saved_state);
1588 __bkt = _M_bucket_index(this->_M_extract()(__node->_M_v()), __code);
1591 this->_M_store_code(__node, __code);
1594 _M_insert_bucket_begin(__bkt, __node);
1596 return iterator(__node);
1600 this->_M_deallocate_node(__node);
1601 __throw_exception_again;
1607 template<
typename _Key,
typename _Value,
1608 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1609 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1611 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1612 _H1, _H2, _Hash, _RehashPolicy,
1614 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1615 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1616 _M_insert_multi_node(__node_type* __hint, __hash_code __code,
1617 __node_type* __node)
1619 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
1621 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
1625 if (__do_rehash.
first)
1626 _M_rehash(__do_rehash.
second, __saved_state);
1628 this->_M_store_code(__node, __code);
1629 const key_type& __k = this->_M_extract()(__node->_M_v());
1630 size_type __bkt = _M_bucket_index(__k, __code);
1635 = __builtin_expect(__hint !=
nullptr,
false)
1636 && this->_M_equals(__k, __code, __hint)
1638 : _M_find_before_node(__bkt, __k, __code);
1642 __node->_M_nxt = __prev->_M_nxt;
1643 __prev->_M_nxt = __node;
1644 if (__builtin_expect(__prev == __hint,
false))
1648 && !this->_M_equals(__k, __code, __node->_M_next()))
1650 size_type __next_bkt = _M_bucket_index(__node->_M_next());
1651 if (__next_bkt != __bkt)
1652 _M_buckets[__next_bkt] = __node;
1660 _M_insert_bucket_begin(__bkt, __node);
1662 return iterator(__node);
1666 this->_M_deallocate_node(__node);
1667 __throw_exception_again;
1672 template<
typename _Key,
typename _Value,
1673 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1674 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1676 template<
typename _Arg,
typename _NodeGenerator>
1677 std::pair<
typename _Hashtable<_Key, _Value, _Alloc,
1678 _ExtractKey, _Equal, _H1,
1679 _H2, _Hash, _RehashPolicy,
1680 _Traits>::iterator,
bool>
1681 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1682 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1683 _M_insert(_Arg&& __v,
const _NodeGenerator& __node_gen,
std::true_type)
1685 const key_type& __k = this->_M_extract()(__v);
1686 __hash_code __code = this->_M_hash_code(__k);
1687 size_type __bkt = _M_bucket_index(__k, __code);
1689 __node_type* __n = _M_find_node(__bkt, __k, __code);
1693 __n = __node_gen(std::forward<_Arg>(__v));
1694 return std::make_pair(_M_insert_unique_node(__bkt, __code, __n),
true);
1698 template<
typename _Key,
typename _Value,
1699 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1700 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1702 template<
typename _Arg,
typename _NodeGenerator>
1703 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1704 _H1, _H2, _Hash, _RehashPolicy,
1706 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1707 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1708 _M_insert(const_iterator __hint, _Arg&& __v,
1709 const _NodeGenerator& __node_gen,
1714 __hash_code __code = this->_M_hash_code(this->_M_extract()(__v));
1717 __node_type* __node = __node_gen(std::forward<_Arg>(__v));
1719 return _M_insert_multi_node(__hint._M_cur, __code, __node);
1722 template<
typename _Key,
typename _Value,
1723 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1724 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1726 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1727 _H1, _H2, _Hash, _RehashPolicy,
1729 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1730 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1731 erase(const_iterator __it)
1733 __node_type* __n = __it._M_cur;
1734 std::size_t __bkt = _M_bucket_index(__n);
1739 __node_base* __prev_n = _M_get_previous_node(__bkt, __n);
1740 return _M_erase(__bkt, __prev_n, __n);
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_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n)
1754 if (__prev_n == _M_buckets[__bkt])
1755 _M_remove_bucket_begin(__bkt, __n->_M_next(),
1756 __n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0);
1757 else if (__n->_M_nxt)
1759 size_type __next_bkt = _M_bucket_index(__n->_M_next());
1760 if (__next_bkt != __bkt)
1761 _M_buckets[__next_bkt] = __prev_n;
1764 __prev_n->_M_nxt = __n->_M_nxt;
1765 iterator __result(__n->_M_next());
1766 this->_M_deallocate_node(__n);
1772 template<
typename _Key,
typename _Value,
1773 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1774 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1776 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1777 _H1, _H2, _Hash, _RehashPolicy,
1779 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1780 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1783 __hash_code __code = this->_M_hash_code(__k);
1784 std::size_t __bkt = _M_bucket_index(__k, __code);
1787 __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code);
1792 __node_type* __n =
static_cast<__node_type*
>(__prev_n->_M_nxt);
1793 _M_erase(__bkt, __prev_n, __n);
1797 template<
typename _Key,
typename _Value,
1798 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1799 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1801 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1802 _H1, _H2, _Hash, _RehashPolicy,
1804 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1805 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1808 __hash_code __code = this->_M_hash_code(__k);
1809 std::size_t __bkt = _M_bucket_index(__k, __code);
1812 __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code);
1822 __node_type* __n =
static_cast<__node_type*
>(__prev_n->_M_nxt);
1823 __node_type* __n_last = __n;
1824 std::size_t __n_last_bkt = __bkt;
1827 __n_last = __n_last->_M_next();
1830 __n_last_bkt = _M_bucket_index(__n_last);
1832 while (__n_last_bkt == __bkt && this->_M_equals(__k, __code, __n_last));
1835 size_type __result = 0;
1838 __node_type* __p = __n->_M_next();
1839 this->_M_deallocate_node(__n);
1844 while (__n != __n_last);
1846 if (__prev_n == _M_buckets[__bkt])
1847 _M_remove_bucket_begin(__bkt, __n_last, __n_last_bkt);
1848 else if (__n_last && __n_last_bkt != __bkt)
1849 _M_buckets[__n_last_bkt] = __prev_n;
1850 __prev_n->_M_nxt = __n_last;
1854 template<
typename _Key,
typename _Value,
1855 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1856 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1858 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1859 _H1, _H2, _Hash, _RehashPolicy,
1861 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1862 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1863 erase(const_iterator __first, const_iterator __last)
1865 __node_type* __n = __first._M_cur;
1866 __node_type* __last_n = __last._M_cur;
1867 if (__n == __last_n)
1868 return iterator(__n);
1870 std::size_t __bkt = _M_bucket_index(__n);
1872 __node_base* __prev_n = _M_get_previous_node(__bkt, __n);
1873 bool __is_bucket_begin = __n == _M_bucket_begin(__bkt);
1874 std::size_t __n_bkt = __bkt;
1879 __node_type* __tmp = __n;
1880 __n = __n->_M_next();
1881 this->_M_deallocate_node(__tmp);
1885 __n_bkt = _M_bucket_index(__n);
1887 while (__n != __last_n && __n_bkt == __bkt);
1888 if (__is_bucket_begin)
1889 _M_remove_bucket_begin(__bkt, __n, __n_bkt);
1890 if (__n == __last_n)
1892 __is_bucket_begin =
true;
1896 if (__n && (__n_bkt != __bkt || __is_bucket_begin))
1897 _M_buckets[__n_bkt] = __prev_n;
1898 __prev_n->_M_nxt = __n;
1899 return iterator(__n);
1902 template<
typename _Key,
typename _Value,
1903 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1904 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1907 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1908 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1911 this->_M_deallocate_nodes(_M_begin());
1912 __builtin_memset(_M_buckets, 0, _M_bucket_count *
sizeof(__bucket_type));
1913 _M_element_count = 0;
1914 _M_before_begin._M_nxt =
nullptr;
1917 template<
typename _Key,
typename _Value,
1918 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1919 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1922 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1923 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1924 rehash(size_type __n)
1926 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
1927 std::size_t __buckets
1928 =
std::max(_M_rehash_policy._M_bkt_for_elements(_M_element_count + 1),
1930 __buckets = _M_rehash_policy._M_next_bkt(__buckets);
1932 if (__buckets != _M_bucket_count)
1933 _M_rehash(__buckets, __saved_state);
1936 _M_rehash_policy._M_reset(__saved_state);
1939 template<
typename _Key,
typename _Value,
1940 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1941 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1944 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1945 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1946 _M_rehash(size_type __n,
const __rehash_state& __state)
1950 _M_rehash_aux(__n, __unique_keys());
1956 _M_rehash_policy._M_reset(__state);
1957 __throw_exception_again;
1962 template<
typename _Key,
typename _Value,
1963 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1964 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1967 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1968 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1971 __bucket_type* __new_buckets = this->_M_allocate_buckets(__n);
1972 __node_type* __p = _M_begin();
1973 _M_before_begin._M_nxt =
nullptr;
1974 std::size_t __bbegin_bkt = 0;
1977 __node_type* __next = __p->_M_next();
1978 std::size_t __bkt = __hash_code_base::_M_bucket_index(__p, __n);
1979 if (!__new_buckets[__bkt])
1981 __p->_M_nxt = _M_before_begin._M_nxt;
1982 _M_before_begin._M_nxt = __p;
1983 __new_buckets[__bkt] = &_M_before_begin;
1985 __new_buckets[__bbegin_bkt] = __p;
1986 __bbegin_bkt = __bkt;
1990 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
1991 __new_buckets[__bkt]->_M_nxt = __p;
1996 if (__builtin_expect(_M_bucket_count != 0,
true))
1997 _M_deallocate_buckets();
1998 _M_bucket_count = __n;
1999 _M_buckets = __new_buckets;
2004 template<
typename _Key,
typename _Value,
2005 typename _Alloc,
typename _ExtractKey,
typename _Equal,
2006 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
2009 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2010 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2013 __bucket_type* __new_buckets = this->_M_allocate_buckets(__n);
2015 __node_type* __p = _M_begin();
2016 _M_before_begin._M_nxt =
nullptr;
2017 std::size_t __bbegin_bkt = 0;
2018 std::size_t __prev_bkt = 0;
2019 __node_type* __prev_p =
nullptr;
2020 bool __check_bucket =
false;
2024 __node_type* __next = __p->_M_next();
2025 std::size_t __bkt = __hash_code_base::_M_bucket_index(__p, __n);
2027 if (__prev_p && __prev_bkt == __bkt)
2032 __p->_M_nxt = __prev_p->_M_nxt;
2033 __prev_p->_M_nxt = __p;
2040 __check_bucket =
true;
2048 if (__prev_p->_M_nxt)
2050 std::size_t __next_bkt
2051 = __hash_code_base::_M_bucket_index(__prev_p->_M_next(),
2053 if (__next_bkt != __prev_bkt)
2054 __new_buckets[__next_bkt] = __prev_p;
2056 __check_bucket =
false;
2059 if (!__new_buckets[__bkt])
2061 __p->_M_nxt = _M_before_begin._M_nxt;
2062 _M_before_begin._M_nxt = __p;
2063 __new_buckets[__bkt] = &_M_before_begin;
2065 __new_buckets[__bbegin_bkt] = __p;
2066 __bbegin_bkt = __bkt;
2070 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2071 __new_buckets[__bkt]->_M_nxt = __p;
2079 if (__check_bucket && __prev_p->_M_nxt)
2081 std::size_t __next_bkt
2082 = __hash_code_base::_M_bucket_index(__prev_p->_M_next(), __n);
2083 if (__next_bkt != __prev_bkt)
2084 __new_buckets[__next_bkt] = __prev_p;
2087 if (__builtin_expect(_M_bucket_count != 0,
true))
2088 _M_deallocate_buckets();
2089 _M_bucket_count = __n;
2090 _M_buckets = __new_buckets;
2093 _GLIBCXX_END_NAMESPACE_VERSION
2096 #endif // _HASHTABLE_H
Node const_iterators, used to iterate through all the hashtable.
Default ranged hash function H. In principle it should be a function object composed from objects of ...
_T2 second
first is a copy of the first object
Uniform interface to C++98 and C++0x allocators.
constexpr pair< typename __decay_and_strip< _T1 >::__type, typename __decay_and_strip< _T2 >::__type > make_pair(_T1 &&__x, _T2 &&__y)
A convenience wrapper for creating a pair from two objects.
constexpr const _Tp * begin(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to the first element of the initializer_list.
_T1 first
second_type is the second bound type
Node iterators, used to iterate through all the hashtable.
constexpr size_t size() const noexcept
Returns the total number of bits.
Default range hashing function: use division to fold a large number into the range [0...
Struct holding two objects of arbitrary type.
iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
const _Tp & max(const _Tp &, const _Tp &)
This does what you think it does.
size_t count() const noexcept
Returns the number of bits which are set.
Uniform interface to all allocator types.
integral_constant< bool, true > true_type
The type used as a compile-time boolean with true value.
constexpr const _Tp * end(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to one past the last element of the initializer_list. ...
void swap(function< _Res(_Args...)> &__x, function< _Res(_Args...)> &__y)
Swap the targets of two polymorphic function object wrappers.
constexpr conditional< __move_if_noexcept_cond< _Tp >::value, const _Tp &, _Tp && >::type move_if_noexcept(_Tp &__x) noexcept
Conditionally convert a value to an rvalue.