31 #define _HASHTABLE_H 1 33 #pragma GCC system_header 36 #if __cplusplus > 201402L 40 namespace std _GLIBCXX_VISIBILITY(default)
42 _GLIBCXX_BEGIN_NAMESPACE_VERSION
44 template<
typename _Tp,
typename _Hash>
47 __is_fast_hash<_Hash>,
49 __is_nothrow_invocable<const _Hash&, const _Tp&>>>;
169 template<
typename _Key,
typename _Value,
typename _Alloc,
170 typename _ExtractKey,
typename _Equal,
171 typename _H1,
typename _H2,
typename _Hash,
172 typename _RehashPolicy,
typename _Traits>
175 _H1, _H2, _Hash, _Traits>,
177 _H1, _H2, _Hash, _RehashPolicy, _Traits>,
179 _H1, _H2, _Hash, _RehashPolicy, _Traits>,
181 _H1, _H2, _Hash, _RehashPolicy, _Traits>,
183 _H1, _H2, _Hash, _RehashPolicy, _Traits>,
185 __alloc_rebind<_Alloc,
186 __detail::_Hash_node<_Value,
187 _Traits::__hash_cached::value>>>
189 static_assert(
is_same<
typename remove_cv<_Value>::type, _Value>::value,
190 "unordered container must have a non-const, non-volatile value_type");
191 #ifdef __STRICT_ANSI__ 193 "unordered container must have the same value_type as its allocator");
196 using __traits_type = _Traits;
197 using __hash_cached =
typename __traits_type::__hash_cached;
199 using __node_alloc_type = __alloc_rebind<_Alloc, __node_type>;
203 using __value_alloc_traits =
204 typename __hashtable_alloc::__value_alloc_traits;
205 using __node_alloc_traits =
211 typedef _Key key_type;
212 typedef _Value value_type;
213 typedef _Alloc allocator_type;
214 typedef _Equal key_equal;
218 typedef typename __value_alloc_traits::pointer pointer;
219 typedef typename __value_alloc_traits::const_pointer const_pointer;
220 typedef value_type& reference;
221 typedef const value_type& const_reference;
224 using __rehash_type = _RehashPolicy;
225 using __rehash_state =
typename __rehash_type::_State;
227 using __constant_iterators =
typename __traits_type::__constant_iterators;
228 using __unique_keys =
typename __traits_type::__unique_keys;
231 __constant_iterators::value,
233 __detail::_Select1st>::type;
236 _Hashtable_base<_Key, _Value, _ExtractKey,
237 _Equal, _H1, _H2, _Hash, _Traits>;
240 using __hash_code =
typename __hashtable_base::__hash_code;
241 using __ireturn_type =
typename __hashtable_base::__ireturn_type;
244 _Equal, _H1, _H2, _Hash,
245 _RehashPolicy, _Traits>;
250 _RehashPolicy, _Traits>;
253 _Equal, _H1, _H2, _Hash,
254 _RehashPolicy, _Traits>;
256 using __reuse_or_alloc_node_type =
257 __detail::_ReuseOrAllocNode<__node_alloc_type>;
260 template<
typename _Cond>
261 using __if_hash_cached = __or_<__not_<__hash_cached>, _Cond>;
263 template<
typename _Cond>
264 using __if_hash_not_cached = __or_<__hash_cached, _Cond>;
270 struct __hash_code_base_access : __hash_code_base
271 {
using __hash_code_base::_M_bucket_index; };
275 static_assert(noexcept(declval<const __hash_code_base_access&>()
278 "Cache the hash code or qualify your functors involved" 279 " in hash code and bucket index computation with noexcept");
287 "Functor used to map hash code to bucket index" 288 " must be default constructible");
290 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
291 typename _ExtractKeya,
typename _Equala,
292 typename _H1a,
typename _H2a,
typename _Hasha,
293 typename _RehashPolicya,
typename _Traitsa,
297 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
298 typename _ExtractKeya,
typename _Equala,
299 typename _H1a,
typename _H2a,
typename _Hasha,
300 typename _RehashPolicya,
typename _Traitsa>
303 template<
typename _Keya,
typename _Valuea,
typename _Alloca,
304 typename _ExtractKeya,
typename _Equala,
305 typename _H1a,
typename _H2a,
typename _Hasha,
306 typename _RehashPolicya,
typename _Traitsa,
307 bool _Constant_iteratorsa>
311 using size_type =
typename __hashtable_base::size_type;
312 using difference_type =
typename __hashtable_base::difference_type;
318 using const_local_iterator =
typename __hashtable_base::
319 const_local_iterator;
321 #if __cplusplus > 201402L 322 using node_type = _Node_handle<_Key, _Value, __node_alloc_type>;
323 using insert_return_type = _Node_insert_return<iterator, node_type>;
327 __bucket_type* _M_buckets = &_M_single_bucket;
328 size_type _M_bucket_count = 1;
329 __node_base _M_before_begin;
330 size_type _M_element_count = 0;
331 _RehashPolicy _M_rehash_policy;
339 __bucket_type _M_single_bucket =
nullptr;
342 _M_uses_single_bucket(__bucket_type* __bkts)
const 343 {
return __builtin_expect(__bkts == &_M_single_bucket,
false); }
346 _M_uses_single_bucket()
const 347 {
return _M_uses_single_bucket(_M_buckets); }
350 _M_base_alloc() {
return *
this; }
353 _M_allocate_buckets(size_type __n)
355 if (__builtin_expect(__n == 1,
false))
357 _M_single_bucket =
nullptr;
358 return &_M_single_bucket;
361 return __hashtable_alloc::_M_allocate_buckets(__n);
365 _M_deallocate_buckets(__bucket_type* __bkts, size_type __n)
367 if (_M_uses_single_bucket(__bkts))
370 __hashtable_alloc::_M_deallocate_buckets(__bkts, __n);
374 _M_deallocate_buckets()
375 { _M_deallocate_buckets(_M_buckets, _M_bucket_count); }
380 _M_bucket_begin(size_type __bkt)
const;
384 {
return static_cast<__node_type*>(_M_before_begin._M_nxt); }
386 template<
typename _NodeGenerator>
388 _M_assign(
const _Hashtable&,
const _NodeGenerator&);
399 _Hashtable(
const _H1& __h1,
const _H2& __h2,
const _Hash& __h,
400 const _Equal& __eq,
const _ExtractKey& __exk,
401 const allocator_type& __a)
410 const _H1&,
const _H2&,
const _Hash&,
411 const _Equal&,
const _ExtractKey&,
412 const allocator_type&);
414 template<
typename _InputIterator>
415 _Hashtable(_InputIterator __first, _InputIterator __last,
416 size_type __bucket_hint,
417 const _H1&,
const _H2&,
const _Hash&,
418 const _Equal&,
const _ExtractKey&,
419 const allocator_type&);
437 const _H1& __hf = _H1(),
438 const key_equal& __eql = key_equal(),
439 const allocator_type& __a = allocator_type())
440 :
_Hashtable(__n, __hf, _H2(), _Hash(), __eql,
441 __key_extract(), __a)
444 template<
typename _InputIterator>
445 _Hashtable(_InputIterator __f, _InputIterator __l,
447 const _H1& __hf = _H1(),
448 const key_equal& __eql = key_equal(),
449 const allocator_type& __a = allocator_type())
450 :
_Hashtable(__f, __l, __n, __hf, _H2(), _Hash(), __eql,
451 __key_extract(), __a)
456 const _H1& __hf = _H1(),
457 const key_equal& __eql = key_equal(),
458 const allocator_type& __a = allocator_type())
459 :
_Hashtable(__l.begin(), __l.end(), __n, __hf, _H2(), _Hash(), __eql,
460 __key_extract(), __a)
468 noexcept(__node_alloc_traits::_S_nothrow_move()
472 constexpr
bool __move_storage =
473 __node_alloc_traits::_S_propagate_on_move_assign()
474 || __node_alloc_traits::_S_always_equal();
482 __reuse_or_alloc_node_type __roan(_M_begin(), *
this);
483 _M_before_begin._M_nxt =
nullptr;
485 this->_M_insert_range(__l.begin(), __l.end(), __roan, __unique_keys());
493 noexcept(__and_<__is_nothrow_swappable<_H1>,
494 __is_nothrow_swappable<_Equal>>::value);
499 {
return iterator(_M_begin()); }
502 begin()
const noexcept
503 {
return const_iterator(_M_begin()); }
507 {
return iterator(
nullptr); }
511 {
return const_iterator(
nullptr); }
515 {
return const_iterator(_M_begin()); }
518 cend()
const noexcept
519 {
return const_iterator(
nullptr); }
522 size()
const noexcept
523 {
return _M_element_count; }
526 empty()
const noexcept
527 {
return size() == 0; }
530 get_allocator()
const noexcept
531 {
return allocator_type(this->_M_node_allocator()); }
534 max_size()
const noexcept
535 {
return __node_alloc_traits::max_size(this->_M_node_allocator()); }
540 {
return this->_M_eq(); }
546 bucket_count()
const noexcept
547 {
return _M_bucket_count; }
550 max_bucket_count()
const noexcept
551 {
return max_size(); }
554 bucket_size(size_type __n)
const 558 bucket(
const key_type& __k)
const 559 {
return _M_bucket_index(__k, this->_M_hash_code(__k)); }
564 return local_iterator(*
this, _M_bucket_begin(__n),
565 __n, _M_bucket_count);
570 {
return local_iterator(*
this,
nullptr, __n, _M_bucket_count); }
573 begin(size_type __n)
const 575 return const_local_iterator(*
this, _M_bucket_begin(__n),
576 __n, _M_bucket_count);
580 end(size_type __n)
const 581 {
return const_local_iterator(*
this,
nullptr, __n, _M_bucket_count); }
585 cbegin(size_type __n)
const 587 return const_local_iterator(*
this, _M_bucket_begin(__n),
588 __n, _M_bucket_count);
592 cend(size_type __n)
const 593 {
return const_local_iterator(*
this,
nullptr, __n, _M_bucket_count); }
596 load_factor()
const noexcept
598 return static_cast<float>(size()) / static_cast<float>(bucket_count());
607 __rehash_policy()
const 608 {
return _M_rehash_policy; }
611 __rehash_policy(
const _RehashPolicy& __pol)
612 { _M_rehash_policy = __pol; }
616 find(
const key_type& __k);
619 find(
const key_type& __k)
const;
622 count(
const key_type& __k)
const;
625 equal_range(
const key_type& __k);
628 equal_range(
const key_type& __k)
const;
634 {
return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); }
637 _M_bucket_index(
const key_type& __k, __hash_code __c)
const 638 {
return __hash_code_base::_M_bucket_index(__k, __c, _M_bucket_count); }
643 _M_find_before_node(size_type,
const key_type&, __hash_code)
const;
646 _M_find_node(size_type __bkt,
const key_type& __key,
647 __hash_code __c)
const 649 __node_base* __before_n = _M_find_before_node(__bkt, __key, __c);
651 return static_cast<__node_type*>(__before_n->_M_nxt);
661 _M_remove_bucket_begin(size_type __bkt,
__node_type* __next_n,
662 size_type __next_bkt);
666 _M_get_previous_node(size_type __bkt, __node_base* __n);
672 _M_insert_unique_node(size_type __bkt, __hash_code __code,
681 template<
typename... _Args>
685 template<
typename... _Args>
688 {
return _M_emplace(
cend(), __uk, std::forward<_Args>(__args)...); }
691 template<
typename... _Args>
693 _M_emplace(const_iterator,
std::true_type __uk, _Args&&... __args)
694 {
return _M_emplace(__uk, std::forward<_Args>(__args)...).first; }
696 template<
typename... _Args>
700 template<
typename _Arg,
typename _NodeGenerator>
702 _M_insert(_Arg&&,
const _NodeGenerator&,
true_type, size_type = 1);
704 template<
typename _Arg,
typename _NodeGenerator>
706 _M_insert(_Arg&& __arg,
const _NodeGenerator& __node_gen,
709 return _M_insert(
cend(), std::forward<_Arg>(__arg), __node_gen,
714 template<
typename _Arg,
typename _NodeGenerator>
716 _M_insert(const_iterator, _Arg&& __arg,
717 const _NodeGenerator& __node_gen,
true_type __uk)
720 _M_insert(std::forward<_Arg>(__arg), __node_gen, __uk).
first;
724 template<
typename _Arg,
typename _NodeGenerator>
726 _M_insert(const_iterator, _Arg&&,
736 _M_erase(size_type __bkt, __node_base* __prev_n,
__node_type* __n);
740 template<
typename... _Args>
742 emplace(_Args&&... __args)
743 {
return _M_emplace(__unique_keys(), std::forward<_Args>(__args)...); }
745 template<
typename... _Args>
747 emplace_hint(const_iterator __hint, _Args&&... __args)
749 return _M_emplace(__hint, __unique_keys(),
750 std::forward<_Args>(__args)...);
757 erase(const_iterator);
762 {
return erase(const_iterator(__it)); }
765 erase(
const key_type& __k)
766 {
return _M_erase(__unique_keys(), __k); }
769 erase(const_iterator, const_iterator);
775 void rehash(size_type __n);
780 #if __cplusplus > 201402L 783 _M_reinsert_node(node_type&& __nh)
785 insert_return_type __ret;
787 __ret.position =
end();
790 __glibcxx_assert(get_allocator() == __nh.get_allocator());
792 const key_type& __k = __nh._M_key();
793 __hash_code __code = this->_M_hash_code(__k);
794 size_type __bkt = _M_bucket_index(__k, __code);
795 if (
__node_type* __n = _M_find_node(__bkt, __k, __code))
797 __ret.node = std::move(__nh);
798 __ret.position = iterator(__n);
799 __ret.inserted =
false;
804 = _M_insert_unique_node(__bkt, __code, __nh._M_ptr);
805 __nh._M_ptr =
nullptr;
806 __ret.inserted =
true;
814 _M_reinsert_node_multi(const_iterator __hint, node_type&& __nh)
821 __glibcxx_assert(get_allocator() == __nh.get_allocator());
823 auto __code = this->_M_hash_code(__nh._M_key());
826 __ret = _M_insert_multi_node(__hint._M_cur, __code, __node);
833 extract(const_iterator __pos)
836 size_t __bkt = _M_bucket_index(__n);
841 __node_base* __prev_n = _M_get_previous_node(__bkt, __n);
843 if (__prev_n == _M_buckets[__bkt])
844 _M_remove_bucket_begin(__bkt, __n->_M_next(),
845 __n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0);
846 else if (__n->_M_nxt)
848 size_type __next_bkt = _M_bucket_index(__n->_M_next());
849 if (__next_bkt != __bkt)
850 _M_buckets[__next_bkt] = __prev_n;
853 __prev_n->_M_nxt = __n->_M_nxt;
854 __n->_M_nxt =
nullptr;
856 return { __n, this->_M_node_allocator() };
861 extract(
const _Key& __k)
864 auto __pos = find(__k);
866 __nh = extract(const_iterator(__pos));
871 template<
typename _Compatible_Hashtable>
873 _M_merge_unique(_Compatible_Hashtable& __src) noexcept
875 static_assert(is_same_v<
typename _Compatible_Hashtable::node_type,
876 node_type>,
"Node types are compatible");
877 __glibcxx_assert(get_allocator() == __src.get_allocator());
879 auto __n_elt = __src.size();
880 for (
auto __i = __src.begin(), __end = __src.end(); __i != __end;)
883 const key_type& __k = this->_M_extract()(__pos._M_cur->_M_v());
884 __hash_code __code = this->_M_hash_code(__k);
885 size_type __bkt = _M_bucket_index(__k, __code);
886 if (_M_find_node(__bkt, __k, __code) ==
nullptr)
888 auto __nh = __src.extract(__pos);
889 _M_insert_unique_node(__bkt, __code, __nh._M_ptr, __n_elt);
890 __nh._M_ptr =
nullptr;
893 else if (__n_elt != 1)
899 template<
typename _Compatible_Hashtable>
901 _M_merge_multi(_Compatible_Hashtable& __src) noexcept
903 static_assert(is_same_v<
typename _Compatible_Hashtable::node_type,
904 node_type>,
"Node types are compatible");
905 __glibcxx_assert(get_allocator() == __src.get_allocator());
907 this->reserve(size() + __src.size());
908 for (
auto __i = __src.begin(), __end = __src.end(); __i != __end;)
909 _M_reinsert_node_multi(
cend(), __src.extract(__i++));
922 void _M_rehash(size_type __n,
const __rehash_state& __state);
927 template<
typename _Key,
typename _Value,
928 typename _Alloc,
typename _ExtractKey,
typename _Equal,
929 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
932 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
933 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
934 _M_bucket_begin(size_type __bkt)
const 937 __node_base* __n = _M_buckets[__bkt];
938 return __n ? static_cast<__node_type*>(__n->_M_nxt) : nullptr;
941 template<
typename _Key,
typename _Value,
942 typename _Alloc,
typename _ExtractKey,
typename _Equal,
943 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
945 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
946 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
947 _Hashtable(size_type __bucket_hint,
948 const _H1& __h1,
const _H2& __h2,
const _Hash& __h,
949 const _Equal& __eq,
const _ExtractKey& __exk,
950 const allocator_type& __a)
951 : _Hashtable(__h1, __h2, __h, __eq, __exk, __a)
953 auto __bkt = _M_rehash_policy._M_next_bkt(__bucket_hint);
954 if (__bkt > _M_bucket_count)
956 _M_buckets = _M_allocate_buckets(__bkt);
957 _M_bucket_count = __bkt;
961 template<
typename _Key,
typename _Value,
962 typename _Alloc,
typename _ExtractKey,
typename _Equal,
963 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
965 template<
typename _InputIterator>
966 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
967 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
968 _Hashtable(_InputIterator __f, _InputIterator __l,
969 size_type __bucket_hint,
970 const _H1& __h1,
const _H2& __h2,
const _Hash& __h,
971 const _Equal& __eq,
const _ExtractKey& __exk,
972 const allocator_type& __a)
973 : _Hashtable(__h1, __h2, __h, __eq, __exk, __a)
975 auto __nb_elems = __detail::__distance_fw(__f, __l);
977 _M_rehash_policy._M_next_bkt(
978 std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems),
981 if (__bkt_count > _M_bucket_count)
983 _M_buckets = _M_allocate_buckets(__bkt_count);
984 _M_bucket_count = __bkt_count;
987 for (; __f != __l; ++__f)
991 template<
typename _Key,
typename _Value,
992 typename _Alloc,
typename _ExtractKey,
typename _Equal,
993 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
996 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
997 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
998 operator=(
const _Hashtable& __ht)
1004 if (__node_alloc_traits::_S_propagate_on_copy_assign())
1006 auto& __this_alloc = this->_M_node_allocator();
1007 auto& __that_alloc = __ht._M_node_allocator();
1008 if (!__node_alloc_traits::_S_always_equal()
1009 && __this_alloc != __that_alloc)
1012 this->_M_deallocate_nodes(_M_begin());
1013 _M_before_begin._M_nxt =
nullptr;
1014 _M_deallocate_buckets();
1015 _M_buckets =
nullptr;
1016 std::__alloc_on_copy(__this_alloc, __that_alloc);
1017 __hashtable_base::operator=(__ht);
1018 _M_bucket_count = __ht._M_bucket_count;
1019 _M_element_count = __ht._M_element_count;
1020 _M_rehash_policy = __ht._M_rehash_policy;
1024 [
this](
const __node_type* __n)
1025 {
return this->_M_allocate_node(__n->_M_v()); });
1032 __throw_exception_again;
1036 std::__alloc_on_copy(__this_alloc, __that_alloc);
1040 __bucket_type* __former_buckets =
nullptr;
1041 std::size_t __former_bucket_count = _M_bucket_count;
1042 const __rehash_state& __former_state = _M_rehash_policy._M_state();
1044 if (_M_bucket_count != __ht._M_bucket_count)
1046 __former_buckets = _M_buckets;
1047 _M_buckets = _M_allocate_buckets(__ht._M_bucket_count);
1048 _M_bucket_count = __ht._M_bucket_count;
1051 __builtin_memset(_M_buckets, 0,
1052 _M_bucket_count *
sizeof(__bucket_type));
1056 __hashtable_base::operator=(__ht);
1057 _M_element_count = __ht._M_element_count;
1058 _M_rehash_policy = __ht._M_rehash_policy;
1059 __reuse_or_alloc_node_type __roan(_M_begin(), *
this);
1060 _M_before_begin._M_nxt =
nullptr;
1062 [&__roan](
const __node_type* __n)
1063 {
return __roan(__n->_M_v()); });
1064 if (__former_buckets)
1065 _M_deallocate_buckets(__former_buckets, __former_bucket_count);
1069 if (__former_buckets)
1072 _M_deallocate_buckets();
1073 _M_rehash_policy._M_reset(__former_state);
1074 _M_buckets = __former_buckets;
1075 _M_bucket_count = __former_bucket_count;
1077 __builtin_memset(_M_buckets, 0,
1078 _M_bucket_count *
sizeof(__bucket_type));
1079 __throw_exception_again;
1084 template<
typename _Key,
typename _Value,
1085 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1086 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1088 template<
typename _NodeGenerator>
1090 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1091 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1092 _M_assign(
const _Hashtable& __ht,
const _NodeGenerator& __node_gen)
1094 __bucket_type* __buckets =
nullptr;
1096 _M_buckets = __buckets = _M_allocate_buckets(_M_bucket_count);
1100 if (!__ht._M_before_begin._M_nxt)
1105 __node_type* __ht_n = __ht._M_begin();
1106 __node_type* __this_n = __node_gen(__ht_n);
1107 this->_M_copy_code(__this_n, __ht_n);
1108 _M_before_begin._M_nxt = __this_n;
1109 _M_buckets[_M_bucket_index(__this_n)] = &_M_before_begin;
1112 __node_base* __prev_n = __this_n;
1113 for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next())
1115 __this_n = __node_gen(__ht_n);
1116 __prev_n->_M_nxt = __this_n;
1117 this->_M_copy_code(__this_n, __ht_n);
1118 size_type __bkt = _M_bucket_index(__this_n);
1119 if (!_M_buckets[__bkt])
1120 _M_buckets[__bkt] = __prev_n;
1121 __prev_n = __this_n;
1128 _M_deallocate_buckets();
1129 __throw_exception_again;
1133 template<
typename _Key,
typename _Value,
1134 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1135 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1138 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1139 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1142 _M_rehash_policy._M_reset();
1143 _M_bucket_count = 1;
1144 _M_single_bucket =
nullptr;
1145 _M_buckets = &_M_single_bucket;
1146 _M_before_begin._M_nxt =
nullptr;
1147 _M_element_count = 0;
1150 template<
typename _Key,
typename _Value,
1151 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1152 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1155 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1156 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1159 this->_M_deallocate_nodes(_M_begin());
1160 _M_deallocate_buckets();
1161 __hashtable_base::operator=(std::move(__ht));
1162 _M_rehash_policy = __ht._M_rehash_policy;
1163 if (!__ht._M_uses_single_bucket())
1164 _M_buckets = __ht._M_buckets;
1167 _M_buckets = &_M_single_bucket;
1168 _M_single_bucket = __ht._M_single_bucket;
1170 _M_bucket_count = __ht._M_bucket_count;
1171 _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt;
1172 _M_element_count = __ht._M_element_count;
1173 std::__alloc_on_move(this->_M_node_allocator(), __ht._M_node_allocator());
1178 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
1182 template<
typename _Key,
typename _Value,
1183 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1184 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1187 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1188 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1191 if (__ht._M_node_allocator() == this->_M_node_allocator())
1196 __bucket_type* __former_buckets =
nullptr;
1197 size_type __former_bucket_count = _M_bucket_count;
1198 const __rehash_state& __former_state = _M_rehash_policy._M_state();
1200 if (_M_bucket_count != __ht._M_bucket_count)
1202 __former_buckets = _M_buckets;
1203 _M_buckets = _M_allocate_buckets(__ht._M_bucket_count);
1204 _M_bucket_count = __ht._M_bucket_count;
1207 __builtin_memset(_M_buckets, 0,
1208 _M_bucket_count *
sizeof(__bucket_type));
1212 __hashtable_base::operator=(std::move(__ht));
1213 _M_element_count = __ht._M_element_count;
1214 _M_rehash_policy = __ht._M_rehash_policy;
1215 __reuse_or_alloc_node_type __roan(_M_begin(), *
this);
1216 _M_before_begin._M_nxt =
nullptr;
1218 [&__roan](__node_type* __n)
1221 if (__former_buckets)
1222 _M_deallocate_buckets(__former_buckets, __former_bucket_count);
1227 if (__former_buckets)
1229 _M_deallocate_buckets();
1230 _M_rehash_policy._M_reset(__former_state);
1231 _M_buckets = __former_buckets;
1232 _M_bucket_count = __former_bucket_count;
1234 __builtin_memset(_M_buckets, 0,
1235 _M_bucket_count *
sizeof(__bucket_type));
1236 __throw_exception_again;
1241 template<
typename _Key,
typename _Value,
1242 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1243 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1245 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1246 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1247 _Hashtable(
const _Hashtable& __ht)
1248 : __hashtable_base(__ht),
1250 __rehash_base(__ht),
1252 __node_alloc_traits::_S_select_on_copy(__ht._M_node_allocator())),
1253 _M_buckets(nullptr),
1254 _M_bucket_count(__ht._M_bucket_count),
1255 _M_element_count(__ht._M_element_count),
1256 _M_rehash_policy(__ht._M_rehash_policy)
1259 [
this](
const __node_type* __n)
1260 {
return this->_M_allocate_node(__n->_M_v()); });
1263 template<
typename _Key,
typename _Value,
1264 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1265 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1267 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1268 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1269 _Hashtable(_Hashtable&& __ht) noexcept
1270 : __hashtable_base(__ht),
1272 __rehash_base(__ht),
1273 __hashtable_alloc(std::move(__ht._M_base_alloc())),
1274 _M_buckets(__ht._M_buckets),
1275 _M_bucket_count(__ht._M_bucket_count),
1276 _M_before_begin(__ht._M_before_begin._M_nxt),
1277 _M_element_count(__ht._M_element_count),
1278 _M_rehash_policy(__ht._M_rehash_policy)
1281 if (__ht._M_uses_single_bucket())
1283 _M_buckets = &_M_single_bucket;
1284 _M_single_bucket = __ht._M_single_bucket;
1290 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
1295 template<
typename _Key,
typename _Value,
1296 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1297 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1299 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1300 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1301 _Hashtable(
const _Hashtable& __ht,
const allocator_type& __a)
1302 : __hashtable_base(__ht),
1304 __rehash_base(__ht),
1305 __hashtable_alloc(__node_alloc_type(__a)),
1307 _M_bucket_count(__ht._M_bucket_count),
1308 _M_element_count(__ht._M_element_count),
1309 _M_rehash_policy(__ht._M_rehash_policy)
1312 [
this](
const __node_type* __n)
1313 {
return this->_M_allocate_node(__n->_M_v()); });
1316 template<
typename _Key,
typename _Value,
1317 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1318 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1320 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1321 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1322 _Hashtable(_Hashtable&& __ht,
const allocator_type& __a)
1323 : __hashtable_base(__ht),
1325 __rehash_base(__ht),
1326 __hashtable_alloc(__node_alloc_type(__a)),
1327 _M_buckets(nullptr),
1328 _M_bucket_count(__ht._M_bucket_count),
1329 _M_element_count(__ht._M_element_count),
1330 _M_rehash_policy(__ht._M_rehash_policy)
1332 if (__ht._M_node_allocator() == this->_M_node_allocator())
1334 if (__ht._M_uses_single_bucket())
1336 _M_buckets = &_M_single_bucket;
1337 _M_single_bucket = __ht._M_single_bucket;
1340 _M_buckets = __ht._M_buckets;
1342 _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt;
1346 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
1352 [
this](__node_type* __n)
1354 return this->_M_allocate_node(
1361 template<
typename _Key,
typename _Value,
1362 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1363 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1365 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1366 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1367 ~_Hashtable() noexcept
1370 _M_deallocate_buckets();
1373 template<
typename _Key,
typename _Value,
1374 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1375 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1378 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1379 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1380 swap(_Hashtable& __x)
1381 noexcept(__and_<__is_nothrow_swappable<_H1>,
1382 __is_nothrow_swappable<_Equal>>::value)
1389 std::__alloc_on_swap(this->_M_node_allocator(), __x._M_node_allocator());
1390 std::swap(_M_rehash_policy, __x._M_rehash_policy);
1393 if (this->_M_uses_single_bucket())
1395 if (!__x._M_uses_single_bucket())
1397 _M_buckets = __x._M_buckets;
1398 __x._M_buckets = &__x._M_single_bucket;
1401 else if (__x._M_uses_single_bucket())
1403 __x._M_buckets = _M_buckets;
1404 _M_buckets = &_M_single_bucket;
1407 std::swap(_M_buckets, __x._M_buckets);
1409 std::swap(_M_bucket_count, __x._M_bucket_count);
1410 std::swap(_M_before_begin._M_nxt, __x._M_before_begin._M_nxt);
1411 std::swap(_M_element_count, __x._M_element_count);
1412 std::swap(_M_single_bucket, __x._M_single_bucket);
1417 _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin;
1420 __x._M_buckets[__x._M_bucket_index(__x._M_begin())]
1421 = &__x._M_before_begin;
1424 template<
typename _Key,
typename _Value,
1425 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1426 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1429 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1430 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1431 find(
const key_type& __k)
1434 __hash_code __code = this->_M_hash_code(__k);
1435 std::size_t __n = _M_bucket_index(__k, __code);
1436 __node_type* __p = _M_find_node(__n, __k, __code);
1437 return __p ? iterator(__p) :
end();
1440 template<
typename _Key,
typename _Value,
1441 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1442 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1445 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1446 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1447 find(
const key_type& __k)
const 1450 __hash_code __code = this->_M_hash_code(__k);
1451 std::size_t __n = _M_bucket_index(__k, __code);
1452 __node_type* __p = _M_find_node(__n, __k, __code);
1453 return __p ? const_iterator(__p) :
end();
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 count(
const key_type& __k)
const 1466 __hash_code __code = this->_M_hash_code(__k);
1467 std::size_t __n = _M_bucket_index(__k, __code);
1468 __node_type* __p = _M_bucket_begin(__n);
1472 std::size_t __result = 0;
1473 for (;; __p = __p->_M_next())
1475 if (this->_M_equals(__k, __code, __p))
1482 if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
1488 template<
typename _Key,
typename _Value,
1489 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1490 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1493 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1494 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1495 equal_range(
const key_type& __k)
1496 -> pair<iterator, iterator>
1498 __hash_code __code = this->_M_hash_code(__k);
1499 std::size_t __n = _M_bucket_index(__k, __code);
1500 __node_type* __p = _M_find_node(__n, __k, __code);
1504 __node_type* __p1 = __p->_M_next();
1505 while (__p1 && _M_bucket_index(__p1) == __n
1506 && this->_M_equals(__k, __code, __p1))
1507 __p1 = __p1->_M_next();
1515 template<
typename _Key,
typename _Value,
1516 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1517 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1520 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1521 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1522 equal_range(
const key_type& __k)
const 1523 -> pair<const_iterator, const_iterator>
1525 __hash_code __code = this->_M_hash_code(__k);
1526 std::size_t __n = _M_bucket_index(__k, __code);
1527 __node_type* __p = _M_find_node(__n, __k, __code);
1531 __node_type* __p1 = __p->_M_next();
1532 while (__p1 && _M_bucket_index(__p1) == __n
1533 && this->_M_equals(__k, __code, __p1))
1534 __p1 = __p1->_M_next();
1536 return std::make_pair(const_iterator(__p), const_iterator(__p1));
1544 template<
typename _Key,
typename _Value,
1545 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1546 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1549 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1550 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1551 _M_find_before_node(size_type __n,
const key_type& __k,
1552 __hash_code __code)
const 1555 __node_base* __prev_p = _M_buckets[__n];
1559 for (__node_type* __p = static_cast<__node_type*>(__prev_p->_M_nxt);;
1560 __p = __p->_M_next())
1562 if (this->_M_equals(__k, __code, __p))
1565 if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __n)
1572 template<
typename _Key,
typename _Value,
1573 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1574 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1577 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1578 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1579 _M_insert_bucket_begin(size_type __bkt, __node_type* __node)
1581 if (_M_buckets[__bkt])
1585 __node->_M_nxt = _M_buckets[__bkt]->_M_nxt;
1586 _M_buckets[__bkt]->_M_nxt = __node;
1593 __node->_M_nxt = _M_before_begin._M_nxt;
1594 _M_before_begin._M_nxt = __node;
1598 _M_buckets[_M_bucket_index(__node->_M_next())] = __node;
1599 _M_buckets[__bkt] = &_M_before_begin;
1603 template<
typename _Key,
typename _Value,
1604 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1605 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1608 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1609 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1610 _M_remove_bucket_begin(size_type __bkt, __node_type* __next,
1611 size_type __next_bkt)
1613 if (!__next || __next_bkt != __bkt)
1618 _M_buckets[__next_bkt] = _M_buckets[__bkt];
1621 if (&_M_before_begin == _M_buckets[__bkt])
1622 _M_before_begin._M_nxt = __next;
1623 _M_buckets[__bkt] =
nullptr;
1627 template<
typename _Key,
typename _Value,
1628 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1629 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1632 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1633 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1634 _M_get_previous_node(size_type __bkt, __node_base* __n)
1637 __node_base* __prev_n = _M_buckets[__bkt];
1638 while (__prev_n->_M_nxt != __n)
1639 __prev_n = __prev_n->_M_nxt;
1643 template<
typename _Key,
typename _Value,
1644 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1645 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1647 template<
typename... _Args>
1649 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1650 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1652 -> pair<iterator, bool>
1655 __node_type* __node = this->_M_allocate_node(std::forward<_Args>(__args)...);
1656 const key_type& __k = this->_M_extract()(__node->_M_v());
1660 __code = this->_M_hash_code(__k);
1664 this->_M_deallocate_node(__node);
1665 __throw_exception_again;
1668 size_type __bkt = _M_bucket_index(__k, __code);
1669 if (__node_type* __p = _M_find_node(__bkt, __k, __code))
1672 this->_M_deallocate_node(__node);
1677 return std::make_pair(_M_insert_unique_node(__bkt, __code, __node),
1681 template<
typename _Key,
typename _Value,
1682 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1683 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1685 template<
typename... _Args>
1687 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1688 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1693 __node_type* __node =
1694 this->_M_allocate_node(std::forward<_Args>(__args)...);
1699 __code = this->_M_hash_code(this->_M_extract()(__node->_M_v()));
1703 this->_M_deallocate_node(__node);
1704 __throw_exception_again;
1707 return _M_insert_multi_node(__hint._M_cur, __code, __node);
1710 template<
typename _Key,
typename _Value,
1711 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1712 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1715 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1716 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1717 _M_insert_unique_node(size_type __bkt, __hash_code __code,
1718 __node_type* __node, size_type __n_elt)
1721 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
1723 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count,
1728 if (__do_rehash.
first)
1730 _M_rehash(__do_rehash.
second, __saved_state);
1731 __bkt = _M_bucket_index(this->_M_extract()(__node->_M_v()), __code);
1734 this->_M_store_code(__node, __code);
1737 _M_insert_bucket_begin(__bkt, __node);
1739 return iterator(__node);
1743 this->_M_deallocate_node(__node);
1744 __throw_exception_again;
1750 template<
typename _Key,
typename _Value,
1751 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1752 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1755 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1756 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1757 _M_insert_multi_node(__node_type* __hint, __hash_code __code,
1758 __node_type* __node)
1761 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
1763 = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
1767 if (__do_rehash.
first)
1768 _M_rehash(__do_rehash.
second, __saved_state);
1770 this->_M_store_code(__node, __code);
1771 const key_type& __k = this->_M_extract()(__node->_M_v());
1772 size_type __bkt = _M_bucket_index(__k, __code);
1777 = __builtin_expect(__hint !=
nullptr,
false)
1778 && this->_M_equals(__k, __code, __hint)
1780 : _M_find_before_node(__bkt, __k, __code);
1784 __node->_M_nxt = __prev->_M_nxt;
1785 __prev->_M_nxt = __node;
1786 if (__builtin_expect(__prev == __hint,
false))
1790 && !this->_M_equals(__k, __code, __node->_M_next()))
1792 size_type __next_bkt = _M_bucket_index(__node->_M_next());
1793 if (__next_bkt != __bkt)
1794 _M_buckets[__next_bkt] = __node;
1802 _M_insert_bucket_begin(__bkt, __node);
1804 return iterator(__node);
1808 this->_M_deallocate_node(__node);
1809 __throw_exception_again;
1814 template<
typename _Key,
typename _Value,
1815 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1816 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1818 template<
typename _Arg,
typename _NodeGenerator>
1820 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1821 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1822 _M_insert(_Arg&& __v,
const _NodeGenerator& __node_gen,
true_type,
1824 -> pair<iterator, bool>
1826 const key_type& __k = this->_M_extract()(__v);
1827 __hash_code __code = this->_M_hash_code(__k);
1828 size_type __bkt = _M_bucket_index(__k, __code);
1830 __node_type* __n = _M_find_node(__bkt, __k, __code);
1834 __n = __node_gen(std::forward<_Arg>(__v));
1835 return { _M_insert_unique_node(__bkt, __code, __n, __n_elt),
true };
1839 template<
typename _Key,
typename _Value,
1840 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1841 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1843 template<
typename _Arg,
typename _NodeGenerator>
1845 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1846 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1847 _M_insert(const_iterator __hint, _Arg&& __v,
1848 const _NodeGenerator& __node_gen,
false_type)
1853 __hash_code __code = this->_M_hash_code(this->_M_extract()(__v));
1856 __node_type* __node = __node_gen(std::forward<_Arg>(__v));
1858 return _M_insert_multi_node(__hint._M_cur, __code, __node);
1861 template<
typename _Key,
typename _Value,
1862 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1863 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1866 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1867 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1868 erase(const_iterator __it)
1871 __node_type* __n = __it._M_cur;
1872 std::size_t __bkt = _M_bucket_index(__n);
1877 __node_base* __prev_n = _M_get_previous_node(__bkt, __n);
1878 return _M_erase(__bkt, __prev_n, __n);
1881 template<
typename _Key,
typename _Value,
1882 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1883 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1886 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1887 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1888 _M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n)
1891 if (__prev_n == _M_buckets[__bkt])
1892 _M_remove_bucket_begin(__bkt, __n->_M_next(),
1893 __n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0);
1894 else if (__n->_M_nxt)
1896 size_type __next_bkt = _M_bucket_index(__n->_M_next());
1897 if (__next_bkt != __bkt)
1898 _M_buckets[__next_bkt] = __prev_n;
1901 __prev_n->_M_nxt = __n->_M_nxt;
1902 iterator __result(__n->_M_next());
1903 this->_M_deallocate_node(__n);
1909 template<
typename _Key,
typename _Value,
1910 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1911 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1914 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1915 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1919 __hash_code __code = this->_M_hash_code(__k);
1920 std::size_t __bkt = _M_bucket_index(__k, __code);
1923 __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code);
1928 __node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt);
1929 _M_erase(__bkt, __prev_n, __n);
1933 template<
typename _Key,
typename _Value,
1934 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1935 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1938 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1939 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1943 __hash_code __code = this->_M_hash_code(__k);
1944 std::size_t __bkt = _M_bucket_index(__k, __code);
1947 __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code);
1957 __node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt);
1958 __node_type* __n_last = __n;
1959 std::size_t __n_last_bkt = __bkt;
1962 __n_last = __n_last->_M_next();
1965 __n_last_bkt = _M_bucket_index(__n_last);
1967 while (__n_last_bkt == __bkt && this->_M_equals(__k, __code, __n_last));
1970 size_type __result = 0;
1973 __node_type* __p = __n->_M_next();
1974 this->_M_deallocate_node(__n);
1979 while (__n != __n_last);
1981 if (__prev_n == _M_buckets[__bkt])
1982 _M_remove_bucket_begin(__bkt, __n_last, __n_last_bkt);
1983 else if (__n_last && __n_last_bkt != __bkt)
1984 _M_buckets[__n_last_bkt] = __prev_n;
1985 __prev_n->_M_nxt = __n_last;
1989 template<
typename _Key,
typename _Value,
1990 typename _Alloc,
typename _ExtractKey,
typename _Equal,
1991 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
1994 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
1995 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
1996 erase(const_iterator __first, const_iterator __last)
1999 __node_type* __n = __first._M_cur;
2000 __node_type* __last_n = __last._M_cur;
2001 if (__n == __last_n)
2002 return iterator(__n);
2004 std::size_t __bkt = _M_bucket_index(__n);
2006 __node_base* __prev_n = _M_get_previous_node(__bkt, __n);
2007 bool __is_bucket_begin = __n == _M_bucket_begin(__bkt);
2008 std::size_t __n_bkt = __bkt;
2013 __node_type* __tmp = __n;
2014 __n = __n->_M_next();
2015 this->_M_deallocate_node(__tmp);
2019 __n_bkt = _M_bucket_index(__n);
2021 while (__n != __last_n && __n_bkt == __bkt);
2022 if (__is_bucket_begin)
2023 _M_remove_bucket_begin(__bkt, __n, __n_bkt);
2024 if (__n == __last_n)
2026 __is_bucket_begin =
true;
2030 if (__n && (__n_bkt != __bkt || __is_bucket_begin))
2031 _M_buckets[__n_bkt] = __prev_n;
2032 __prev_n->_M_nxt = __n;
2033 return iterator(__n);
2036 template<
typename _Key,
typename _Value,
2037 typename _Alloc,
typename _ExtractKey,
typename _Equal,
2038 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
2041 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2042 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2045 this->_M_deallocate_nodes(_M_begin());
2046 __builtin_memset(_M_buckets, 0, _M_bucket_count *
sizeof(__bucket_type));
2047 _M_element_count = 0;
2048 _M_before_begin._M_nxt =
nullptr;
2051 template<
typename _Key,
typename _Value,
2052 typename _Alloc,
typename _ExtractKey,
typename _Equal,
2053 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
2056 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2057 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2058 rehash(size_type __n)
2060 const __rehash_state& __saved_state = _M_rehash_policy._M_state();
2061 std::size_t __buckets
2062 =
std::max(_M_rehash_policy._M_bkt_for_elements(_M_element_count + 1),
2064 __buckets = _M_rehash_policy._M_next_bkt(__buckets);
2066 if (__buckets != _M_bucket_count)
2067 _M_rehash(__buckets, __saved_state);
2070 _M_rehash_policy._M_reset(__saved_state);
2073 template<
typename _Key,
typename _Value,
2074 typename _Alloc,
typename _ExtractKey,
typename _Equal,
2075 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
2078 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2079 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2080 _M_rehash(size_type __n,
const __rehash_state& __state)
2084 _M_rehash_aux(__n, __unique_keys());
2090 _M_rehash_policy._M_reset(__state);
2091 __throw_exception_again;
2096 template<
typename _Key,
typename _Value,
2097 typename _Alloc,
typename _ExtractKey,
typename _Equal,
2098 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
2101 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2102 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2105 __bucket_type* __new_buckets = _M_allocate_buckets(__n);
2106 __node_type* __p = _M_begin();
2107 _M_before_begin._M_nxt =
nullptr;
2108 std::size_t __bbegin_bkt = 0;
2111 __node_type* __next = __p->_M_next();
2112 std::size_t __bkt = __hash_code_base::_M_bucket_index(__p, __n);
2113 if (!__new_buckets[__bkt])
2115 __p->_M_nxt = _M_before_begin._M_nxt;
2116 _M_before_begin._M_nxt = __p;
2117 __new_buckets[__bkt] = &_M_before_begin;
2119 __new_buckets[__bbegin_bkt] = __p;
2120 __bbegin_bkt = __bkt;
2124 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2125 __new_buckets[__bkt]->_M_nxt = __p;
2130 _M_deallocate_buckets();
2131 _M_bucket_count = __n;
2132 _M_buckets = __new_buckets;
2137 template<
typename _Key,
typename _Value,
2138 typename _Alloc,
typename _ExtractKey,
typename _Equal,
2139 typename _H1,
typename _H2,
typename _Hash,
typename _RehashPolicy,
2142 _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
2143 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
2146 __bucket_type* __new_buckets = _M_allocate_buckets(__n);
2148 __node_type* __p = _M_begin();
2149 _M_before_begin._M_nxt =
nullptr;
2150 std::size_t __bbegin_bkt = 0;
2151 std::size_t __prev_bkt = 0;
2152 __node_type* __prev_p =
nullptr;
2153 bool __check_bucket =
false;
2157 __node_type* __next = __p->_M_next();
2158 std::size_t __bkt = __hash_code_base::_M_bucket_index(__p, __n);
2160 if (__prev_p && __prev_bkt == __bkt)
2165 __p->_M_nxt = __prev_p->_M_nxt;
2166 __prev_p->_M_nxt = __p;
2173 __check_bucket =
true;
2181 if (__prev_p->_M_nxt)
2183 std::size_t __next_bkt
2184 = __hash_code_base::_M_bucket_index(__prev_p->_M_next(),
2186 if (__next_bkt != __prev_bkt)
2187 __new_buckets[__next_bkt] = __prev_p;
2189 __check_bucket =
false;
2192 if (!__new_buckets[__bkt])
2194 __p->_M_nxt = _M_before_begin._M_nxt;
2195 _M_before_begin._M_nxt = __p;
2196 __new_buckets[__bkt] = &_M_before_begin;
2198 __new_buckets[__bbegin_bkt] = __p;
2199 __bbegin_bkt = __bkt;
2203 __p->_M_nxt = __new_buckets[__bkt]->_M_nxt;
2204 __new_buckets[__bkt]->_M_nxt = __p;
2212 if (__check_bucket && __prev_p->_M_nxt)
2214 std::size_t __next_bkt
2215 = __hash_code_base::_M_bucket_index(__prev_p->_M_next(), __n);
2216 if (__next_bkt != __prev_bkt)
2217 __new_buckets[__next_bkt] = __prev_p;
2220 _M_deallocate_buckets();
2221 _M_bucket_count = __n;
2222 _M_buckets = __new_buckets;
2225 #if __cplusplus > 201402L 2226 template<
typename,
typename,
typename>
class _Hash_merge_helper { };
2229 _GLIBCXX_END_NAMESPACE_VERSION
2232 #endif // _HASHTABLE_H Node const_iterators, used to iterate through all the hashtable.
Struct holding two objects of arbitrary type.
integral_constant< bool, true > true_type
The type used as a compile-time boolean with true value.
_GLIBCXX17_CONSTEXPR iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
Node iterators, used to iterate through all the hashtable.
Define a member typedef type to one of two argument types.
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.
is_nothrow_move_assignable
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.
ISO C++ entities toplevel namespace is std.
integral_constant< bool, false > false_type
The type used as a compile-time boolean with false value.
constexpr const _Tp * end(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to one past the last element of the initializer_list.
Uniform interface to C++98 and C++11 allocators.
constexpr auto cbegin(const _Container &__cont) noexcept(noexcept(std::begin(__cont))) -> decltype(std::begin(__cont))
Return an iterator pointing to the first element of the const container.
constexpr auto cend(const _Container &__cont) noexcept(noexcept(std::end(__cont))) -> decltype(std::end(__cont))
Return an iterator pointing to one past the last element of the const container.
_T1 first
second_type is the second bound type
_Tp exchange(_Tp &__obj, _Up &&__new_val)
Assign __new_val to __obj and return its previous value.
constexpr const _Tp * begin(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to the first element of the initializer_list.
_T2 second
first is a copy of the first object
_GLIBCXX14_CONSTEXPR const _Tp & max(const _Tp &, const _Tp &)
This does what you think it does.