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>,
46 __detail::__is_noexcept_hash<_Tp, _Hash>>>;
166 template<
typename _Key,
typename _Value,
typename _Alloc,
167 typename _ExtractKey,
typename _Equal,
168 typename _H1,
typename _H2,
typename _Hash,
169 typename _RehashPolicy,
typename _Traits>
172 _H1, _H2, _Hash, _Traits>,
174 _H1, _H2, _Hash, _RehashPolicy, _Traits>,
176 _H1, _H2, _Hash, _RehashPolicy, _Traits>,
178 _H1, _H2, _Hash, _RehashPolicy, _Traits>,
180 _H1, _H2, _Hash, _RehashPolicy, _Traits>,
182 typename __alloctr_rebind<_Alloc,
183 __detail::_Hash_node<_Value,
184 _Traits::__hash_cached::value> >::__type>
186 using __traits_type = _Traits;
187 using __hash_cached =
typename __traits_type::__hash_cached;
189 using __node_alloc_type =
190 typename __alloctr_rebind<_Alloc, __node_type>::__type;
194 using __value_alloc_traits =
196 using __node_alloc_traits =
202 typedef _Key key_type;
203 typedef _Value value_type;
204 typedef _Alloc allocator_type;
205 typedef _Equal key_equal;
209 typedef typename __value_alloc_traits::pointer pointer;
210 typedef typename __value_alloc_traits::const_pointer const_pointer;
211 typedef value_type& reference;
212 typedef const value_type& const_reference;
215 using __rehash_type = _RehashPolicy;
216 using __rehash_state =
typename __rehash_type::_State;
218 using __constant_iterators =
typename __traits_type::__constant_iterators;
219 using __unique_keys =
typename __traits_type::__unique_keys;
221 using __key_extract =
typename std::conditional<
222 __constant_iterators::value,
224 __detail::_Select1st>::type;
228 _Equal, _H1, _H2, _Hash, _Traits>;
231 using __hash_code =
typename __hashtable_base::__hash_code;
232 using __ireturn_type =
typename __hashtable_base::__ireturn_type;
235 _Equal, _H1, _H2, _Hash,
236 _RehashPolicy, _Traits>;
241 _RehashPolicy, _Traits>;
244 _Equal, _H1, _H2, _Hash,
245 _RehashPolicy, _Traits>;
247 using __reuse_or_alloc_node_type =
248 __detail::_ReuseOrAllocNode<__node_alloc_type>;
251 template<
typename _Cond>
252 using __if_hash_cached = __or_<__not_<__hash_cached>, _Cond>;
254 template<
typename _Cond>
255 using __if_hash_not_cached = __or_<__hash_cached, _Cond>;
261 struct __hash_code_base_access : __hash_code_base
262 {
using __hash_code_base::_M_bucket_index; };
266 static_assert(noexcept(declval<const __hash_code_base_access&>()
269 "Cache the hash code or qualify your functors involved"
270 " in hash code and bucket index computation with noexcept");
277 static_assert(__if_hash_cached<is_default_constructible<_H2>>::value,
278 "Functor used to map hash code to bucket index"
279 " must be default constructible");
281 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
282 typename _ExtractKeya,
typename _Equala,
283 typename _H1a,
typename _H2a,
typename _Hasha,
284 typename _RehashPolicya,
typename _Traitsa,
288 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
289 typename _ExtractKeya,
typename _Equala,
290 typename _H1a,
typename _H2a,
typename _Hasha,
291 typename _RehashPolicya,
typename _Traitsa>
294 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
295 typename _ExtractKeya,
typename _Equala,
296 typename _H1a,
typename _H2a,
typename _Hasha,
297 typename _RehashPolicya,
typename _Traitsa,
298 bool _Constant_iteratorsa,
bool _Unique_keysa>
302 using size_type =
typename __hashtable_base::size_type;
303 using difference_type =
typename __hashtable_base::difference_type;
313 __bucket_type* _M_buckets;
314 size_type _M_bucket_count;
315 __node_base _M_before_begin;
316 size_type _M_element_count;
317 _RehashPolicy _M_rehash_policy;
320 _M_base_alloc() {
return *
this; }
322 using __hashtable_alloc::_M_deallocate_buckets;
325 _M_deallocate_buckets()
326 { this->_M_deallocate_buckets(_M_buckets, _M_bucket_count); }
331 _M_bucket_begin(size_type __bkt)
const;
335 {
return static_cast<__node_type*
>(_M_before_begin._M_nxt); }
337 template<
typename _NodeGenerator>
339 _M_assign(
const _Hashtable&,
const _NodeGenerator&);
353 const _H1&,
const _H2&,
const _Hash&,
354 const _Equal&,
const _ExtractKey&,
355 const allocator_type&);
357 template<
typename _InputIterator>
358 _Hashtable(_InputIterator __first, _InputIterator __last,
359 size_type __bucket_hint,
360 const _H1&,
const _H2&,
const _Hash&,
361 const _Equal&,
const _ExtractKey&,
362 const allocator_type&);
377 __key_extract(), __a)
382 const _H1& __hf = _H1(),
383 const key_equal& __eql = key_equal(),
384 const allocator_type& __a = allocator_type())
387 __key_extract(), __a)
390 template<
typename _InputIterator>
391 _Hashtable(_InputIterator __f, _InputIterator __l,
393 const _H1& __hf = _H1(),
394 const key_equal& __eql = key_equal(),
395 const allocator_type& __a = allocator_type())
398 __key_extract(), __a)
403 const _H1& __hf = _H1(),
404 const key_equal& __eql = key_equal(),
405 const allocator_type& __a = allocator_type())
406 :
_Hashtable(__l.begin(), __l.end(), __n, __hf,
409 __key_extract(), __a)
417 noexcept(__node_alloc_traits::_S_nothrow_move())
419 constexpr
bool __move_storage =
420 __node_alloc_traits::_S_propagate_on_move_assign()
421 || __node_alloc_traits::_S_always_equal();
422 _M_move_assign(std::move(__ht),
430 __reuse_or_alloc_node_type __roan(_M_begin(), *
this);
431 _M_before_begin._M_nxt =
nullptr;
433 this->_M_insert_range(__l.begin(), __l.end(), __roan);
441 noexcept(__node_alloc_traits::_S_nothrow_swap());
446 {
return iterator(_M_begin()); }
449 begin()
const noexcept
450 {
return const_iterator(_M_begin()); }
454 {
return iterator(
nullptr); }
458 {
return const_iterator(
nullptr); }
461 cbegin()
const noexcept
462 {
return const_iterator(_M_begin()); }
465 cend()
const noexcept
466 {
return const_iterator(
nullptr); }
469 size()
const noexcept
470 {
return _M_element_count; }
473 empty()
const noexcept
474 {
return size() == 0; }
477 get_allocator()
const noexcept
478 {
return allocator_type(this->_M_node_allocator()); }
481 max_size()
const noexcept
482 {
return __node_alloc_traits::max_size(this->_M_node_allocator()); }
487 {
return this->_M_eq(); }
493 bucket_count()
const noexcept
494 {
return _M_bucket_count; }
497 max_bucket_count()
const noexcept
498 {
return max_size(); }
501 bucket_size(size_type __n)
const
505 bucket(
const key_type& __k)
const
506 {
return _M_bucket_index(__k, this->_M_hash_code(__k)); }
511 return local_iterator(*
this, _M_bucket_begin(__n),
512 __n, _M_bucket_count);
517 {
return local_iterator(*
this,
nullptr, __n, _M_bucket_count); }
520 begin(size_type __n)
const
522 return const_local_iterator(*
this, _M_bucket_begin(__n),
523 __n, _M_bucket_count);
527 end(size_type __n)
const
528 {
return const_local_iterator(*
this,
nullptr, __n, _M_bucket_count); }
532 cbegin(size_type __n)
const
534 return const_local_iterator(*
this, _M_bucket_begin(__n),
535 __n, _M_bucket_count);
539 cend(size_type __n)
const
540 {
return const_local_iterator(*
this,
nullptr, __n, _M_bucket_count); }
543 load_factor()
const noexcept
545 return static_cast<float>(
size()) / static_cast<float>(bucket_count());
554 __rehash_policy()
const
555 {
return _M_rehash_policy; }
558 __rehash_policy(
const _RehashPolicy&);
562 find(
const key_type& __k);
565 find(
const key_type& __k)
const;
568 count(
const key_type& __k)
const;
571 equal_range(
const key_type& __k);
574 equal_range(
const key_type& __k)
const;
580 {
return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); }
583 _M_bucket_index(
const key_type& __k, __hash_code __c)
const
584 {
return __hash_code_base::_M_bucket_index(__k, __c, _M_bucket_count); }
589 _M_find_before_node(size_type,
const key_type&, __hash_code)
const;
592 _M_find_node(size_type __bkt,
const key_type& __key,
593 __hash_code __c)
const
595 __node_base* __before_n = _M_find_before_node(__bkt, __key, __c);
597 return static_cast<__node_type*
>(__before_n->_M_nxt);
607 _M_remove_bucket_begin(size_type __bkt,
__node_type* __next_n,
608 size_type __next_bkt);
612 _M_get_previous_node(size_type __bkt, __node_base* __n);
618 _M_insert_unique_node(size_type __bkt, __hash_code __code,
627 template<
typename... _Args>
631 template<
typename... _Args>
634 {
return _M_emplace(cend(), __uk, std::forward<_Args>(__args)...); }
637 template<
typename... _Args>
639 _M_emplace(const_iterator,
std::true_type __uk, _Args&&... __args)
640 {
return _M_emplace(__uk, std::forward<_Args>(__args)...).first; }
642 template<
typename... _Args>
646 template<
typename _Arg,
typename _NodeGenerator>
650 template<
typename _Arg,
typename _NodeGenerator>
652 _M_insert(_Arg&& __arg,
const _NodeGenerator& __node_gen,
655 return _M_insert(cend(), std::forward<_Arg>(__arg), __node_gen,
660 template<
typename _Arg,
typename _NodeGenerator>
662 _M_insert(const_iterator, _Arg&& __arg,
const _NodeGenerator& __node_gen,
666 _M_insert(std::forward<_Arg>(__arg), __node_gen, __uk).
first;
670 template<
typename _Arg,
typename _NodeGenerator>
672 _M_insert(const_iterator, _Arg&&,
const _NodeGenerator&,
std::false_type);
681 _M_erase(size_type __bkt, __node_base* __prev_n,
__node_type* __n);
685 template<
typename... _Args>
687 emplace(_Args&&... __args)
688 {
return _M_emplace(__unique_keys(), std::forward<_Args>(__args)...); }
690 template<
typename... _Args>
692 emplace_hint(const_iterator __hint, _Args&&... __args)
694 return _M_emplace(__hint, __unique_keys(),
695 std::forward<_Args>(__args)...);
702 erase(const_iterator);
707 {
return erase(const_iterator(__it)); }
710 erase(
const key_type& __k)
712 if (__builtin_expect(_M_bucket_count == 0,
false))
714 return _M_erase(__unique_keys(), __k);
718 erase(const_iterator, const_iterator);
724 void rehash(size_type __n);
738 void _M_rehash(size_type __n,
const __rehash_state& __state);
743 template<
typename _Key,
typename _Value,
744 typename _Alloc,
typename _ExtractKey,
typename _Equal,
745 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
747 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
748 _Equal, _H1, _H2, _Hash, _RehashPolicy,
749 _Traits>::__node_type*
750 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
751 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
752 _M_bucket_begin(size_type __bkt)
const
754 __node_base* __n = _M_buckets[__bkt];
755 return __n ?
static_cast<__node_type*
>(__n->_M_nxt) :
nullptr;
758 template<
typename _Key,
typename _Value,
759 typename _Alloc,
typename _ExtractKey,
typename _Equal,
760 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
762 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
763 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
764 _Hashtable(size_type __bucket_hint,
765 const _H1& __h1,
const _H2& __h2,
const _Hash& __h,
766 const _Equal& __eq,
const _ExtractKey& __exk,
767 const allocator_type& __a)
768 : __hashtable_base(__exk, __h1, __h2, __h, __eq),
771 __hashtable_alloc(__node_alloc_type(__a)),
775 _M_bucket_count = _M_rehash_policy._M_next_bkt(__bucket_hint);
776 _M_buckets = this->_M_allocate_buckets(_M_bucket_count);
779 template<
typename _Key,
typename _Value,
780 typename _Alloc,
typename _ExtractKey,
typename _Equal,
781 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
783 template<
typename _InputIterator>
784 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
785 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
786 _Hashtable(_InputIterator __f, _InputIterator __l,
787 size_type __bucket_hint,
788 const _H1& __h1,
const _H2& __h2,
const _Hash& __h,
789 const _Equal& __eq,
const _ExtractKey& __exk,
790 const allocator_type& __a)
791 : __hashtable_base(__exk, __h1, __h2, __h, __eq),
794 __hashtable_alloc(__node_alloc_type(__a)),
798 auto __nb_elems = __detail::__distance_fw(__f, __l);
800 _M_rehash_policy._M_next_bkt(
801 std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems),
804 _M_buckets = this->_M_allocate_buckets(_M_bucket_count);
807 for (; __f != __l; ++__f)
813 _M_deallocate_buckets();
814 __throw_exception_again;
818 template<
typename _Key,
typename _Value,
819 typename _Alloc,
typename _ExtractKey,
typename _Equal,
820 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
822 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
823 _H1, _H2, _Hash, _RehashPolicy, _Traits>&
824 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
825 _H1, _H2, _Hash, _RehashPolicy, _Traits>::operator=(
826 const _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
827 _H1, _H2, _Hash, _RehashPolicy, _Traits>& __ht)
832 if (__node_alloc_traits::_S_propagate_on_copy_assign())
834 auto& __this_alloc = this->_M_node_allocator();
835 auto& __that_alloc = __ht._M_node_allocator();
836 if (!__node_alloc_traits::_S_always_equal()
837 && __this_alloc != __that_alloc)
840 this->_M_deallocate_nodes(_M_begin());
841 if (__builtin_expect(_M_bucket_count != 0,
true))
842 _M_deallocate_buckets();
844 std::__alloc_on_copy(__this_alloc, __that_alloc);
845 __hashtable_base::operator=(__ht);
846 _M_bucket_count = __ht._M_bucket_count;
847 _M_element_count = __ht._M_element_count;
848 _M_rehash_policy = __ht._M_rehash_policy;
852 [
this](
const __node_type* __n)
853 {
return this->_M_allocate_node(__n->_M_v()); });
860 __throw_exception_again;
864 std::__alloc_on_copy(__this_alloc, __that_alloc);
868 __bucket_type* __former_buckets =
nullptr;
869 std::size_t __former_bucket_count = _M_bucket_count;
870 const __rehash_state& __former_state = _M_rehash_policy._M_state();
872 if (_M_bucket_count != __ht._M_bucket_count)
874 __former_buckets = _M_buckets;
875 _M_buckets = this->_M_allocate_buckets(__ht._M_bucket_count);
876 _M_bucket_count = __ht._M_bucket_count;
879 __builtin_memset(_M_buckets, 0,
880 _M_bucket_count *
sizeof(__bucket_type));
884 __hashtable_base::operator=(__ht);
885 _M_element_count = __ht._M_element_count;
886 _M_rehash_policy = __ht._M_rehash_policy;
887 __reuse_or_alloc_node_type __roan(_M_begin(), *
this);
888 _M_before_begin._M_nxt =
nullptr;
890 [&__roan](
const __node_type* __n)
891 {
return __roan(__n->_M_v()); });
892 if (__former_buckets)
893 this->_M_deallocate_buckets(__former_buckets,
894 __former_bucket_count);
898 if (__former_buckets)
901 _M_deallocate_buckets();
902 _M_rehash_policy._M_reset(__former_state);
903 _M_buckets = __former_buckets;
904 _M_bucket_count = __former_bucket_count;
906 __builtin_memset(_M_buckets, 0,
907 _M_bucket_count *
sizeof(__bucket_type));
908 __throw_exception_again;
913 template<
typename _Key,
typename _Value,
914 typename _Alloc,
typename _ExtractKey,
typename _Equal,
915 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
917 template<
typename _NodeGenerator>
919 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
920 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
921 _M_assign(
const _Hashtable& __ht,
const _NodeGenerator& __node_gen)
923 __bucket_type* __buckets =
nullptr;
925 _M_buckets = __buckets = this->_M_allocate_buckets(_M_bucket_count);
929 if (!__ht._M_before_begin._M_nxt)
934 __node_type* __ht_n = __ht._M_begin();
935 __node_type* __this_n = __node_gen(__ht_n);
936 this->_M_copy_code(__this_n, __ht_n);
937 _M_before_begin._M_nxt = __this_n;
938 _M_buckets[_M_bucket_index(__this_n)] = &_M_before_begin;
941 __node_base* __prev_n = __this_n;
942 for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next())
944 __this_n = __node_gen(__ht_n);
945 __prev_n->_M_nxt = __this_n;
946 this->_M_copy_code(__this_n, __ht_n);
947 size_type __bkt = _M_bucket_index(__this_n);
948 if (!_M_buckets[__bkt])
949 _M_buckets[__bkt] = __prev_n;
957 _M_deallocate_buckets();
958 __throw_exception_again;
962 template<
typename _Key,
typename _Value,
963 typename _Alloc,
typename _ExtractKey,
typename _Equal,
964 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
967 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
968 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
971 _M_rehash_policy._M_reset();
973 _M_buckets =
nullptr;
974 _M_before_begin._M_nxt =
nullptr;
975 _M_element_count = 0;
978 template<
typename _Key,
typename _Value,
979 typename _Alloc,
typename _ExtractKey,
typename _Equal,
980 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
983 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
984 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
987 this->_M_deallocate_nodes(_M_begin());
988 if (__builtin_expect(_M_bucket_count != 0,
true))
989 _M_deallocate_buckets();
991 __hashtable_base::operator=(std::move(__ht));
992 _M_rehash_policy = __ht._M_rehash_policy;
993 _M_buckets = __ht._M_buckets;
994 _M_bucket_count = __ht._M_bucket_count;
995 _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt;
996 _M_element_count = __ht._M_element_count;
997 std::__alloc_on_move(this->_M_node_allocator(), __ht._M_node_allocator());
1002 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
1006 template<
typename _Key,
typename _Value,
1007 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1008 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1011 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1012 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1015 if (__ht._M_node_allocator() == this->_M_node_allocator())
1020 __bucket_type* __former_buckets =
nullptr;
1021 size_type __former_bucket_count = _M_bucket_count;
1022 const __rehash_state& __former_state = _M_rehash_policy._M_state();
1024 if (_M_bucket_count != __ht._M_bucket_count)
1026 __former_buckets = _M_buckets;
1027 _M_buckets = this->_M_allocate_buckets(__ht._M_bucket_count);
1028 _M_bucket_count = __ht._M_bucket_count;
1031 __builtin_memset(_M_buckets, 0,
1032 _M_bucket_count *
sizeof(__bucket_type));
1036 __hashtable_base::operator=(std::move(__ht));
1037 _M_element_count = __ht._M_element_count;
1038 _M_rehash_policy = __ht._M_rehash_policy;
1039 __reuse_or_alloc_node_type __roan(_M_begin(), *
this);
1040 _M_before_begin._M_nxt =
nullptr;
1042 [&__roan](__node_type* __n)
1048 if (__former_buckets)
1050 _M_deallocate_buckets();
1051 _M_rehash_policy._M_reset(__former_state);
1052 _M_buckets = __former_buckets;
1053 _M_bucket_count = __former_bucket_count;
1055 __builtin_memset(_M_buckets, 0,
1056 _M_bucket_count *
sizeof(__bucket_type));
1057 __throw_exception_again;
1062 template<
typename _Key,
typename _Value,
1063 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1064 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1066 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1067 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1068 _Hashtable(
const _Hashtable& __ht)
1069 : __hashtable_base(__ht),
1071 __rehash_base(__ht),
1073 __node_alloc_traits::_S_select_on_copy(__ht._M_node_allocator())),
1075 _M_bucket_count(__ht._M_bucket_count),
1076 _M_element_count(__ht._M_element_count),
1077 _M_rehash_policy(__ht._M_rehash_policy)
1080 [
this](
const __node_type* __n)
1081 {
return this->_M_allocate_node(__n->_M_v()); });
1084 template<
typename _Key,
typename _Value,
1085 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1086 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1088 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1089 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1090 _Hashtable(_Hashtable&& __ht) noexcept
1091 : __hashtable_base(__ht),
1093 __rehash_base(__ht),
1094 __hashtable_alloc(std::move(__ht._M_base_alloc())),
1095 _M_buckets(__ht._M_buckets),
1096 _M_bucket_count(__ht._M_bucket_count),
1097 _M_before_begin(__ht._M_before_begin._M_nxt),
1098 _M_element_count(__ht._M_element_count),
1099 _M_rehash_policy(__ht._M_rehash_policy)
1104 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
1108 template<
typename _Key,
typename _Value,
1109 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1110 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1112 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1113 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1114 _Hashtable(
const _Hashtable& __ht,
const allocator_type& __a)
1115 : __hashtable_base(__ht),
1117 __rehash_base(__ht),
1118 __hashtable_alloc(__node_alloc_type(__a)),
1120 _M_bucket_count(__ht._M_bucket_count),
1121 _M_element_count(__ht._M_element_count),
1122 _M_rehash_policy(__ht._M_rehash_policy)
1125 [
this](
const __node_type* __n)
1126 {
return this->_M_allocate_node(__n->_M_v()); });
1129 template<
typename _Key,
typename _Value,
1130 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1131 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1133 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1134 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1135 _Hashtable(_Hashtable&& __ht,
const allocator_type& __a)
1136 : __hashtable_base(__ht),
1138 __rehash_base(__ht),
1139 __hashtable_alloc(__node_alloc_type(__a)),
1141 _M_bucket_count(__ht._M_bucket_count),
1142 _M_element_count(__ht._M_element_count),
1143 _M_rehash_policy(__ht._M_rehash_policy)
1145 if (__ht._M_node_allocator() == this->_M_node_allocator())
1147 _M_buckets = __ht._M_buckets;
1148 _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt;
1152 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
1158 [
this](__node_type* __n)
1160 return this->_M_allocate_node(
1167 template<
typename _Key,
typename _Value,
1168 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1169 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1171 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1172 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1173 ~_Hashtable() noexcept
1177 _M_deallocate_buckets();
1180 template<
typename _Key,
typename _Value,
1181 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1182 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1185 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1186 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1187 swap(_Hashtable& __x)
1188 noexcept(__node_alloc_traits::_S_nothrow_swap())
1195 std::__alloc_on_swap(this->_M_node_allocator(), __x._M_node_allocator());
1196 std::swap(_M_rehash_policy, __x._M_rehash_policy);
1197 std::swap(_M_buckets, __x._M_buckets);
1198 std::swap(_M_bucket_count, __x._M_bucket_count);
1199 std::swap(_M_before_begin._M_nxt, __x._M_before_begin._M_nxt);
1200 std::swap(_M_element_count, __x._M_element_count);
1205 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
1207 __x._M_buckets[__x._M_bucket_index(__x._M_begin())]
1208 = &__x._M_before_begin;
1211 template<
typename _Key,
typename _Value,
1212 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1213 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1216 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1217 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1218 __rehash_policy(
const _RehashPolicy& __pol)
1220 size_type __n_bkt = __pol._M_bkt_for_elements(_M_element_count);
1221 __n_bkt = __pol._M_next_bkt(__n_bkt);
1222 if (__n_bkt != _M_bucket_count)
1223 _M_rehash(__n_bkt, _M_rehash_policy._M_state());
1224 _M_rehash_policy = __pol;
1227 template<
typename _Key,
typename _Value,
1228 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1229 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1231 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1232 _H1, _H2, _Hash, _RehashPolicy,
1234 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1235 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1236 find(
const key_type& __k)
1238 if (__builtin_expect(_M_bucket_count == 0,
false))
1241 __hash_code __code = this->_M_hash_code(__k);
1242 std::size_t __n = _M_bucket_index(__k, __code);
1243 __node_type* __p = _M_find_node(__n, __k, __code);
1244 return __p ? iterator(__p) :
end();
1247 template<
typename _Key,
typename _Value,
1248 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1249 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1251 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1252 _H1, _H2, _Hash, _RehashPolicy,
1253 _Traits>::const_iterator
1254 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1255 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1256 find(
const key_type& __k)
const
1258 if (__builtin_expect(_M_bucket_count == 0,
false))
1261 __hash_code __code = this->_M_hash_code(__k);
1262 std::size_t __n = _M_bucket_index(__k, __code);
1263 __node_type* __p = _M_find_node(__n, __k, __code);
1264 return __p ? const_iterator(__p) :
end();
1267 template<
typename _Key,
typename _Value,
1268 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1269 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1271 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1272 _H1, _H2, _Hash, _RehashPolicy,
1274 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1275 _H1, _H2, _Hash, _RehashPolicy, _Traits>
::
1276 count(
const key_type& __k)
const
1278 if (__builtin_expect(_M_bucket_count == 0,
false))
1281 __hash_code __code = this->_M_hash_code(__k);
1282 std::size_t __n = _M_bucket_index(__k, __code);
1283 __node_type* __p = _M_bucket_begin(__n);
1287 std::size_t __result = 0;
1288 for (;; __p = __p->_M_next())
1290 if (this->_M_equals(__k, __code, __p))
1297 if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
1303 template<
typename _Key,
typename _Value,
1304 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1305 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1307 std::pair<
typename _Hashtable<_Key, _Value, _Alloc,
1308 _ExtractKey, _Equal, _H1,
1309 _H2, _Hash, _RehashPolicy,
1311 typename _Hashtable<_Key, _Value, _Alloc,
1312 _ExtractKey, _Equal, _H1,
1313 _H2, _Hash, _RehashPolicy,
1315 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1316 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1317 equal_range(
const key_type& __k)
1319 if (__builtin_expect(_M_bucket_count == 0,
false))
1322 __hash_code __code = this->_M_hash_code(__k);
1323 std::size_t __n = _M_bucket_index(__k, __code);
1324 __node_type* __p = _M_find_node(__n, __k, __code);
1328 __node_type* __p1 = __p->_M_next();
1329 while (__p1 && _M_bucket_index(__p1) == __n
1330 && this->_M_equals(__k, __code, __p1))
1331 __p1 = __p1->_M_next();
1339 template<
typename _Key,
typename _Value,
1340 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1341 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1343 std::pair<
typename _Hashtable<_Key, _Value, _Alloc,
1344 _ExtractKey, _Equal, _H1,
1345 _H2, _Hash, _RehashPolicy,
1346 _Traits>::const_iterator,
1347 typename _Hashtable<_Key, _Value, _Alloc,
1348 _ExtractKey, _Equal, _H1,
1349 _H2, _Hash, _RehashPolicy,
1350 _Traits>::const_iterator>
1351 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1352 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1353 equal_range(
const key_type& __k)
const
1355 if (__builtin_expect(_M_bucket_count == 0,
false))
1358 __hash_code __code = this->_M_hash_code(__k);
1359 std::size_t __n = _M_bucket_index(__k, __code);
1360 __node_type* __p = _M_find_node(__n, __k, __code);
1364 __node_type* __p1 = __p->_M_next();
1365 while (__p1 && _M_bucket_index(__p1) == __n
1366 && this->_M_equals(__k, __code, __p1))
1367 __p1 = __p1->_M_next();
1369 return std::make_pair(const_iterator(__p), const_iterator(__p1));
1377 template<
typename _Key,
typename _Value,
1378 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1379 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1381 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
1382 _Equal, _H1, _H2, _Hash, _RehashPolicy,
1383 _Traits>::__node_base*
1384 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1385 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1386 _M_find_before_node(size_type __n,
const key_type& __k,
1387 __hash_code __code)
const
1389 __node_base* __prev_p = _M_buckets[__n];
1393 for (__node_type* __p = static_cast<__node_type*>(__prev_p->_M_nxt);;
1394 __p = __p->_M_next())
1396 if (this->_M_equals(__k, __code, __p))
1399 if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
1406 template<
typename _Key,
typename _Value,
1407 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1408 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1411 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1412 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1413 _M_insert_bucket_begin(size_type __bkt, __node_type* __node)
1415 if (_M_buckets[__bkt])
1419 __node->_M_nxt = _M_buckets[__bkt]->_M_nxt;
1420 _M_buckets[__bkt]->_M_nxt = __node;
1427 __node->_M_nxt = _M_before_begin._M_nxt;
1428 _M_before_begin._M_nxt = __node;
1432 _M_buckets[_M_bucket_index(__node->_M_next())] = __node;
1433 _M_buckets[__bkt] = &_M_before_begin;
1437 template<
typename _Key,
typename _Value,
1438 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1439 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1442 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1443 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1444 _M_remove_bucket_begin(size_type __bkt, __node_type* __next,
1445 size_type __next_bkt)
1447 if (!__next || __next_bkt != __bkt)
1452 _M_buckets[__next_bkt] = _M_buckets[__bkt];
1455 if (&_M_before_begin == _M_buckets[__bkt])
1456 _M_before_begin._M_nxt = __next;
1457 _M_buckets[__bkt] =
nullptr;
1461 template<
typename _Key,
typename _Value,
1462 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1463 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1465 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey,
1466 _Equal, _H1, _H2, _Hash, _RehashPolicy,
1467 _Traits>::__node_base*
1468 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1469 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1470 _M_get_previous_node(size_type __bkt, __node_base* __n)
1472 __node_base* __prev_n = _M_buckets[__bkt];
1473 while (__prev_n->_M_nxt != __n)
1474 __prev_n = __prev_n->_M_nxt;
1478 template<
typename _Key,
typename _Value,
1479 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1480 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1482 template<
typename... _Args>
1483 std::pair<
typename _Hashtable<_Key, _Value, _Alloc,
1484 _ExtractKey, _Equal, _H1,
1485 _H2, _Hash, _RehashPolicy,
1486 _Traits>::iterator,
bool>
1487 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1488 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1492 __node_type* __node = this->_M_allocate_node(std::forward<_Args>(__args)...);
1493 const key_type& __k = this->_M_extract()(__node->_M_v());
1497 __code = this->_M_hash_code(__k);
1501 this->_M_deallocate_node(__node);
1502 __throw_exception_again;
1505 size_type __bkt = _M_bucket_index(__k, __code);
1506 if (__node_type* __p = _M_find_node(__bkt, __k, __code))
1509 this->_M_deallocate_node(__node);
1514 return std::make_pair(_M_insert_unique_node(__bkt, __code, __node),
1518 template<
typename _Key,
typename _Value,
1519 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1520 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1522 template<
typename... _Args>
1523 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1524 _H1, _H2, _Hash, _RehashPolicy,
1526 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1527 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1531 __node_type* __node =
1532 this->_M_allocate_node(std::forward<_Args>(__args)...);
1537 __code = this->_M_hash_code(this->_M_extract()(__node->_M_v()));
1541 this->_M_deallocate_node(__node);
1542 __throw_exception_again;
1545 return _M_insert_multi_node(__hint._M_cur, __code, __node);
1548 template<
typename _Key,
typename _Value,
1549 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1550 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1552 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1553 _H1, _H2, _Hash, _RehashPolicy,
1555 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1556 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1557 _M_insert_unique_node(size_type __bkt, __hash_code __code,
1558 __node_type* __node)
1560 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
1562 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
1566 if (__do_rehash.
first)
1568 _M_rehash(__do_rehash.
second, __saved_state);
1569 __bkt = _M_bucket_index(this->_M_extract()(__node->_M_v()), __code);
1572 this->_M_store_code(__node, __code);
1575 _M_insert_bucket_begin(__bkt, __node);
1577 return iterator(__node);
1581 this->_M_deallocate_node(__node);
1582 __throw_exception_again;
1588 template<
typename _Key,
typename _Value,
1589 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1590 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1592 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1593 _H1, _H2, _Hash, _RehashPolicy,
1595 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1596 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1597 _M_insert_multi_node(__node_type* __hint, __hash_code __code,
1598 __node_type* __node)
1600 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
1602 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
1606 if (__do_rehash.
first)
1607 _M_rehash(__do_rehash.
second, __saved_state);
1609 this->_M_store_code(__node, __code);
1610 const key_type& __k = this->_M_extract()(__node->_M_v());
1611 size_type __bkt = _M_bucket_index(__k, __code);
1616 = __builtin_expect(__hint !=
nullptr,
false)
1617 && this->_M_equals(__k, __code, __hint)
1619 : _M_find_before_node(__bkt, __k, __code);
1623 __node->_M_nxt = __prev->_M_nxt;
1624 __prev->_M_nxt = __node;
1625 if (__builtin_expect(__prev == __hint,
false))
1629 && !this->_M_equals(__k, __code, __node->_M_next()))
1631 size_type __next_bkt = _M_bucket_index(__node->_M_next());
1632 if (__next_bkt != __bkt)
1633 _M_buckets[__next_bkt] = __node;
1641 _M_insert_bucket_begin(__bkt, __node);
1643 return iterator(__node);
1647 this->_M_deallocate_node(__node);
1648 __throw_exception_again;
1653 template<
typename _Key,
typename _Value,
1654 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1655 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1657 template<
typename _Arg,
typename _NodeGenerator>
1658 std::pair<
typename _Hashtable<_Key, _Value, _Alloc,
1659 _ExtractKey, _Equal, _H1,
1660 _H2, _Hash, _RehashPolicy,
1661 _Traits>::iterator,
bool>
1662 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1663 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1664 _M_insert(_Arg&& __v,
const _NodeGenerator& __node_gen,
std::true_type)
1666 const key_type& __k = this->_M_extract()(__v);
1667 __hash_code __code = this->_M_hash_code(__k);
1668 size_type __bkt = _M_bucket_index(__k, __code);
1670 __node_type* __n = _M_find_node(__bkt, __k, __code);
1674 __n = __node_gen(std::forward<_Arg>(__v));
1675 return std::make_pair(_M_insert_unique_node(__bkt, __code, __n),
true);
1679 template<
typename _Key,
typename _Value,
1680 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1681 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1683 template<
typename _Arg,
typename _NodeGenerator>
1684 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1685 _H1, _H2, _Hash, _RehashPolicy,
1687 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1688 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1689 _M_insert(const_iterator __hint, _Arg&& __v,
1690 const _NodeGenerator& __node_gen,
1695 __hash_code __code = this->_M_hash_code(this->_M_extract()(__v));
1698 __node_type* __node = __node_gen(std::forward<_Arg>(__v));
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 erase(const_iterator __it)
1714 __node_type* __n = __it._M_cur;
1715 std::size_t __bkt = _M_bucket_index(__n);
1720 __node_base* __prev_n = _M_get_previous_node(__bkt, __n);
1721 return _M_erase(__bkt, __prev_n, __n);
1724 template<
typename _Key,
typename _Value,
1725 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1726 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1728 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1729 _H1, _H2, _Hash, _RehashPolicy,
1731 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1732 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1733 _M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n)
1735 if (__prev_n == _M_buckets[__bkt])
1736 _M_remove_bucket_begin(__bkt, __n->_M_next(),
1737 __n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0);
1738 else if (__n->_M_nxt)
1740 size_type __next_bkt = _M_bucket_index(__n->_M_next());
1741 if (__next_bkt != __bkt)
1742 _M_buckets[__next_bkt] = __prev_n;
1745 __prev_n->_M_nxt = __n->_M_nxt;
1746 iterator __result(__n->_M_next());
1747 this->_M_deallocate_node(__n);
1753 template<
typename _Key,
typename _Value,
1754 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1755 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1757 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1758 _H1, _H2, _Hash, _RehashPolicy,
1760 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1761 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1764 __hash_code __code = this->_M_hash_code(__k);
1765 std::size_t __bkt = _M_bucket_index(__k, __code);
1768 __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code);
1773 __node_type* __n =
static_cast<__node_type*
>(__prev_n->_M_nxt);
1774 _M_erase(__bkt, __prev_n, __n);
1778 template<
typename _Key,
typename _Value,
1779 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1780 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1782 typename _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1783 _H1, _H2, _Hash, _RehashPolicy,
1785 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1786 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1789 __hash_code __code = this->_M_hash_code(__k);
1790 std::size_t __bkt = _M_bucket_index(__k, __code);
1793 __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code);
1803 __node_type* __n =
static_cast<__node_type*
>(__prev_n->_M_nxt);
1804 __node_type* __n_last = __n;
1805 std::size_t __n_last_bkt = __bkt;
1808 __n_last = __n_last->_M_next();
1811 __n_last_bkt = _M_bucket_index(__n_last);
1813 while (__n_last_bkt == __bkt && this->_M_equals(__k, __code, __n_last));
1816 size_type __result = 0;
1819 __node_type* __p = __n->_M_next();
1820 this->_M_deallocate_node(__n);
1825 while (__n != __n_last);
1827 if (__prev_n == _M_buckets[__bkt])
1828 _M_remove_bucket_begin(__bkt, __n_last, __n_last_bkt);
1829 else if (__n_last && __n_last_bkt != __bkt)
1830 _M_buckets[__n_last_bkt] = __prev_n;
1831 __prev_n->_M_nxt = __n_last;
1835 template<
typename _Key,
typename _Value,
1836 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1837 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
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 erase(const_iterator __first, const_iterator __last)
1846 __node_type* __n = __first._M_cur;
1847 __node_type* __last_n = __last._M_cur;
1848 if (__n == __last_n)
1849 return iterator(__n);
1851 std::size_t __bkt = _M_bucket_index(__n);
1853 __node_base* __prev_n = _M_get_previous_node(__bkt, __n);
1854 bool __is_bucket_begin = __n == _M_bucket_begin(__bkt);
1855 std::size_t __n_bkt = __bkt;
1860 __node_type* __tmp = __n;
1861 __n = __n->_M_next();
1862 this->_M_deallocate_node(__tmp);
1866 __n_bkt = _M_bucket_index(__n);
1868 while (__n != __last_n && __n_bkt == __bkt);
1869 if (__is_bucket_begin)
1870 _M_remove_bucket_begin(__bkt, __n, __n_bkt);
1871 if (__n == __last_n)
1873 __is_bucket_begin =
true;
1877 if (__n && (__n_bkt != __bkt || __is_bucket_begin))
1878 _M_buckets[__n_bkt] = __prev_n;
1879 __prev_n->_M_nxt = __n;
1880 return iterator(__n);
1883 template<
typename _Key,
typename _Value,
1884 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1885 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1888 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1889 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1892 this->_M_deallocate_nodes(_M_begin());
1893 __builtin_memset(_M_buckets, 0, _M_bucket_count *
sizeof(__bucket_type));
1894 _M_element_count = 0;
1895 _M_before_begin._M_nxt =
nullptr;
1898 template<
typename _Key,
typename _Value,
1899 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1900 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1903 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1904 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1905 rehash(size_type __n)
1907 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
1908 std::size_t __buckets
1909 =
std::max(_M_rehash_policy._M_bkt_for_elements(_M_element_count + 1),
1911 __buckets = _M_rehash_policy._M_next_bkt(__buckets);
1913 if (__buckets != _M_bucket_count)
1914 _M_rehash(__buckets, __saved_state);
1917 _M_rehash_policy._M_reset(__saved_state);
1920 template<
typename _Key,
typename _Value,
1921 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1922 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1925 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1926 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1927 _M_rehash(size_type __n,
const __rehash_state& __state)
1931 _M_rehash_aux(__n, __unique_keys());
1937 _M_rehash_policy._M_reset(__state);
1938 __throw_exception_again;
1943 template<
typename _Key,
typename _Value,
1944 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1945 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1948 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1949 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1952 __bucket_type* __new_buckets = this->_M_allocate_buckets(__n);
1953 __node_type* __p = _M_begin();
1954 _M_before_begin._M_nxt =
nullptr;
1955 std::size_t __bbegin_bkt = 0;
1958 __node_type* __next = __p->_M_next();
1959 std::size_t __bkt = __hash_code_base::_M_bucket_index(__p, __n);
1960 if (!__new_buckets[__bkt])
1962 __p->_M_nxt = _M_before_begin._M_nxt;
1963 _M_before_begin._M_nxt = __p;
1964 __new_buckets[__bkt] = &_M_before_begin;
1966 __new_buckets[__bbegin_bkt] = __p;
1967 __bbegin_bkt = __bkt;
1971 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
1972 __new_buckets[__bkt]->_M_nxt = __p;
1977 if (__builtin_expect(_M_bucket_count != 0,
true))
1978 _M_deallocate_buckets();
1979 _M_bucket_count = __n;
1980 _M_buckets = __new_buckets;
1985 template<
typename _Key,
typename _Value,
1986 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1987 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1990 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1991 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1994 __bucket_type* __new_buckets = this->_M_allocate_buckets(__n);
1996 __node_type* __p = _M_begin();
1997 _M_before_begin._M_nxt =
nullptr;
1998 std::size_t __bbegin_bkt = 0;
1999 std::size_t __prev_bkt = 0;
2000 __node_type* __prev_p =
nullptr;
2001 bool __check_bucket =
false;
2005 __node_type* __next = __p->_M_next();
2006 std::size_t __bkt = __hash_code_base::_M_bucket_index(__p, __n);
2008 if (__prev_p && __prev_bkt == __bkt)
2013 __p->_M_nxt = __prev_p->_M_nxt;
2014 __prev_p->_M_nxt = __p;
2021 __check_bucket =
true;
2029 if (__prev_p->_M_nxt)
2031 std::size_t __next_bkt
2032 = __hash_code_base::_M_bucket_index(__prev_p->_M_next(),
2034 if (__next_bkt != __prev_bkt)
2035 __new_buckets[__next_bkt] = __prev_p;
2037 __check_bucket =
false;
2040 if (!__new_buckets[__bkt])
2042 __p->_M_nxt = _M_before_begin._M_nxt;
2043 _M_before_begin._M_nxt = __p;
2044 __new_buckets[__bkt] = &_M_before_begin;
2046 __new_buckets[__bbegin_bkt] = __p;
2047 __bbegin_bkt = __bkt;
2051 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2052 __new_buckets[__bkt]->_M_nxt = __p;
2060 if (__check_bucket && __prev_p->_M_nxt)
2062 std::size_t __next_bkt
2063 = __hash_code_base::_M_bucket_index(__prev_p->_M_next(), __n);
2064 if (__next_bkt != __prev_bkt)
2065 __new_buckets[__next_bkt] = __prev_p;
2068 if (__builtin_expect(_M_bucket_count != 0,
true))
2069 _M_deallocate_buckets();
2070 _M_bucket_count = __n;
2071 _M_buckets = __new_buckets;
2074 _GLIBCXX_END_NAMESPACE_VERSION
2077 #endif // _HASHTABLE_H
Node iterators, used to iterate through all the hashtable.
Struct holding two objects of arbitrary type.
Default ranged hash function H. In principle it should be a function object composed from objects of ...
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 C++98 and C++0x allocators.
Uniform interface to all allocator types.
integral_constant< bool, true > true_type
The type used as a compile-time boolean with true value.
Node const_iterators, used to iterate through all the hashtable.
_T2 second
first is a copy of the first object
constexpr const _Tp * end(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to one past the last element of the initializer_list. ...
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.
iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
Default range hashing function: use division to fold a large number into the range [0...
_T1 first
second_type is the second bound type
constexpr size_t size() const noexcept
Returns the total number of bits.
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.