Warning, /include/c++/v1/__cxx03/__hash_table is written in an unsupported language. File is not indexed.
0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0007 //
0008 //===----------------------------------------------------------------------===//
0009
0010 #ifndef _LIBCPP___CXX03___HASH_TABLE
0011 #define _LIBCPP___CXX03___HASH_TABLE
0012
0013 #include <__cxx03/__algorithm/max.h>
0014 #include <__cxx03/__algorithm/min.h>
0015 #include <__cxx03/__assert>
0016 #include <__cxx03/__bit/countl.h>
0017 #include <__cxx03/__config>
0018 #include <__cxx03/__functional/hash.h>
0019 #include <__cxx03/__functional/invoke.h>
0020 #include <__cxx03/__iterator/iterator_traits.h>
0021 #include <__cxx03/__memory/addressof.h>
0022 #include <__cxx03/__memory/allocator_traits.h>
0023 #include <__cxx03/__memory/compressed_pair.h>
0024 #include <__cxx03/__memory/construct_at.h>
0025 #include <__cxx03/__memory/pointer_traits.h>
0026 #include <__cxx03/__memory/swap_allocator.h>
0027 #include <__cxx03/__memory/unique_ptr.h>
0028 #include <__cxx03/__type_traits/can_extract_key.h>
0029 #include <__cxx03/__type_traits/conditional.h>
0030 #include <__cxx03/__type_traits/is_const.h>
0031 #include <__cxx03/__type_traits/is_constructible.h>
0032 #include <__cxx03/__type_traits/is_nothrow_assignable.h>
0033 #include <__cxx03/__type_traits/is_nothrow_constructible.h>
0034 #include <__cxx03/__type_traits/is_pointer.h>
0035 #include <__cxx03/__type_traits/is_reference.h>
0036 #include <__cxx03/__type_traits/is_swappable.h>
0037 #include <__cxx03/__type_traits/remove_const.h>
0038 #include <__cxx03/__type_traits/remove_cvref.h>
0039 #include <__cxx03/__utility/forward.h>
0040 #include <__cxx03/__utility/move.h>
0041 #include <__cxx03/__utility/pair.h>
0042 #include <__cxx03/__utility/swap.h>
0043 #include <__cxx03/cmath>
0044 #include <__cxx03/cstring>
0045 #include <__cxx03/initializer_list>
0046 #include <__cxx03/new> // __launder
0047
0048 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0049 # pragma GCC system_header
0050 #endif
0051
0052 _LIBCPP_PUSH_MACROS
0053 #include <__cxx03/__undef_macros>
0054
0055 _LIBCPP_BEGIN_NAMESPACE_STD
0056
0057 template <class _Key, class _Tp>
0058 struct __hash_value_type;
0059
0060 template <class _Tp>
0061 struct __is_hash_value_type_imp : false_type {};
0062
0063 template <class _Key, class _Value>
0064 struct __is_hash_value_type_imp<__hash_value_type<_Key, _Value> > : true_type {};
0065
0066 template <class... _Args>
0067 struct __is_hash_value_type : false_type {};
0068
0069 template <class _One>
0070 struct __is_hash_value_type<_One> : __is_hash_value_type_imp<__remove_cvref_t<_One> > {};
0071
0072 _LIBCPP_EXPORTED_FROM_ABI size_t __next_prime(size_t __n);
0073
0074 template <class _NodePtr>
0075 struct __hash_node_base {
0076 typedef typename pointer_traits<_NodePtr>::element_type __node_type;
0077 typedef __hash_node_base __first_node;
0078 typedef __rebind_pointer_t<_NodePtr, __first_node> __node_base_pointer;
0079 typedef _NodePtr __node_pointer;
0080
0081 #if defined(_LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB)
0082 typedef __node_base_pointer __next_pointer;
0083 #else
0084 typedef __conditional_t<is_pointer<__node_pointer>::value, __node_base_pointer, __node_pointer> __next_pointer;
0085 #endif
0086
0087 __next_pointer __next_;
0088
0089 _LIBCPP_HIDE_FROM_ABI __next_pointer __ptr() _NOEXCEPT {
0090 return static_cast<__next_pointer>(pointer_traits<__node_base_pointer>::pointer_to(*this));
0091 }
0092
0093 _LIBCPP_HIDE_FROM_ABI __node_pointer __upcast() _NOEXCEPT {
0094 return static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(*this));
0095 }
0096
0097 _LIBCPP_HIDE_FROM_ABI size_t __hash() const _NOEXCEPT { return static_cast<__node_type const&>(*this).__hash_; }
0098
0099 _LIBCPP_HIDE_FROM_ABI __hash_node_base() _NOEXCEPT : __next_(nullptr) {}
0100 _LIBCPP_HIDE_FROM_ABI explicit __hash_node_base(__next_pointer __next) _NOEXCEPT : __next_(__next) {}
0101 };
0102
0103 template <class _Tp, class _VoidPtr>
0104 struct __hash_node : public __hash_node_base< __rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > > {
0105 typedef _Tp __node_value_type;
0106 using _Base = __hash_node_base<__rebind_pointer_t<_VoidPtr, __hash_node<_Tp, _VoidPtr> > >;
0107 using __next_pointer = typename _Base::__next_pointer;
0108
0109 size_t __hash_;
0110
0111 // We allow starting the lifetime of nodes without initializing the value held by the node,
0112 // since that is handled by the hash table itself in order to be allocator-aware.
0113 #ifndef _LIBCPP_CXX03_LANG
0114
0115 private:
0116 union {
0117 _Tp __value_;
0118 };
0119
0120 public:
0121 _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return __value_; }
0122 #else
0123
0124 private:
0125 _ALIGNAS_TYPE(_Tp) char __buffer_[sizeof(_Tp)];
0126
0127 public:
0128 _LIBCPP_HIDE_FROM_ABI _Tp& __get_value() { return *std::__launder(reinterpret_cast<_Tp*>(&__buffer_)); }
0129 #endif
0130
0131 _LIBCPP_HIDE_FROM_ABI explicit __hash_node(__next_pointer __next, size_t __hash) : _Base(__next), __hash_(__hash) {}
0132 _LIBCPP_HIDE_FROM_ABI ~__hash_node() {}
0133 };
0134
0135 inline _LIBCPP_HIDE_FROM_ABI bool __is_hash_power2(size_t __bc) { return __bc > 2 && !(__bc & (__bc - 1)); }
0136
0137 inline _LIBCPP_HIDE_FROM_ABI size_t __constrain_hash(size_t __h, size_t __bc) {
0138 return !(__bc & (__bc - 1)) ? __h & (__bc - 1) : (__h < __bc ? __h : __h % __bc);
0139 }
0140
0141 inline _LIBCPP_HIDE_FROM_ABI size_t __next_hash_pow2(size_t __n) {
0142 return __n < 2 ? __n : (size_t(1) << (numeric_limits<size_t>::digits - __libcpp_clz(__n - 1)));
0143 }
0144
0145 template <class _Tp, class _Hash, class _Equal, class _Alloc>
0146 class __hash_table;
0147
0148 template <class _NodePtr>
0149 class _LIBCPP_TEMPLATE_VIS __hash_iterator;
0150 template <class _ConstNodePtr>
0151 class _LIBCPP_TEMPLATE_VIS __hash_const_iterator;
0152 template <class _NodePtr>
0153 class _LIBCPP_TEMPLATE_VIS __hash_local_iterator;
0154 template <class _ConstNodePtr>
0155 class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator;
0156 template <class _HashIterator>
0157 class _LIBCPP_TEMPLATE_VIS __hash_map_iterator;
0158 template <class _HashIterator>
0159 class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator;
0160
0161 template <class _Tp>
0162 struct __hash_key_value_types {
0163 static_assert(!is_reference<_Tp>::value && !is_const<_Tp>::value, "");
0164 typedef _Tp key_type;
0165 typedef _Tp __node_value_type;
0166 typedef _Tp __container_value_type;
0167 static const bool __is_map = false;
0168
0169 _LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(_Tp const& __v) { return __v; }
0170 _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(__node_value_type const& __v) { return __v; }
0171 _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) { return std::addressof(__n); }
0172 _LIBCPP_HIDE_FROM_ABI static __container_value_type&& __move(__node_value_type& __v) { return std::move(__v); }
0173 };
0174
0175 template <class _Key, class _Tp>
0176 struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > {
0177 typedef _Key key_type;
0178 typedef _Tp mapped_type;
0179 typedef __hash_value_type<_Key, _Tp> __node_value_type;
0180 typedef pair<const _Key, _Tp> __container_value_type;
0181 typedef __container_value_type __map_value_type;
0182 static const bool __is_map = true;
0183
0184 _LIBCPP_HIDE_FROM_ABI static key_type const& __get_key(__container_value_type const& __v) { return __v.first; }
0185
0186 template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __node_value_type>::value, int> = 0>
0187 _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) {
0188 return __t.__get_value();
0189 }
0190
0191 template <class _Up, __enable_if_t<__is_same_uncvref<_Up, __container_value_type>::value, int> = 0>
0192 _LIBCPP_HIDE_FROM_ABI static __container_value_type const& __get_value(_Up& __t) {
0193 return __t;
0194 }
0195
0196 _LIBCPP_HIDE_FROM_ABI static __container_value_type* __get_ptr(__node_value_type& __n) {
0197 return std::addressof(__n.__get_value());
0198 }
0199 _LIBCPP_HIDE_FROM_ABI static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) { return __v.__move(); }
0200 };
0201
0202 template <class _Tp, class _AllocPtr, class _KVTypes = __hash_key_value_types<_Tp>, bool = _KVTypes::__is_map>
0203 struct __hash_map_pointer_types {};
0204
0205 template <class _Tp, class _AllocPtr, class _KVTypes>
0206 struct __hash_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> {
0207 typedef typename _KVTypes::__map_value_type _Mv;
0208 typedef __rebind_pointer_t<_AllocPtr, _Mv> __map_value_type_pointer;
0209 typedef __rebind_pointer_t<_AllocPtr, const _Mv> __const_map_value_type_pointer;
0210 };
0211
0212 template <class _NodePtr, class _NodeT = typename pointer_traits<_NodePtr>::element_type>
0213 struct __hash_node_types;
0214
0215 template <class _NodePtr, class _Tp, class _VoidPtr>
0216 struct __hash_node_types<_NodePtr, __hash_node<_Tp, _VoidPtr> >
0217 : public __hash_key_value_types<_Tp>,
0218 __hash_map_pointer_types<_Tp, _VoidPtr>
0219
0220 {
0221 typedef __hash_key_value_types<_Tp> __base;
0222
0223 public:
0224 typedef ptrdiff_t difference_type;
0225 typedef size_t size_type;
0226
0227 typedef __rebind_pointer_t<_NodePtr, void> __void_pointer;
0228
0229 typedef typename pointer_traits<_NodePtr>::element_type __node_type;
0230 typedef _NodePtr __node_pointer;
0231
0232 typedef __hash_node_base<__node_pointer> __node_base_type;
0233 typedef __rebind_pointer_t<_NodePtr, __node_base_type> __node_base_pointer;
0234
0235 typedef typename __node_base_type::__next_pointer __next_pointer;
0236
0237 typedef _Tp __node_value_type;
0238 typedef __rebind_pointer_t<_VoidPtr, __node_value_type> __node_value_type_pointer;
0239 typedef __rebind_pointer_t<_VoidPtr, const __node_value_type> __const_node_value_type_pointer;
0240
0241 private:
0242 static_assert(!is_const<__node_type>::value, "_NodePtr should never be a pointer to const");
0243 static_assert(is_same<typename pointer_traits<_VoidPtr>::element_type, void>::value,
0244 "_VoidPtr does not point to unqualified void type");
0245 static_assert(is_same<__rebind_pointer_t<_VoidPtr, __node_type>, _NodePtr>::value,
0246 "_VoidPtr does not rebind to _NodePtr.");
0247 };
0248
0249 template <class _HashIterator>
0250 struct __hash_node_types_from_iterator;
0251 template <class _NodePtr>
0252 struct __hash_node_types_from_iterator<__hash_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
0253 template <class _NodePtr>
0254 struct __hash_node_types_from_iterator<__hash_const_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
0255 template <class _NodePtr>
0256 struct __hash_node_types_from_iterator<__hash_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
0257 template <class _NodePtr>
0258 struct __hash_node_types_from_iterator<__hash_const_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
0259
0260 template <class _NodeValueTp, class _VoidPtr>
0261 struct __make_hash_node_types {
0262 typedef __hash_node<_NodeValueTp, _VoidPtr> _NodeTp;
0263 typedef __rebind_pointer_t<_VoidPtr, _NodeTp> _NodePtr;
0264 typedef __hash_node_types<_NodePtr> type;
0265 };
0266
0267 template <class _NodePtr>
0268 class _LIBCPP_TEMPLATE_VIS __hash_iterator {
0269 typedef __hash_node_types<_NodePtr> _NodeTypes;
0270 typedef _NodePtr __node_pointer;
0271 typedef typename _NodeTypes::__next_pointer __next_pointer;
0272
0273 __next_pointer __node_;
0274
0275 public:
0276 typedef forward_iterator_tag iterator_category;
0277 typedef typename _NodeTypes::__node_value_type value_type;
0278 typedef typename _NodeTypes::difference_type difference_type;
0279 typedef value_type& reference;
0280 typedef typename _NodeTypes::__node_value_type_pointer pointer;
0281
0282 _LIBCPP_HIDE_FROM_ABI __hash_iterator() _NOEXCEPT : __node_(nullptr) {}
0283
0284 _LIBCPP_HIDE_FROM_ABI reference operator*() const {
0285 _LIBCPP_ASSERT_NON_NULL(
0286 __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container iterator");
0287 return __node_->__upcast()->__get_value();
0288 }
0289
0290 _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
0291 _LIBCPP_ASSERT_NON_NULL(
0292 __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container iterator");
0293 return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__get_value());
0294 }
0295
0296 _LIBCPP_HIDE_FROM_ABI __hash_iterator& operator++() {
0297 _LIBCPP_ASSERT_NON_NULL(
0298 __node_ != nullptr, "Attempted to increment a non-incrementable unordered container iterator");
0299 __node_ = __node_->__next_;
0300 return *this;
0301 }
0302
0303 _LIBCPP_HIDE_FROM_ABI __hash_iterator operator++(int) {
0304 __hash_iterator __t(*this);
0305 ++(*this);
0306 return __t;
0307 }
0308
0309 friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __hash_iterator& __x, const __hash_iterator& __y) {
0310 return __x.__node_ == __y.__node_;
0311 }
0312 friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y) {
0313 return !(__x == __y);
0314 }
0315
0316 private:
0317 _LIBCPP_HIDE_FROM_ABI explicit __hash_iterator(__next_pointer __node) _NOEXCEPT : __node_(__node) {}
0318
0319 template <class, class, class, class>
0320 friend class __hash_table;
0321 template <class>
0322 friend class _LIBCPP_TEMPLATE_VIS __hash_const_iterator;
0323 template <class>
0324 friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator;
0325 template <class, class, class, class, class>
0326 friend class _LIBCPP_TEMPLATE_VIS unordered_map;
0327 template <class, class, class, class, class>
0328 friend class _LIBCPP_TEMPLATE_VIS unordered_multimap;
0329 };
0330
0331 template <class _NodePtr>
0332 class _LIBCPP_TEMPLATE_VIS __hash_const_iterator {
0333 static_assert(!is_const<typename pointer_traits<_NodePtr>::element_type>::value, "");
0334 typedef __hash_node_types<_NodePtr> _NodeTypes;
0335 typedef _NodePtr __node_pointer;
0336 typedef typename _NodeTypes::__next_pointer __next_pointer;
0337
0338 __next_pointer __node_;
0339
0340 public:
0341 typedef __hash_iterator<_NodePtr> __non_const_iterator;
0342
0343 typedef forward_iterator_tag iterator_category;
0344 typedef typename _NodeTypes::__node_value_type value_type;
0345 typedef typename _NodeTypes::difference_type difference_type;
0346 typedef const value_type& reference;
0347 typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
0348
0349 _LIBCPP_HIDE_FROM_ABI __hash_const_iterator() _NOEXCEPT : __node_(nullptr) {}
0350
0351 _LIBCPP_HIDE_FROM_ABI __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT : __node_(__x.__node_) {}
0352
0353 _LIBCPP_HIDE_FROM_ABI reference operator*() const {
0354 _LIBCPP_ASSERT_NON_NULL(
0355 __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
0356 return __node_->__upcast()->__get_value();
0357 }
0358 _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
0359 _LIBCPP_ASSERT_NON_NULL(
0360 __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_iterator");
0361 return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__get_value());
0362 }
0363
0364 _LIBCPP_HIDE_FROM_ABI __hash_const_iterator& operator++() {
0365 _LIBCPP_ASSERT_NON_NULL(
0366 __node_ != nullptr, "Attempted to increment a non-incrementable unordered container const_iterator");
0367 __node_ = __node_->__next_;
0368 return *this;
0369 }
0370
0371 _LIBCPP_HIDE_FROM_ABI __hash_const_iterator operator++(int) {
0372 __hash_const_iterator __t(*this);
0373 ++(*this);
0374 return __t;
0375 }
0376
0377 friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y) {
0378 return __x.__node_ == __y.__node_;
0379 }
0380 friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y) {
0381 return !(__x == __y);
0382 }
0383
0384 private:
0385 _LIBCPP_HIDE_FROM_ABI explicit __hash_const_iterator(__next_pointer __node) _NOEXCEPT : __node_(__node) {}
0386
0387 template <class, class, class, class>
0388 friend class __hash_table;
0389 template <class>
0390 friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator;
0391 template <class, class, class, class, class>
0392 friend class _LIBCPP_TEMPLATE_VIS unordered_map;
0393 template <class, class, class, class, class>
0394 friend class _LIBCPP_TEMPLATE_VIS unordered_multimap;
0395 };
0396
0397 template <class _NodePtr>
0398 class _LIBCPP_TEMPLATE_VIS __hash_local_iterator {
0399 typedef __hash_node_types<_NodePtr> _NodeTypes;
0400 typedef _NodePtr __node_pointer;
0401 typedef typename _NodeTypes::__next_pointer __next_pointer;
0402
0403 __next_pointer __node_;
0404 size_t __bucket_;
0405 size_t __bucket_count_;
0406
0407 public:
0408 typedef forward_iterator_tag iterator_category;
0409 typedef typename _NodeTypes::__node_value_type value_type;
0410 typedef typename _NodeTypes::difference_type difference_type;
0411 typedef value_type& reference;
0412 typedef typename _NodeTypes::__node_value_type_pointer pointer;
0413
0414 _LIBCPP_HIDE_FROM_ABI __hash_local_iterator() _NOEXCEPT : __node_(nullptr) {}
0415
0416 _LIBCPP_HIDE_FROM_ABI reference operator*() const {
0417 _LIBCPP_ASSERT_NON_NULL(
0418 __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container local_iterator");
0419 return __node_->__upcast()->__get_value();
0420 }
0421
0422 _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
0423 _LIBCPP_ASSERT_NON_NULL(
0424 __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container local_iterator");
0425 return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__get_value());
0426 }
0427
0428 _LIBCPP_HIDE_FROM_ABI __hash_local_iterator& operator++() {
0429 _LIBCPP_ASSERT_NON_NULL(
0430 __node_ != nullptr, "Attempted to increment a non-incrementable unordered container local_iterator");
0431 __node_ = __node_->__next_;
0432 if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_)
0433 __node_ = nullptr;
0434 return *this;
0435 }
0436
0437 _LIBCPP_HIDE_FROM_ABI __hash_local_iterator operator++(int) {
0438 __hash_local_iterator __t(*this);
0439 ++(*this);
0440 return __t;
0441 }
0442
0443 friend _LIBCPP_HIDE_FROM_ABI bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y) {
0444 return __x.__node_ == __y.__node_;
0445 }
0446 friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y) {
0447 return !(__x == __y);
0448 }
0449
0450 private:
0451 _LIBCPP_HIDE_FROM_ABI explicit __hash_local_iterator(
0452 __next_pointer __node, size_t __bucket, size_t __bucket_count) _NOEXCEPT
0453 : __node_(__node),
0454 __bucket_(__bucket),
0455 __bucket_count_(__bucket_count) {
0456 if (__node_ != nullptr)
0457 __node_ = __node_->__next_;
0458 }
0459
0460 template <class, class, class, class>
0461 friend class __hash_table;
0462 template <class>
0463 friend class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator;
0464 template <class>
0465 friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator;
0466 };
0467
0468 template <class _ConstNodePtr>
0469 class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator {
0470 typedef __hash_node_types<_ConstNodePtr> _NodeTypes;
0471 typedef _ConstNodePtr __node_pointer;
0472 typedef typename _NodeTypes::__next_pointer __next_pointer;
0473
0474 __next_pointer __node_;
0475 size_t __bucket_;
0476 size_t __bucket_count_;
0477
0478 typedef pointer_traits<__node_pointer> __pointer_traits;
0479 typedef typename __pointer_traits::element_type __node;
0480 typedef __remove_const_t<__node> __non_const_node;
0481 typedef __rebind_pointer_t<__node_pointer, __non_const_node> __non_const_node_pointer;
0482
0483 public:
0484 typedef __hash_local_iterator<__non_const_node_pointer> __non_const_iterator;
0485
0486 typedef forward_iterator_tag iterator_category;
0487 typedef typename _NodeTypes::__node_value_type value_type;
0488 typedef typename _NodeTypes::difference_type difference_type;
0489 typedef const value_type& reference;
0490 typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
0491
0492 _LIBCPP_HIDE_FROM_ABI __hash_const_local_iterator() _NOEXCEPT : __node_(nullptr) {}
0493
0494 _LIBCPP_HIDE_FROM_ABI __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT
0495 : __node_(__x.__node_),
0496 __bucket_(__x.__bucket_),
0497 __bucket_count_(__x.__bucket_count_) {}
0498
0499 _LIBCPP_HIDE_FROM_ABI reference operator*() const {
0500 _LIBCPP_ASSERT_NON_NULL(
0501 __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
0502 return __node_->__upcast()->__get_value();
0503 }
0504
0505 _LIBCPP_HIDE_FROM_ABI pointer operator->() const {
0506 _LIBCPP_ASSERT_NON_NULL(
0507 __node_ != nullptr, "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
0508 return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__get_value());
0509 }
0510
0511 _LIBCPP_HIDE_FROM_ABI __hash_const_local_iterator& operator++() {
0512 _LIBCPP_ASSERT_NON_NULL(
0513 __node_ != nullptr, "Attempted to increment a non-incrementable unordered container const_local_iterator");
0514 __node_ = __node_->__next_;
0515 if (__node_ != nullptr && std::__constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_)
0516 __node_ = nullptr;
0517 return *this;
0518 }
0519
0520 _LIBCPP_HIDE_FROM_ABI __hash_const_local_iterator operator++(int) {
0521 __hash_const_local_iterator __t(*this);
0522 ++(*this);
0523 return __t;
0524 }
0525
0526 friend _LIBCPP_HIDE_FROM_ABI bool
0527 operator==(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y) {
0528 return __x.__node_ == __y.__node_;
0529 }
0530 friend _LIBCPP_HIDE_FROM_ABI bool
0531 operator!=(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y) {
0532 return !(__x == __y);
0533 }
0534
0535 private:
0536 _LIBCPP_HIDE_FROM_ABI explicit __hash_const_local_iterator(
0537 __next_pointer __node_ptr, size_t __bucket, size_t __bucket_count) _NOEXCEPT
0538 : __node_(__node_ptr),
0539 __bucket_(__bucket),
0540 __bucket_count_(__bucket_count) {
0541 if (__node_ != nullptr)
0542 __node_ = __node_->__next_;
0543 }
0544
0545 template <class, class, class, class>
0546 friend class __hash_table;
0547 template <class>
0548 friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator;
0549 };
0550
0551 template <class _Alloc>
0552 class __bucket_list_deallocator {
0553 typedef _Alloc allocator_type;
0554 typedef allocator_traits<allocator_type> __alloc_traits;
0555 typedef typename __alloc_traits::size_type size_type;
0556
0557 __compressed_pair<size_type, allocator_type> __data_;
0558
0559 public:
0560 typedef typename __alloc_traits::pointer pointer;
0561
0562 _LIBCPP_HIDE_FROM_ABI __bucket_list_deallocator() _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
0563 : __data_(0, __default_init_tag()) {}
0564
0565 _LIBCPP_HIDE_FROM_ABI __bucket_list_deallocator(const allocator_type& __a, size_type __size)
0566 _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
0567 : __data_(__size, __a) {}
0568
0569 _LIBCPP_HIDE_FROM_ABI __bucket_list_deallocator(__bucket_list_deallocator&& __x)
0570 _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
0571 : __data_(std::move(__x.__data_)) {
0572 __x.size() = 0;
0573 }
0574
0575 _LIBCPP_HIDE_FROM_ABI size_type& size() _NOEXCEPT { return __data_.first(); }
0576 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __data_.first(); }
0577
0578 _LIBCPP_HIDE_FROM_ABI allocator_type& __alloc() _NOEXCEPT { return __data_.second(); }
0579 _LIBCPP_HIDE_FROM_ABI const allocator_type& __alloc() const _NOEXCEPT { return __data_.second(); }
0580
0581 _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT { __alloc_traits::deallocate(__alloc(), __p, size()); }
0582 };
0583
0584 template <class _Alloc>
0585 class __hash_map_node_destructor;
0586
0587 template <class _Alloc>
0588 class __hash_node_destructor {
0589 typedef _Alloc allocator_type;
0590 typedef allocator_traits<allocator_type> __alloc_traits;
0591
0592 public:
0593 typedef typename __alloc_traits::pointer pointer;
0594
0595 private:
0596 typedef __hash_node_types<pointer> _NodeTypes;
0597
0598 allocator_type& __na_;
0599
0600 public:
0601 bool __value_constructed;
0602
0603 _LIBCPP_HIDE_FROM_ABI __hash_node_destructor(__hash_node_destructor const&) = default;
0604 _LIBCPP_HIDE_FROM_ABI __hash_node_destructor& operator=(const __hash_node_destructor&) = delete;
0605
0606 _LIBCPP_HIDE_FROM_ABI explicit __hash_node_destructor(allocator_type& __na, bool __constructed = false) _NOEXCEPT
0607 : __na_(__na),
0608 __value_constructed(__constructed) {}
0609
0610 _LIBCPP_HIDE_FROM_ABI void operator()(pointer __p) _NOEXCEPT {
0611 if (__value_constructed) {
0612 __alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__get_value()));
0613 std::__destroy_at(std::addressof(*__p));
0614 }
0615 if (__p)
0616 __alloc_traits::deallocate(__na_, __p, 1);
0617 }
0618
0619 template <class>
0620 friend class __hash_map_node_destructor;
0621 };
0622
0623 #if _LIBCPP_STD_VER >= 17
0624 template <class _NodeType, class _Alloc>
0625 struct __generic_container_node_destructor;
0626
0627 template <class _Tp, class _VoidPtr, class _Alloc>
0628 struct __generic_container_node_destructor<__hash_node<_Tp, _VoidPtr>, _Alloc> : __hash_node_destructor<_Alloc> {
0629 using __hash_node_destructor<_Alloc>::__hash_node_destructor;
0630 };
0631 #endif
0632
0633 template <class _Key, class _Hash, class _Equal>
0634 struct __enforce_unordered_container_requirements {
0635 #ifndef _LIBCPP_CXX03_LANG
0636 static_assert(__check_hash_requirements<_Key, _Hash>::value,
0637 "the specified hash does not meet the Hash requirements");
0638 static_assert(is_copy_constructible<_Equal>::value, "the specified comparator is required to be copy constructible");
0639 #endif
0640 typedef int type;
0641 };
0642
0643 template <class _Key, class _Hash, class _Equal>
0644 #ifndef _LIBCPP_CXX03_LANG
0645 _LIBCPP_DIAGNOSE_WARNING(!__invokable<_Equal const&, _Key const&, _Key const&>::value,
0646 "the specified comparator type does not provide a viable const call operator")
0647 _LIBCPP_DIAGNOSE_WARNING(!__invokable<_Hash const&, _Key const&>::value,
0648 "the specified hash functor does not provide a viable const call operator")
0649 #endif
0650 typename __enforce_unordered_container_requirements<_Key, _Hash, _Equal>::type
0651 __diagnose_unordered_container_requirements(int);
0652
0653 // This dummy overload is used so that the compiler won't emit a spurious
0654 // "no matching function for call to __diagnose_unordered_xxx" diagnostic
0655 // when the overload above causes a hard error.
0656 template <class _Key, class _Hash, class _Equal>
0657 int __diagnose_unordered_container_requirements(void*);
0658
0659 template <class _Tp, class _Hash, class _Equal, class _Alloc>
0660 class __hash_table {
0661 public:
0662 typedef _Tp value_type;
0663 typedef _Hash hasher;
0664 typedef _Equal key_equal;
0665 typedef _Alloc allocator_type;
0666
0667 private:
0668 typedef allocator_traits<allocator_type> __alloc_traits;
0669 typedef typename __make_hash_node_types<value_type, typename __alloc_traits::void_pointer>::type _NodeTypes;
0670
0671 public:
0672 typedef typename _NodeTypes::__node_value_type __node_value_type;
0673 typedef typename _NodeTypes::__container_value_type __container_value_type;
0674 typedef typename _NodeTypes::key_type key_type;
0675 typedef value_type& reference;
0676 typedef const value_type& const_reference;
0677 typedef typename __alloc_traits::pointer pointer;
0678 typedef typename __alloc_traits::const_pointer const_pointer;
0679 #ifndef _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
0680 typedef typename __alloc_traits::size_type size_type;
0681 #else
0682 typedef typename _NodeTypes::size_type size_type;
0683 #endif
0684 typedef typename _NodeTypes::difference_type difference_type;
0685
0686 public:
0687 // Create __node
0688
0689 typedef typename _NodeTypes::__node_type __node;
0690 typedef __rebind_alloc<__alloc_traits, __node> __node_allocator;
0691 typedef allocator_traits<__node_allocator> __node_traits;
0692 typedef typename _NodeTypes::__void_pointer __void_pointer;
0693 typedef typename _NodeTypes::__node_pointer __node_pointer;
0694 typedef typename _NodeTypes::__node_pointer __node_const_pointer;
0695 typedef typename _NodeTypes::__node_base_type __first_node;
0696 typedef typename _NodeTypes::__node_base_pointer __node_base_pointer;
0697 typedef typename _NodeTypes::__next_pointer __next_pointer;
0698
0699 private:
0700 // check for sane allocator pointer rebinding semantics. Rebinding the
0701 // allocator for a new pointer type should be exactly the same as rebinding
0702 // the pointer using 'pointer_traits'.
0703 static_assert(is_same<__node_pointer, typename __node_traits::pointer>::value,
0704 "Allocator does not rebind pointers in a sane manner.");
0705 typedef __rebind_alloc<__node_traits, __first_node> __node_base_allocator;
0706 typedef allocator_traits<__node_base_allocator> __node_base_traits;
0707 static_assert(is_same<__node_base_pointer, typename __node_base_traits::pointer>::value,
0708 "Allocator does not rebind pointers in a sane manner.");
0709
0710 private:
0711 typedef __rebind_alloc<__node_traits, __next_pointer> __pointer_allocator;
0712 typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter;
0713 typedef unique_ptr<__next_pointer[], __bucket_list_deleter> __bucket_list;
0714 typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits;
0715 typedef typename __bucket_list_deleter::pointer __node_pointer_pointer;
0716
0717 // --- Member data begin ---
0718 __bucket_list __bucket_list_;
0719 __compressed_pair<__first_node, __node_allocator> __p1_;
0720 __compressed_pair<size_type, hasher> __p2_;
0721 __compressed_pair<float, key_equal> __p3_;
0722 // --- Member data end ---
0723
0724 _LIBCPP_HIDE_FROM_ABI size_type& size() _NOEXCEPT { return __p2_.first(); }
0725
0726 public:
0727 _LIBCPP_HIDE_FROM_ABI size_type size() const _NOEXCEPT { return __p2_.first(); }
0728
0729 _LIBCPP_HIDE_FROM_ABI hasher& hash_function() _NOEXCEPT { return __p2_.second(); }
0730 _LIBCPP_HIDE_FROM_ABI const hasher& hash_function() const _NOEXCEPT { return __p2_.second(); }
0731
0732 _LIBCPP_HIDE_FROM_ABI float& max_load_factor() _NOEXCEPT { return __p3_.first(); }
0733 _LIBCPP_HIDE_FROM_ABI float max_load_factor() const _NOEXCEPT { return __p3_.first(); }
0734
0735 _LIBCPP_HIDE_FROM_ABI key_equal& key_eq() _NOEXCEPT { return __p3_.second(); }
0736 _LIBCPP_HIDE_FROM_ABI const key_equal& key_eq() const _NOEXCEPT { return __p3_.second(); }
0737
0738 _LIBCPP_HIDE_FROM_ABI __node_allocator& __node_alloc() _NOEXCEPT { return __p1_.second(); }
0739 _LIBCPP_HIDE_FROM_ABI const __node_allocator& __node_alloc() const _NOEXCEPT { return __p1_.second(); }
0740
0741 public:
0742 typedef __hash_iterator<__node_pointer> iterator;
0743 typedef __hash_const_iterator<__node_pointer> const_iterator;
0744 typedef __hash_local_iterator<__node_pointer> local_iterator;
0745 typedef __hash_const_local_iterator<__node_pointer> const_local_iterator;
0746
0747 _LIBCPP_HIDE_FROM_ABI __hash_table() _NOEXCEPT_(
0748 is_nothrow_default_constructible<__bucket_list>::value&& is_nothrow_default_constructible<__first_node>::value&&
0749 is_nothrow_default_constructible<__node_allocator>::value&& is_nothrow_default_constructible<hasher>::value&&
0750 is_nothrow_default_constructible<key_equal>::value);
0751 _LIBCPP_HIDE_FROM_ABI __hash_table(const hasher& __hf, const key_equal& __eql);
0752 _LIBCPP_HIDE_FROM_ABI __hash_table(const hasher& __hf, const key_equal& __eql, const allocator_type& __a);
0753 _LIBCPP_HIDE_FROM_ABI explicit __hash_table(const allocator_type& __a);
0754 _LIBCPP_HIDE_FROM_ABI __hash_table(const __hash_table& __u);
0755 _LIBCPP_HIDE_FROM_ABI __hash_table(const __hash_table& __u, const allocator_type& __a);
0756 _LIBCPP_HIDE_FROM_ABI __hash_table(__hash_table&& __u) _NOEXCEPT_(
0757 is_nothrow_move_constructible<__bucket_list>::value&& is_nothrow_move_constructible<__first_node>::value&&
0758 is_nothrow_move_constructible<__node_allocator>::value&& is_nothrow_move_constructible<hasher>::value&&
0759 is_nothrow_move_constructible<key_equal>::value);
0760 _LIBCPP_HIDE_FROM_ABI __hash_table(__hash_table&& __u, const allocator_type& __a);
0761 _LIBCPP_HIDE_FROM_ABI ~__hash_table();
0762
0763 _LIBCPP_HIDE_FROM_ABI __hash_table& operator=(const __hash_table& __u);
0764 _LIBCPP_HIDE_FROM_ABI __hash_table& operator=(__hash_table&& __u)
0765 _NOEXCEPT_(__node_traits::propagate_on_container_move_assignment::value&&
0766 is_nothrow_move_assignable<__node_allocator>::value&& is_nothrow_move_assignable<hasher>::value&&
0767 is_nothrow_move_assignable<key_equal>::value);
0768 template <class _InputIterator>
0769 _LIBCPP_HIDE_FROM_ABI void __assign_unique(_InputIterator __first, _InputIterator __last);
0770 template <class _InputIterator>
0771 _LIBCPP_HIDE_FROM_ABI void __assign_multi(_InputIterator __first, _InputIterator __last);
0772
0773 _LIBCPP_HIDE_FROM_ABI size_type max_size() const _NOEXCEPT {
0774 return std::min<size_type>(__node_traits::max_size(__node_alloc()), numeric_limits<difference_type >::max());
0775 }
0776
0777 private:
0778 _LIBCPP_HIDE_FROM_ABI __next_pointer __node_insert_multi_prepare(size_t __cp_hash, value_type& __cp_val);
0779 _LIBCPP_HIDE_FROM_ABI void __node_insert_multi_perform(__node_pointer __cp, __next_pointer __pn) _NOEXCEPT;
0780
0781 _LIBCPP_HIDE_FROM_ABI __next_pointer __node_insert_unique_prepare(size_t __nd_hash, value_type& __nd_val);
0782 _LIBCPP_HIDE_FROM_ABI void __node_insert_unique_perform(__node_pointer __ptr) _NOEXCEPT;
0783
0784 public:
0785 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
0786 _LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(__node_pointer __nd);
0787 _LIBCPP_HIDE_FROM_ABI iterator __node_insert_multi(const_iterator __p, __node_pointer __nd);
0788
0789 template <class _Key, class... _Args>
0790 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_key_args(_Key const& __k, _Args&&... __args);
0791
0792 template <class... _Args>
0793 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_impl(_Args&&... __args);
0794
0795 template <class _Pp>
0796 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_Pp&& __x) {
0797 return __emplace_unique_extract_key(std::forward<_Pp>(__x), __can_extract_key<_Pp, key_type>());
0798 }
0799
0800 template <class _First,
0801 class _Second,
0802 __enable_if_t<__can_extract_map_key<_First, key_type, __container_value_type>::value, int> = 0>
0803 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_First&& __f, _Second&& __s) {
0804 return __emplace_unique_key_args(__f, std::forward<_First>(__f), std::forward<_Second>(__s));
0805 }
0806
0807 template <class... _Args>
0808 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique(_Args&&... __args) {
0809 return __emplace_unique_impl(std::forward<_Args>(__args)...);
0810 }
0811
0812 template <class _Pp>
0813 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, __extract_key_fail_tag) {
0814 return __emplace_unique_impl(std::forward<_Pp>(__x));
0815 }
0816 template <class _Pp>
0817 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, __extract_key_self_tag) {
0818 return __emplace_unique_key_args(__x, std::forward<_Pp>(__x));
0819 }
0820 template <class _Pp>
0821 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __emplace_unique_extract_key(_Pp&& __x, __extract_key_first_tag) {
0822 return __emplace_unique_key_args(__x.first, std::forward<_Pp>(__x));
0823 }
0824
0825 template <class... _Args>
0826 _LIBCPP_HIDE_FROM_ABI iterator __emplace_multi(_Args&&... __args);
0827 template <class... _Args>
0828 _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args);
0829
0830 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __insert_unique(__container_value_type&& __x) {
0831 return __emplace_unique_key_args(_NodeTypes::__get_key(__x), std::move(__x));
0832 }
0833
0834 template <class _Pp, __enable_if_t<!__is_same_uncvref<_Pp, __container_value_type>::value, int> = 0>
0835 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __insert_unique(_Pp&& __x) {
0836 return __emplace_unique(std::forward<_Pp>(__x));
0837 }
0838
0839 template <class _Pp>
0840 _LIBCPP_HIDE_FROM_ABI iterator __insert_multi(_Pp&& __x) {
0841 return __emplace_multi(std::forward<_Pp>(__x));
0842 }
0843
0844 template <class _Pp>
0845 _LIBCPP_HIDE_FROM_ABI iterator __insert_multi(const_iterator __p, _Pp&& __x) {
0846 return __emplace_hint_multi(__p, std::forward<_Pp>(__x));
0847 }
0848
0849 _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __insert_unique(const __container_value_type& __x) {
0850 return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x);
0851 }
0852
0853 #if _LIBCPP_STD_VER >= 17
0854 template <class _NodeHandle, class _InsertReturnType>
0855 _LIBCPP_HIDE_FROM_ABI _InsertReturnType __node_handle_insert_unique(_NodeHandle&& __nh);
0856 template <class _NodeHandle>
0857 _LIBCPP_HIDE_FROM_ABI iterator __node_handle_insert_unique(const_iterator __hint, _NodeHandle&& __nh);
0858 template <class _Table>
0859 _LIBCPP_HIDE_FROM_ABI void __node_handle_merge_unique(_Table& __source);
0860
0861 template <class _NodeHandle>
0862 _LIBCPP_HIDE_FROM_ABI iterator __node_handle_insert_multi(_NodeHandle&& __nh);
0863 template <class _NodeHandle>
0864 _LIBCPP_HIDE_FROM_ABI iterator __node_handle_insert_multi(const_iterator __hint, _NodeHandle&& __nh);
0865 template <class _Table>
0866 _LIBCPP_HIDE_FROM_ABI void __node_handle_merge_multi(_Table& __source);
0867
0868 template <class _NodeHandle>
0869 _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(key_type const& __key);
0870 template <class _NodeHandle>
0871 _LIBCPP_HIDE_FROM_ABI _NodeHandle __node_handle_extract(const_iterator __it);
0872 #endif
0873
0874 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT;
0875 _LIBCPP_HIDE_FROM_ABI void __rehash_unique(size_type __n) { __rehash<true>(__n); }
0876 _LIBCPP_HIDE_FROM_ABI void __rehash_multi(size_type __n) { __rehash<false>(__n); }
0877 _LIBCPP_HIDE_FROM_ABI void __reserve_unique(size_type __n) {
0878 __rehash_unique(static_cast<size_type>(std::ceil(__n / max_load_factor())));
0879 }
0880 _LIBCPP_HIDE_FROM_ABI void __reserve_multi(size_type __n) {
0881 __rehash_multi(static_cast<size_type>(std::ceil(__n / max_load_factor())));
0882 }
0883
0884 _LIBCPP_HIDE_FROM_ABI size_type bucket_count() const _NOEXCEPT { return __bucket_list_.get_deleter().size(); }
0885
0886 _LIBCPP_HIDE_FROM_ABI iterator begin() _NOEXCEPT;
0887 _LIBCPP_HIDE_FROM_ABI iterator end() _NOEXCEPT;
0888 _LIBCPP_HIDE_FROM_ABI const_iterator begin() const _NOEXCEPT;
0889 _LIBCPP_HIDE_FROM_ABI const_iterator end() const _NOEXCEPT;
0890
0891 template <class _Key>
0892 _LIBCPP_HIDE_FROM_ABI size_type bucket(const _Key& __k) const {
0893 _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
0894 bucket_count() > 0, "unordered container::bucket(key) called when bucket_count() == 0");
0895 return std::__constrain_hash(hash_function()(__k), bucket_count());
0896 }
0897
0898 template <class _Key>
0899 _LIBCPP_HIDE_FROM_ABI iterator find(const _Key& __x);
0900 template <class _Key>
0901 _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Key& __x) const;
0902
0903 typedef __hash_node_destructor<__node_allocator> _Dp;
0904 typedef unique_ptr<__node, _Dp> __node_holder;
0905
0906 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __p);
0907 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last);
0908 template <class _Key>
0909 _LIBCPP_HIDE_FROM_ABI size_type __erase_unique(const _Key& __k);
0910 template <class _Key>
0911 _LIBCPP_HIDE_FROM_ABI size_type __erase_multi(const _Key& __k);
0912 _LIBCPP_HIDE_FROM_ABI __node_holder remove(const_iterator __p) _NOEXCEPT;
0913
0914 template <class _Key>
0915 _LIBCPP_HIDE_FROM_ABI size_type __count_unique(const _Key& __k) const;
0916 template <class _Key>
0917 _LIBCPP_HIDE_FROM_ABI size_type __count_multi(const _Key& __k) const;
0918
0919 template <class _Key>
0920 _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> __equal_range_unique(const _Key& __k);
0921 template <class _Key>
0922 _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> __equal_range_unique(const _Key& __k) const;
0923
0924 template <class _Key>
0925 _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> __equal_range_multi(const _Key& __k);
0926 template <class _Key>
0927 _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> __equal_range_multi(const _Key& __k) const;
0928
0929 _LIBCPP_HIDE_FROM_ABI void swap(__hash_table& __u)
0930 #if _LIBCPP_STD_VER <= 11
0931 _NOEXCEPT_(__is_nothrow_swappable_v<hasher>&& __is_nothrow_swappable_v<key_equal> &&
0932 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
0933 __is_nothrow_swappable_v<__pointer_allocator>) &&
0934 (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>));
0935 #else
0936 _NOEXCEPT_(__is_nothrow_swappable_v<hasher>&& __is_nothrow_swappable_v<key_equal>);
0937 #endif
0938
0939 _LIBCPP_HIDE_FROM_ABI size_type max_bucket_count() const _NOEXCEPT { return max_size(); }
0940 _LIBCPP_HIDE_FROM_ABI size_type bucket_size(size_type __n) const;
0941 _LIBCPP_HIDE_FROM_ABI float load_factor() const _NOEXCEPT {
0942 size_type __bc = bucket_count();
0943 return __bc != 0 ? (float)size() / __bc : 0.f;
0944 }
0945 _LIBCPP_HIDE_FROM_ABI void max_load_factor(float __mlf) _NOEXCEPT {
0946 // While passing a non-positive load factor is undefined behavior, in practice the result will be benign (the
0947 // call will be equivalent to `max_load_factor(load_factor())`, which is also the case for passing a valid value
0948 // less than the current `load_factor`).
0949 _LIBCPP_ASSERT_PEDANTIC(__mlf > 0, "unordered container::max_load_factor(lf) called with lf <= 0");
0950 max_load_factor() = std::max(__mlf, load_factor());
0951 }
0952
0953 _LIBCPP_HIDE_FROM_ABI local_iterator begin(size_type __n) {
0954 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0955 __n < bucket_count(), "unordered container::begin(n) called with n >= bucket_count()");
0956 return local_iterator(__bucket_list_[__n], __n, bucket_count());
0957 }
0958
0959 _LIBCPP_HIDE_FROM_ABI local_iterator end(size_type __n) {
0960 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0961 __n < bucket_count(), "unordered container::end(n) called with n >= bucket_count()");
0962 return local_iterator(nullptr, __n, bucket_count());
0963 }
0964
0965 _LIBCPP_HIDE_FROM_ABI const_local_iterator cbegin(size_type __n) const {
0966 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0967 __n < bucket_count(), "unordered container::cbegin(n) called with n >= bucket_count()");
0968 return const_local_iterator(__bucket_list_[__n], __n, bucket_count());
0969 }
0970
0971 _LIBCPP_HIDE_FROM_ABI const_local_iterator cend(size_type __n) const {
0972 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
0973 __n < bucket_count(), "unordered container::cend(n) called with n >= bucket_count()");
0974 return const_local_iterator(nullptr, __n, bucket_count());
0975 }
0976
0977 private:
0978 template <bool _UniqueKeys>
0979 _LIBCPP_HIDE_FROM_ABI void __rehash(size_type __n);
0980 template <bool _UniqueKeys>
0981 _LIBCPP_HIDE_FROM_ABI void __do_rehash(size_type __n);
0982
0983 template <class... _Args>
0984 _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node(_Args&&... __args);
0985
0986 template <class _First, class... _Rest>
0987 _LIBCPP_HIDE_FROM_ABI __node_holder __construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest);
0988
0989 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __hash_table& __u) {
0990 __copy_assign_alloc(__u, integral_constant<bool, __node_traits::propagate_on_container_copy_assignment::value>());
0991 }
0992 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __hash_table& __u, true_type);
0993 _LIBCPP_HIDE_FROM_ABI void __copy_assign_alloc(const __hash_table&, false_type) {}
0994
0995 _LIBCPP_HIDE_FROM_ABI void __move_assign(__hash_table& __u, false_type);
0996 _LIBCPP_HIDE_FROM_ABI void __move_assign(__hash_table& __u, true_type)
0997 _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value&& is_nothrow_move_assignable<hasher>::value&&
0998 is_nothrow_move_assignable<key_equal>::value);
0999 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__hash_table& __u) _NOEXCEPT_(
1000 !__node_traits::propagate_on_container_move_assignment::value ||
1001 (is_nothrow_move_assignable<__pointer_allocator>::value && is_nothrow_move_assignable<__node_allocator>::value)) {
1002 __move_assign_alloc(__u, integral_constant<bool, __node_traits::propagate_on_container_move_assignment::value>());
1003 }
1004 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__hash_table& __u, true_type) _NOEXCEPT_(
1005 is_nothrow_move_assignable<__pointer_allocator>::value&& is_nothrow_move_assignable<__node_allocator>::value) {
1006 __bucket_list_.get_deleter().__alloc() = std::move(__u.__bucket_list_.get_deleter().__alloc());
1007 __node_alloc() = std::move(__u.__node_alloc());
1008 }
1009 _LIBCPP_HIDE_FROM_ABI void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {}
1010
1011 _LIBCPP_HIDE_FROM_ABI void __deallocate_node(__next_pointer __np) _NOEXCEPT;
1012 _LIBCPP_HIDE_FROM_ABI __next_pointer __detach() _NOEXCEPT;
1013
1014 template <class, class, class, class, class>
1015 friend class _LIBCPP_TEMPLATE_VIS unordered_map;
1016 template <class, class, class, class, class>
1017 friend class _LIBCPP_TEMPLATE_VIS unordered_multimap;
1018 };
1019
1020 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1021 inline __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table() _NOEXCEPT_(
1022 is_nothrow_default_constructible<__bucket_list>::value&& is_nothrow_default_constructible<__first_node>::value&&
1023 is_nothrow_default_constructible<__node_allocator>::value&& is_nothrow_default_constructible<hasher>::value&&
1024 is_nothrow_default_constructible<key_equal>::value)
1025 : __p2_(0, __default_init_tag()), __p3_(1.0f, __default_init_tag()) {}
1026
1027 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1028 inline __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf, const key_equal& __eql)
1029 : __bucket_list_(nullptr, __bucket_list_deleter()), __p1_(), __p2_(0, __hf), __p3_(1.0f, __eql) {}
1030
1031 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1032 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(
1033 const hasher& __hf, const key_equal& __eql, const allocator_type& __a)
1034 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1035 __p1_(__default_init_tag(), __node_allocator(__a)),
1036 __p2_(0, __hf),
1037 __p3_(1.0f, __eql) {}
1038
1039 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1040 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
1041 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1042 __p1_(__default_init_tag(), __node_allocator(__a)),
1043 __p2_(0, __default_init_tag()),
1044 __p3_(1.0f, __default_init_tag()) {}
1045
1046 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1047 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
1048 : __bucket_list_(nullptr,
1049 __bucket_list_deleter(allocator_traits<__pointer_allocator>::select_on_container_copy_construction(
1050 __u.__bucket_list_.get_deleter().__alloc()),
1051 0)),
1052 __p1_(__default_init_tag(),
1053 allocator_traits<__node_allocator>::select_on_container_copy_construction(__u.__node_alloc())),
1054 __p2_(0, __u.hash_function()),
1055 __p3_(__u.__p3_) {}
1056
1057 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1058 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u, const allocator_type& __a)
1059 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1060 __p1_(__default_init_tag(), __node_allocator(__a)),
1061 __p2_(0, __u.hash_function()),
1062 __p3_(__u.__p3_) {}
1063
1064 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1065 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u) _NOEXCEPT_(
1066 is_nothrow_move_constructible<__bucket_list>::value&& is_nothrow_move_constructible<__first_node>::value&&
1067 is_nothrow_move_constructible<__node_allocator>::value&& is_nothrow_move_constructible<hasher>::value&&
1068 is_nothrow_move_constructible<key_equal>::value)
1069 : __bucket_list_(std::move(__u.__bucket_list_)),
1070 __p1_(std::move(__u.__p1_)),
1071 __p2_(std::move(__u.__p2_)),
1072 __p3_(std::move(__u.__p3_)) {
1073 if (size() > 0) {
1074 __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr();
1075 __u.__p1_.first().__next_ = nullptr;
1076 __u.size() = 0;
1077 }
1078 }
1079
1080 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1081 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u, const allocator_type& __a)
1082 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1083 __p1_(__default_init_tag(), __node_allocator(__a)),
1084 __p2_(0, std::move(__u.hash_function())),
1085 __p3_(std::move(__u.__p3_)) {
1086 if (__a == allocator_type(__u.__node_alloc())) {
1087 __bucket_list_.reset(__u.__bucket_list_.release());
1088 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
1089 __u.__bucket_list_.get_deleter().size() = 0;
1090 if (__u.size() > 0) {
1091 __p1_.first().__next_ = __u.__p1_.first().__next_;
1092 __u.__p1_.first().__next_ = nullptr;
1093 __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr();
1094 size() = __u.size();
1095 __u.size() = 0;
1096 }
1097 }
1098 }
1099
1100 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1101 __hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table() {
1102 #if defined(_LIBCPP_CXX03_LANG)
1103 static_assert(is_copy_constructible<key_equal>::value, "Predicate must be copy-constructible.");
1104 static_assert(is_copy_constructible<hasher>::value, "Hasher must be copy-constructible.");
1105 #endif
1106
1107 __deallocate_node(__p1_.first().__next_);
1108 }
1109
1110 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1111 void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc(const __hash_table& __u, true_type) {
1112 if (__node_alloc() != __u.__node_alloc()) {
1113 clear();
1114 __bucket_list_.reset();
1115 __bucket_list_.get_deleter().size() = 0;
1116 }
1117 __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc();
1118 __node_alloc() = __u.__node_alloc();
1119 }
1120
1121 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1122 __hash_table<_Tp, _Hash, _Equal, _Alloc>& __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u) {
1123 if (this != std::addressof(__u)) {
1124 __copy_assign_alloc(__u);
1125 hash_function() = __u.hash_function();
1126 key_eq() = __u.key_eq();
1127 max_load_factor() = __u.max_load_factor();
1128 __assign_multi(__u.begin(), __u.end());
1129 }
1130 return *this;
1131 }
1132
1133 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1134 void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate_node(__next_pointer __np) _NOEXCEPT {
1135 __node_allocator& __na = __node_alloc();
1136 while (__np != nullptr) {
1137 __next_pointer __next = __np->__next_;
1138 __node_pointer __real_np = __np->__upcast();
1139 __node_traits::destroy(__na, _NodeTypes::__get_ptr(__real_np->__get_value()));
1140 std::__destroy_at(std::addressof(*__real_np));
1141 __node_traits::deallocate(__na, __real_np, 1);
1142 __np = __next;
1143 }
1144 }
1145
1146 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1147 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
1148 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT {
1149 size_type __bc = bucket_count();
1150 for (size_type __i = 0; __i < __bc; ++__i)
1151 __bucket_list_[__i] = nullptr;
1152 size() = 0;
1153 __next_pointer __cache = __p1_.first().__next_;
1154 __p1_.first().__next_ = nullptr;
1155 return __cache;
1156 }
1157
1158 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1159 void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(__hash_table& __u, true_type)
1160 _NOEXCEPT_(is_nothrow_move_assignable<__node_allocator>::value&& is_nothrow_move_assignable<hasher>::value&&
1161 is_nothrow_move_assignable<key_equal>::value) {
1162 clear();
1163 __bucket_list_.reset(__u.__bucket_list_.release());
1164 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
1165 __u.__bucket_list_.get_deleter().size() = 0;
1166 __move_assign_alloc(__u);
1167 size() = __u.size();
1168 hash_function() = std::move(__u.hash_function());
1169 max_load_factor() = __u.max_load_factor();
1170 key_eq() = std::move(__u.key_eq());
1171 __p1_.first().__next_ = __u.__p1_.first().__next_;
1172 if (size() > 0) {
1173 __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr();
1174 __u.__p1_.first().__next_ = nullptr;
1175 __u.size() = 0;
1176 }
1177 }
1178
1179 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1180 void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(__hash_table& __u, false_type) {
1181 if (__node_alloc() == __u.__node_alloc())
1182 __move_assign(__u, true_type());
1183 else {
1184 hash_function() = std::move(__u.hash_function());
1185 key_eq() = std::move(__u.key_eq());
1186 max_load_factor() = __u.max_load_factor();
1187 if (bucket_count() != 0) {
1188 __next_pointer __cache = __detach();
1189 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1190 try {
1191 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
1192 const_iterator __i = __u.begin();
1193 while (__cache != nullptr && __u.size() != 0) {
1194 __cache->__upcast()->__get_value() = std::move(__u.remove(__i++)->__get_value());
1195 __next_pointer __next = __cache->__next_;
1196 __node_insert_multi(__cache->__upcast());
1197 __cache = __next;
1198 }
1199 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1200 } catch (...) {
1201 __deallocate_node(__cache);
1202 throw;
1203 }
1204 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
1205 __deallocate_node(__cache);
1206 }
1207 const_iterator __i = __u.begin();
1208 while (__u.size() != 0) {
1209 __node_holder __h = __construct_node(_NodeTypes::__move(__u.remove(__i++)->__get_value()));
1210 __node_insert_multi(__h.get());
1211 __h.release();
1212 }
1213 }
1214 }
1215
1216 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1217 inline __hash_table<_Tp, _Hash, _Equal, _Alloc>&
1218 __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u) _NOEXCEPT_(
1219 __node_traits::propagate_on_container_move_assignment::value&& is_nothrow_move_assignable<__node_allocator>::value&&
1220 is_nothrow_move_assignable<hasher>::value&& is_nothrow_move_assignable<key_equal>::value) {
1221 __move_assign(__u, integral_constant<bool, __node_traits::propagate_on_container_move_assignment::value>());
1222 return *this;
1223 }
1224
1225 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1226 template <class _InputIterator>
1227 void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first, _InputIterator __last) {
1228 typedef iterator_traits<_InputIterator> _ITraits;
1229 typedef typename _ITraits::value_type _ItValueType;
1230 static_assert(is_same<_ItValueType, __container_value_type>::value,
1231 "__assign_unique may only be called with the containers value type");
1232
1233 if (bucket_count() != 0) {
1234 __next_pointer __cache = __detach();
1235 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1236 try {
1237 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
1238 for (; __cache != nullptr && __first != __last; ++__first) {
1239 __cache->__upcast()->__get_value() = *__first;
1240 __next_pointer __next = __cache->__next_;
1241 __node_insert_unique(__cache->__upcast());
1242 __cache = __next;
1243 }
1244 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1245 } catch (...) {
1246 __deallocate_node(__cache);
1247 throw;
1248 }
1249 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
1250 __deallocate_node(__cache);
1251 }
1252 for (; __first != __last; ++__first)
1253 __insert_unique(*__first);
1254 }
1255
1256 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1257 template <class _InputIterator>
1258 void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first, _InputIterator __last) {
1259 typedef iterator_traits<_InputIterator> _ITraits;
1260 typedef typename _ITraits::value_type _ItValueType;
1261 static_assert(
1262 (is_same<_ItValueType, __container_value_type>::value || is_same<_ItValueType, __node_value_type>::value),
1263 "__assign_multi may only be called with the containers value type"
1264 " or the nodes value type");
1265 if (bucket_count() != 0) {
1266 __next_pointer __cache = __detach();
1267 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1268 try {
1269 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
1270 for (; __cache != nullptr && __first != __last; ++__first) {
1271 __cache->__upcast()->__get_value() = *__first;
1272 __next_pointer __next = __cache->__next_;
1273 __node_insert_multi(__cache->__upcast());
1274 __cache = __next;
1275 }
1276 #ifndef _LIBCPP_HAS_NO_EXCEPTIONS
1277 } catch (...) {
1278 __deallocate_node(__cache);
1279 throw;
1280 }
1281 #endif // _LIBCPP_HAS_NO_EXCEPTIONS
1282 __deallocate_node(__cache);
1283 }
1284 for (; __first != __last; ++__first)
1285 __insert_multi(_NodeTypes::__get_value(*__first));
1286 }
1287
1288 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1289 inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1290 __hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT {
1291 return iterator(__p1_.first().__next_);
1292 }
1293
1294 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1295 inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1296 __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT {
1297 return iterator(nullptr);
1298 }
1299
1300 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1301 inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1302 __hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT {
1303 return const_iterator(__p1_.first().__next_);
1304 }
1305
1306 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1307 inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1308 __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT {
1309 return const_iterator(nullptr);
1310 }
1311
1312 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1313 void __hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT {
1314 if (size() > 0) {
1315 __deallocate_node(__p1_.first().__next_);
1316 __p1_.first().__next_ = nullptr;
1317 size_type __bc = bucket_count();
1318 for (size_type __i = 0; __i < __bc; ++__i)
1319 __bucket_list_[__i] = nullptr;
1320 size() = 0;
1321 }
1322 }
1323
1324 // Prepare the container for an insertion of the value __value with the hash
1325 // __hash. This does a lookup into the container to see if __value is already
1326 // present, and performs a rehash if necessary. Returns a pointer to the
1327 // existing element if it exists, otherwise nullptr.
1328 //
1329 // Note that this function does forward exceptions if key_eq() throws, and never
1330 // mutates __value or actually inserts into the map.
1331 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1332 _LIBCPP_HIDE_FROM_ABI typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
1333 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_prepare(size_t __hash, value_type& __value) {
1334 size_type __bc = bucket_count();
1335
1336 if (__bc != 0) {
1337 size_t __chash = std::__constrain_hash(__hash, __bc);
1338 __next_pointer __ndptr = __bucket_list_[__chash];
1339 if (__ndptr != nullptr) {
1340 for (__ndptr = __ndptr->__next_;
1341 __ndptr != nullptr &&
1342 (__ndptr->__hash() == __hash || std::__constrain_hash(__ndptr->__hash(), __bc) == __chash);
1343 __ndptr = __ndptr->__next_) {
1344 if ((__ndptr->__hash() == __hash) && key_eq()(__ndptr->__upcast()->__get_value(), __value))
1345 return __ndptr;
1346 }
1347 }
1348 }
1349 if (size() + 1 > __bc * max_load_factor() || __bc == 0) {
1350 __rehash_unique(std::max<size_type>(
1351 2 * __bc + !std::__is_hash_power2(__bc), size_type(std::ceil(float(size() + 1) / max_load_factor()))));
1352 }
1353 return nullptr;
1354 }
1355
1356 // Insert the node __nd into the container by pushing it into the right bucket,
1357 // and updating size(). Assumes that __nd->__hash is up-to-date, and that
1358 // rehashing has already occurred and that no element with the same key exists
1359 // in the map.
1360 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1361 _LIBCPP_HIDE_FROM_ABI void
1362 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_perform(__node_pointer __nd) _NOEXCEPT {
1363 size_type __bc = bucket_count();
1364 size_t __chash = std::__constrain_hash(__nd->__hash(), __bc);
1365 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1366 __next_pointer __pn = __bucket_list_[__chash];
1367 if (__pn == nullptr) {
1368 __pn = __p1_.first().__ptr();
1369 __nd->__next_ = __pn->__next_;
1370 __pn->__next_ = __nd->__ptr();
1371 // fix up __bucket_list_
1372 __bucket_list_[__chash] = __pn;
1373 if (__nd->__next_ != nullptr)
1374 __bucket_list_[std::__constrain_hash(__nd->__next_->__hash(), __bc)] = __nd->__ptr();
1375 } else {
1376 __nd->__next_ = __pn->__next_;
1377 __pn->__next_ = __nd->__ptr();
1378 }
1379 ++size();
1380 }
1381
1382 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1383 pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1384 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd) {
1385 __nd->__hash_ = hash_function()(__nd->__get_value());
1386 __next_pointer __existing_node = __node_insert_unique_prepare(__nd->__hash(), __nd->__get_value());
1387
1388 // Insert the node, unless it already exists in the container.
1389 bool __inserted = false;
1390 if (__existing_node == nullptr) {
1391 __node_insert_unique_perform(__nd);
1392 __existing_node = __nd->__ptr();
1393 __inserted = true;
1394 }
1395 return pair<iterator, bool>(iterator(__existing_node), __inserted);
1396 }
1397
1398 // Prepare the container for an insertion of the value __cp_val with the hash
1399 // __cp_hash. This does a lookup into the container to see if __cp_value is
1400 // already present, and performs a rehash if necessary. Returns a pointer to the
1401 // last occurrence of __cp_val in the map.
1402 //
1403 // Note that this function does forward exceptions if key_eq() throws, and never
1404 // mutates __value or actually inserts into the map.
1405 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1406 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
1407 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_prepare(size_t __cp_hash, value_type& __cp_val) {
1408 size_type __bc = bucket_count();
1409 if (size() + 1 > __bc * max_load_factor() || __bc == 0) {
1410 __rehash_multi(std::max<size_type>(
1411 2 * __bc + !std::__is_hash_power2(__bc), size_type(std::ceil(float(size() + 1) / max_load_factor()))));
1412 __bc = bucket_count();
1413 }
1414 size_t __chash = std::__constrain_hash(__cp_hash, __bc);
1415 __next_pointer __pn = __bucket_list_[__chash];
1416 if (__pn != nullptr) {
1417 for (bool __found = false;
1418 __pn->__next_ != nullptr && std::__constrain_hash(__pn->__next_->__hash(), __bc) == __chash;
1419 __pn = __pn->__next_) {
1420 // __found key_eq() action
1421 // false false loop
1422 // true true loop
1423 // false true set __found to true
1424 // true false break
1425 if (__found !=
1426 (__pn->__next_->__hash() == __cp_hash && key_eq()(__pn->__next_->__upcast()->__get_value(), __cp_val))) {
1427 if (!__found)
1428 __found = true;
1429 else
1430 break;
1431 }
1432 }
1433 }
1434 return __pn;
1435 }
1436
1437 // Insert the node __cp into the container after __pn (which is the last node in
1438 // the bucket that compares equal to __cp). Rehashing, and checking for
1439 // uniqueness has already been performed (in __node_insert_multi_prepare), so
1440 // all we need to do is update the bucket and size(). Assumes that __cp->__hash
1441 // is up-to-date.
1442 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1443 void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_perform(
1444 __node_pointer __cp, __next_pointer __pn) _NOEXCEPT {
1445 size_type __bc = bucket_count();
1446 size_t __chash = std::__constrain_hash(__cp->__hash_, __bc);
1447 if (__pn == nullptr) {
1448 __pn = __p1_.first().__ptr();
1449 __cp->__next_ = __pn->__next_;
1450 __pn->__next_ = __cp->__ptr();
1451 // fix up __bucket_list_
1452 __bucket_list_[__chash] = __pn;
1453 if (__cp->__next_ != nullptr)
1454 __bucket_list_[std::__constrain_hash(__cp->__next_->__hash(), __bc)] = __cp->__ptr();
1455 } else {
1456 __cp->__next_ = __pn->__next_;
1457 __pn->__next_ = __cp->__ptr();
1458 if (__cp->__next_ != nullptr) {
1459 size_t __nhash = std::__constrain_hash(__cp->__next_->__hash(), __bc);
1460 if (__nhash != __chash)
1461 __bucket_list_[__nhash] = __cp->__ptr();
1462 }
1463 }
1464 ++size();
1465 }
1466
1467 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1468 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1469 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp) {
1470 __cp->__hash_ = hash_function()(__cp->__get_value());
1471 __next_pointer __pn = __node_insert_multi_prepare(__cp->__hash(), __cp->__get_value());
1472 __node_insert_multi_perform(__cp, __pn);
1473
1474 return iterator(__cp->__ptr());
1475 }
1476
1477 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1478 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1479 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(const_iterator __p, __node_pointer __cp) {
1480 if (__p != end() && key_eq()(*__p, __cp->__get_value())) {
1481 __next_pointer __np = __p.__node_;
1482 __cp->__hash_ = __np->__hash();
1483 size_type __bc = bucket_count();
1484 if (size() + 1 > __bc * max_load_factor() || __bc == 0) {
1485 __rehash_multi(std::max<size_type>(
1486 2 * __bc + !std::__is_hash_power2(__bc), size_type(std::ceil(float(size() + 1) / max_load_factor()))));
1487 __bc = bucket_count();
1488 }
1489 size_t __chash = std::__constrain_hash(__cp->__hash_, __bc);
1490 __next_pointer __pp = __bucket_list_[__chash];
1491 while (__pp->__next_ != __np)
1492 __pp = __pp->__next_;
1493 __cp->__next_ = __np;
1494 __pp->__next_ = static_cast<__next_pointer>(__cp);
1495 ++size();
1496 return iterator(static_cast<__next_pointer>(__cp));
1497 }
1498 return __node_insert_multi(__cp);
1499 }
1500
1501 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1502 template <class _Key, class... _Args>
1503 pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1504 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args) {
1505 size_t __hash = hash_function()(__k);
1506 size_type __bc = bucket_count();
1507 bool __inserted = false;
1508 __next_pointer __nd;
1509 size_t __chash;
1510 if (__bc != 0) {
1511 __chash = std::__constrain_hash(__hash, __bc);
1512 __nd = __bucket_list_[__chash];
1513 if (__nd != nullptr) {
1514 for (__nd = __nd->__next_;
1515 __nd != nullptr && (__nd->__hash() == __hash || std::__constrain_hash(__nd->__hash(), __bc) == __chash);
1516 __nd = __nd->__next_) {
1517 if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__get_value(), __k))
1518 goto __done;
1519 }
1520 }
1521 }
1522 {
1523 __node_holder __h = __construct_node_hash(__hash, std::forward<_Args>(__args)...);
1524 if (size() + 1 > __bc * max_load_factor() || __bc == 0) {
1525 __rehash_unique(std::max<size_type>(
1526 2 * __bc + !std::__is_hash_power2(__bc), size_type(std::ceil(float(size() + 1) / max_load_factor()))));
1527 __bc = bucket_count();
1528 __chash = std::__constrain_hash(__hash, __bc);
1529 }
1530 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1531 __next_pointer __pn = __bucket_list_[__chash];
1532 if (__pn == nullptr) {
1533 __pn = __p1_.first().__ptr();
1534 __h->__next_ = __pn->__next_;
1535 __pn->__next_ = __h.get()->__ptr();
1536 // fix up __bucket_list_
1537 __bucket_list_[__chash] = __pn;
1538 if (__h->__next_ != nullptr)
1539 __bucket_list_[std::__constrain_hash(__h->__next_->__hash(), __bc)] = __h.get()->__ptr();
1540 } else {
1541 __h->__next_ = __pn->__next_;
1542 __pn->__next_ = static_cast<__next_pointer>(__h.get());
1543 }
1544 __nd = static_cast<__next_pointer>(__h.release());
1545 // increment size
1546 ++size();
1547 __inserted = true;
1548 }
1549 __done:
1550 return pair<iterator, bool>(iterator(__nd), __inserted);
1551 }
1552
1553 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1554 template <class... _Args>
1555 pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1556 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_impl(_Args&&... __args) {
1557 __node_holder __h = __construct_node(std::forward<_Args>(__args)...);
1558 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1559 if (__r.second)
1560 __h.release();
1561 return __r;
1562 }
1563
1564 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1565 template <class... _Args>
1566 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1567 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args) {
1568 __node_holder __h = __construct_node(std::forward<_Args>(__args)...);
1569 iterator __r = __node_insert_multi(__h.get());
1570 __h.release();
1571 return __r;
1572 }
1573
1574 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1575 template <class... _Args>
1576 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1577 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi(const_iterator __p, _Args&&... __args) {
1578 __node_holder __h = __construct_node(std::forward<_Args>(__args)...);
1579 iterator __r = __node_insert_multi(__p, __h.get());
1580 __h.release();
1581 return __r;
1582 }
1583
1584 #if _LIBCPP_STD_VER >= 17
1585 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1586 template <class _NodeHandle, class _InsertReturnType>
1587 _LIBCPP_HIDE_FROM_ABI _InsertReturnType
1588 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(_NodeHandle&& __nh) {
1589 if (__nh.empty())
1590 return _InsertReturnType{end(), false, _NodeHandle()};
1591 pair<iterator, bool> __result = __node_insert_unique(__nh.__ptr_);
1592 if (__result.second)
1593 __nh.__release_ptr();
1594 return _InsertReturnType{__result.first, __result.second, std::move(__nh)};
1595 }
1596
1597 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1598 template <class _NodeHandle>
1599 _LIBCPP_HIDE_FROM_ABI typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1600 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(const_iterator, _NodeHandle&& __nh) {
1601 if (__nh.empty())
1602 return end();
1603 pair<iterator, bool> __result = __node_insert_unique(__nh.__ptr_);
1604 if (__result.second)
1605 __nh.__release_ptr();
1606 return __result.first;
1607 }
1608
1609 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1610 template <class _NodeHandle>
1611 _LIBCPP_HIDE_FROM_ABI _NodeHandle
1612 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(key_type const& __key) {
1613 iterator __i = find(__key);
1614 if (__i == end())
1615 return _NodeHandle();
1616 return __node_handle_extract<_NodeHandle>(__i);
1617 }
1618
1619 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1620 template <class _NodeHandle>
1621 _LIBCPP_HIDE_FROM_ABI _NodeHandle __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(const_iterator __p) {
1622 allocator_type __alloc(__node_alloc());
1623 return _NodeHandle(remove(__p).release(), __alloc);
1624 }
1625
1626 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1627 template <class _Table>
1628 _LIBCPP_HIDE_FROM_ABI void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_unique(_Table& __source) {
1629 static_assert(is_same<__node, typename _Table::__node>::value, "");
1630
1631 for (typename _Table::iterator __it = __source.begin(); __it != __source.end();) {
1632 __node_pointer __src_ptr = __it.__node_->__upcast();
1633 size_t __hash = hash_function()(__src_ptr->__get_value());
1634 __next_pointer __existing_node = __node_insert_unique_prepare(__hash, __src_ptr->__get_value());
1635 auto __prev_iter = __it++;
1636 if (__existing_node == nullptr) {
1637 (void)__source.remove(__prev_iter).release();
1638 __src_ptr->__hash_ = __hash;
1639 __node_insert_unique_perform(__src_ptr);
1640 }
1641 }
1642 }
1643
1644 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1645 template <class _NodeHandle>
1646 _LIBCPP_HIDE_FROM_ABI typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1647 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(_NodeHandle&& __nh) {
1648 if (__nh.empty())
1649 return end();
1650 iterator __result = __node_insert_multi(__nh.__ptr_);
1651 __nh.__release_ptr();
1652 return __result;
1653 }
1654
1655 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1656 template <class _NodeHandle>
1657 _LIBCPP_HIDE_FROM_ABI typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1658 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(const_iterator __hint, _NodeHandle&& __nh) {
1659 if (__nh.empty())
1660 return end();
1661 iterator __result = __node_insert_multi(__hint, __nh.__ptr_);
1662 __nh.__release_ptr();
1663 return __result;
1664 }
1665
1666 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1667 template <class _Table>
1668 _LIBCPP_HIDE_FROM_ABI void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_multi(_Table& __source) {
1669 static_assert(is_same<typename _Table::__node, __node>::value, "");
1670
1671 for (typename _Table::iterator __it = __source.begin(); __it != __source.end();) {
1672 __node_pointer __src_ptr = __it.__node_->__upcast();
1673 size_t __src_hash = hash_function()(__src_ptr->__get_value());
1674 __next_pointer __pn = __node_insert_multi_prepare(__src_hash, __src_ptr->__get_value());
1675 (void)__source.remove(__it++).release();
1676 __src_ptr->__hash_ = __src_hash;
1677 __node_insert_multi_perform(__src_ptr, __pn);
1678 }
1679 }
1680 #endif // _LIBCPP_STD_VER >= 17
1681
1682 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1683 template <bool _UniqueKeys>
1684 void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __n) _LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK {
1685 if (__n == 1)
1686 __n = 2;
1687 else if (__n & (__n - 1))
1688 __n = std::__next_prime(__n);
1689 size_type __bc = bucket_count();
1690 if (__n > __bc)
1691 __do_rehash<_UniqueKeys>(__n);
1692 else if (__n < __bc) {
1693 __n = std::max<size_type>(
1694 __n,
1695 std::__is_hash_power2(__bc) ? std::__next_hash_pow2(size_t(std::ceil(float(size()) / max_load_factor())))
1696 : std::__next_prime(size_t(std::ceil(float(size()) / max_load_factor()))));
1697 if (__n < __bc)
1698 __do_rehash<_UniqueKeys>(__n);
1699 }
1700 }
1701
1702 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1703 template <bool _UniqueKeys>
1704 void __hash_table<_Tp, _Hash, _Equal, _Alloc>::__do_rehash(size_type __nbc) {
1705 __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc();
1706 __bucket_list_.reset(__nbc > 0 ? __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr);
1707 __bucket_list_.get_deleter().size() = __nbc;
1708 if (__nbc > 0) {
1709 for (size_type __i = 0; __i < __nbc; ++__i)
1710 __bucket_list_[__i] = nullptr;
1711 __next_pointer __pp = __p1_.first().__ptr();
1712 __next_pointer __cp = __pp->__next_;
1713 if (__cp != nullptr) {
1714 size_type __chash = std::__constrain_hash(__cp->__hash(), __nbc);
1715 __bucket_list_[__chash] = __pp;
1716 size_type __phash = __chash;
1717 for (__pp = __cp, void(), __cp = __cp->__next_; __cp != nullptr; __cp = __pp->__next_) {
1718 __chash = std::__constrain_hash(__cp->__hash(), __nbc);
1719 if (__chash == __phash)
1720 __pp = __cp;
1721 else {
1722 if (__bucket_list_[__chash] == nullptr) {
1723 __bucket_list_[__chash] = __pp;
1724 __pp = __cp;
1725 __phash = __chash;
1726 } else {
1727 __next_pointer __np = __cp;
1728 if _LIBCPP_CONSTEXPR_SINCE_CXX17 (!_UniqueKeys) {
1729 for (; __np->__next_ != nullptr &&
1730 key_eq()(__cp->__upcast()->__get_value(), __np->__next_->__upcast()->__get_value());
1731 __np = __np->__next_)
1732 ;
1733 }
1734 __pp->__next_ = __np->__next_;
1735 __np->__next_ = __bucket_list_[__chash]->__next_;
1736 __bucket_list_[__chash]->__next_ = __cp;
1737 }
1738 }
1739 }
1740 }
1741 }
1742 }
1743
1744 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1745 template <class _Key>
1746 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1747 __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) {
1748 size_t __hash = hash_function()(__k);
1749 size_type __bc = bucket_count();
1750 if (__bc != 0) {
1751 size_t __chash = std::__constrain_hash(__hash, __bc);
1752 __next_pointer __nd = __bucket_list_[__chash];
1753 if (__nd != nullptr) {
1754 for (__nd = __nd->__next_;
1755 __nd != nullptr && (__nd->__hash() == __hash || std::__constrain_hash(__nd->__hash(), __bc) == __chash);
1756 __nd = __nd->__next_) {
1757 if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__get_value(), __k))
1758 return iterator(__nd);
1759 }
1760 }
1761 }
1762 return end();
1763 }
1764
1765 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1766 template <class _Key>
1767 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1768 __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const {
1769 size_t __hash = hash_function()(__k);
1770 size_type __bc = bucket_count();
1771 if (__bc != 0) {
1772 size_t __chash = std::__constrain_hash(__hash, __bc);
1773 __next_pointer __nd = __bucket_list_[__chash];
1774 if (__nd != nullptr) {
1775 for (__nd = __nd->__next_;
1776 __nd != nullptr && (__hash == __nd->__hash() || std::__constrain_hash(__nd->__hash(), __bc) == __chash);
1777 __nd = __nd->__next_) {
1778 if ((__nd->__hash() == __hash) && key_eq()(__nd->__upcast()->__get_value(), __k))
1779 return const_iterator(__nd);
1780 }
1781 }
1782 }
1783 return end();
1784 }
1785
1786 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1787 template <class... _Args>
1788 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1789 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&&... __args) {
1790 static_assert(!__is_hash_value_type<_Args...>::value, "Construct cannot be called with a hash value type");
1791 __node_allocator& __na = __node_alloc();
1792 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
1793
1794 // Begin the lifetime of the node itself. Note that this doesn't begin the lifetime of the value
1795 // held inside the node, since we need to use the allocator's construct() method for that.
1796 //
1797 // We don't use the allocator's construct() method to construct the node itself since the
1798 // Cpp17FooInsertable named requirements don't require the allocator's construct() method
1799 // to work on anything other than the value_type.
1800 std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ 0);
1801
1802 // Now construct the value_type using the allocator's construct() method.
1803 __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__get_value()), std::forward<_Args>(__args)...);
1804 __h.get_deleter().__value_constructed = true;
1805
1806 __h->__hash_ = hash_function()(__h->__get_value());
1807 return __h;
1808 }
1809
1810 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1811 template <class _First, class... _Rest>
1812 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1813 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest) {
1814 static_assert(!__is_hash_value_type<_First, _Rest...>::value, "Construct cannot be called with a hash value type");
1815 __node_allocator& __na = __node_alloc();
1816 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
1817 std::__construct_at(std::addressof(*__h), /* next = */ nullptr, /* hash = */ __hash);
1818 __node_traits::construct(
1819 __na, _NodeTypes::__get_ptr(__h->__get_value()), std::forward<_First>(__f), std::forward<_Rest>(__rest)...);
1820 __h.get_deleter().__value_constructed = true;
1821 return __h;
1822 }
1823
1824 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1825 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1826 __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p) {
1827 __next_pointer __np = __p.__node_;
1828 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
1829 __p != end(), "unordered container::erase(iterator) called with a non-dereferenceable iterator");
1830 iterator __r(__np);
1831 ++__r;
1832 remove(__p);
1833 return __r;
1834 }
1835
1836 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1837 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1838 __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first, const_iterator __last) {
1839 for (const_iterator __p = __first; __first != __last; __p = __first) {
1840 ++__first;
1841 erase(__p);
1842 }
1843 __next_pointer __np = __last.__node_;
1844 return iterator(__np);
1845 }
1846
1847 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1848 template <class _Key>
1849 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1850 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k) {
1851 iterator __i = find(__k);
1852 if (__i == end())
1853 return 0;
1854 erase(__i);
1855 return 1;
1856 }
1857
1858 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1859 template <class _Key>
1860 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1861 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k) {
1862 size_type __r = 0;
1863 iterator __i = find(__k);
1864 if (__i != end()) {
1865 iterator __e = end();
1866 do {
1867 erase(__i++);
1868 ++__r;
1869 } while (__i != __e && key_eq()(*__i, __k));
1870 }
1871 return __r;
1872 }
1873
1874 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1875 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1876 __hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT {
1877 // current node
1878 __next_pointer __cn = __p.__node_;
1879 size_type __bc = bucket_count();
1880 size_t __chash = std::__constrain_hash(__cn->__hash(), __bc);
1881 // find previous node
1882 __next_pointer __pn = __bucket_list_[__chash];
1883 for (; __pn->__next_ != __cn; __pn = __pn->__next_)
1884 ;
1885 // Fix up __bucket_list_
1886 // if __pn is not in same bucket (before begin is not in same bucket) &&
1887 // if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
1888 if (__pn == __p1_.first().__ptr() || std::__constrain_hash(__pn->__hash(), __bc) != __chash) {
1889 if (__cn->__next_ == nullptr || std::__constrain_hash(__cn->__next_->__hash(), __bc) != __chash)
1890 __bucket_list_[__chash] = nullptr;
1891 }
1892 // if __cn->__next_ is not in same bucket (nullptr is in same bucket)
1893 if (__cn->__next_ != nullptr) {
1894 size_t __nhash = std::__constrain_hash(__cn->__next_->__hash(), __bc);
1895 if (__nhash != __chash)
1896 __bucket_list_[__nhash] = __pn;
1897 }
1898 // remove __cn
1899 __pn->__next_ = __cn->__next_;
1900 __cn->__next_ = nullptr;
1901 --size();
1902 return __node_holder(__cn->__upcast(), _Dp(__node_alloc(), true));
1903 }
1904
1905 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1906 template <class _Key>
1907 inline typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1908 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const {
1909 return static_cast<size_type>(find(__k) != end());
1910 }
1911
1912 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1913 template <class _Key>
1914 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1915 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const {
1916 size_type __r = 0;
1917 const_iterator __i = find(__k);
1918 if (__i != end()) {
1919 const_iterator __e = end();
1920 do {
1921 ++__i;
1922 ++__r;
1923 } while (__i != __e && key_eq()(*__i, __k));
1924 }
1925 return __r;
1926 }
1927
1928 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1929 template <class _Key>
1930 pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
1931 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1932 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(const _Key& __k) {
1933 iterator __i = find(__k);
1934 iterator __j = __i;
1935 if (__i != end())
1936 ++__j;
1937 return pair<iterator, iterator>(__i, __j);
1938 }
1939
1940 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1941 template <class _Key>
1942 pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
1943 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1944 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(const _Key& __k) const {
1945 const_iterator __i = find(__k);
1946 const_iterator __j = __i;
1947 if (__i != end())
1948 ++__j;
1949 return pair<const_iterator, const_iterator>(__i, __j);
1950 }
1951
1952 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1953 template <class _Key>
1954 pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
1955 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1956 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(const _Key& __k) {
1957 iterator __i = find(__k);
1958 iterator __j = __i;
1959 if (__i != end()) {
1960 iterator __e = end();
1961 do {
1962 ++__j;
1963 } while (__j != __e && key_eq()(*__j, __k));
1964 }
1965 return pair<iterator, iterator>(__i, __j);
1966 }
1967
1968 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1969 template <class _Key>
1970 pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
1971 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1972 __hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(const _Key& __k) const {
1973 const_iterator __i = find(__k);
1974 const_iterator __j = __i;
1975 if (__i != end()) {
1976 const_iterator __e = end();
1977 do {
1978 ++__j;
1979 } while (__j != __e && key_eq()(*__j, __k));
1980 }
1981 return pair<const_iterator, const_iterator>(__i, __j);
1982 }
1983
1984 template <class _Tp, class _Hash, class _Equal, class _Alloc>
1985 void __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
1986 #if _LIBCPP_STD_VER <= 11
1987 _NOEXCEPT_(__is_nothrow_swappable_v<hasher>&& __is_nothrow_swappable_v<key_equal> &&
1988 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
1989 __is_nothrow_swappable_v<__pointer_allocator>) &&
1990 (!__node_traits::propagate_on_container_swap::value || __is_nothrow_swappable_v<__node_allocator>))
1991 #else
1992 _NOEXCEPT_(__is_nothrow_swappable_v<hasher>&& __is_nothrow_swappable_v<key_equal>)
1993 #endif
1994 {
1995 _LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR(
1996 __node_traits::propagate_on_container_swap::value || this->__node_alloc() == __u.__node_alloc(),
1997 "unordered container::swap: Either propagate_on_container_swap "
1998 "must be true or the allocators must compare equal");
1999 {
2000 __node_pointer_pointer __npp = __bucket_list_.release();
2001 __bucket_list_.reset(__u.__bucket_list_.release());
2002 __u.__bucket_list_.reset(__npp);
2003 }
2004 std::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
2005 std::__swap_allocator(__bucket_list_.get_deleter().__alloc(), __u.__bucket_list_.get_deleter().__alloc());
2006 std::__swap_allocator(__node_alloc(), __u.__node_alloc());
2007 std::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
2008 __p2_.swap(__u.__p2_);
2009 __p3_.swap(__u.__p3_);
2010 if (size() > 0)
2011 __bucket_list_[std::__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] = __p1_.first().__ptr();
2012 if (__u.size() > 0)
2013 __u.__bucket_list_[std::__constrain_hash(__u.__p1_.first().__next_->__hash(), __u.bucket_count())] =
2014 __u.__p1_.first().__ptr();
2015 }
2016
2017 template <class _Tp, class _Hash, class _Equal, class _Alloc>
2018 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2019 __hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const {
2020 _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(
2021 __n < bucket_count(), "unordered container::bucket_size(n) called with n >= bucket_count()");
2022 __next_pointer __np = __bucket_list_[__n];
2023 size_type __bc = bucket_count();
2024 size_type __r = 0;
2025 if (__np != nullptr) {
2026 for (__np = __np->__next_; __np != nullptr && std::__constrain_hash(__np->__hash(), __bc) == __n;
2027 __np = __np->__next_, (void)++__r)
2028 ;
2029 }
2030 return __r;
2031 }
2032
2033 template <class _Tp, class _Hash, class _Equal, class _Alloc>
2034 inline _LIBCPP_HIDE_FROM_ABI void
2035 swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x, __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y)
2036 _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) {
2037 __x.swap(__y);
2038 }
2039
2040 _LIBCPP_END_NAMESPACE_STD
2041
2042 _LIBCPP_POP_MACROS
2043
2044 #endif // _LIBCPP___CXX03___HASH_TABLE