blob: 1feb4bc3582f69e14df7a1b5890087585e017933 [file] [log] [blame]
Howard Hinnant3e519522010-05-11 19:42:16 +00001// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
Chandler Carruth57b08b02019-01-19 10:56:40 +00004// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Howard Hinnant3e519522010-05-11 19:42:16 +00007//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP__HASH_TABLE
11#define _LIBCPP__HASH_TABLE
12
13#include <__config>
14#include <initializer_list>
15#include <memory>
16#include <iterator>
17#include <algorithm>
18#include <cmath>
Eric Fiselier75d0dcf2016-02-10 20:46:23 +000019#include <utility>
Eric Fiselier04333f92017-01-13 22:42:53 +000020#include <type_traits>
Howard Hinnant3e519522010-05-11 19:42:16 +000021
Eric Fiselierc1bd9192014-08-10 23:53:08 +000022#include <__debug>
Howard Hinnant42a30462013-08-02 00:26:35 +000023
Howard Hinnant073458b2011-10-17 20:05:10 +000024#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnant3e519522010-05-11 19:42:16 +000025#pragma GCC system_header
Howard Hinnant073458b2011-10-17 20:05:10 +000026#endif
Howard Hinnant3e519522010-05-11 19:42:16 +000027
Eric Fiseliera016efb2017-05-31 22:07:49 +000028_LIBCPP_PUSH_MACROS
29#include <__undef_macros>
Howard Hinnant3e519522010-05-11 19:42:16 +000030
Eric Fiselierfcd02212016-02-11 11:59:44 +000031
Eric Fiseliera016efb2017-05-31 22:07:49 +000032_LIBCPP_BEGIN_NAMESPACE_STD
33
Eric Fiselierfcd02212016-02-11 11:59:44 +000034template <class _Key, class _Tp>
35struct __hash_value_type;
Eric Fiselierfcd02212016-02-11 11:59:44 +000036
37#ifndef _LIBCPP_CXX03_LANG
38template <class _Tp>
39struct __is_hash_value_type_imp : false_type {};
40
41template <class _Key, class _Value>
42struct __is_hash_value_type_imp<__hash_value_type<_Key, _Value>> : true_type {};
43
44template <class ..._Args>
45struct __is_hash_value_type : false_type {};
46
47template <class _One>
48struct __is_hash_value_type<_One> : __is_hash_value_type_imp<typename __uncvref<_One>::type> {};
49#endif
50
Howard Hinnant6e412562013-03-06 23:30:19 +000051_LIBCPP_FUNC_VIS
Howard Hinnantce534202011-06-14 19:58:17 +000052size_t __next_prime(size_t __n);
Howard Hinnant3e519522010-05-11 19:42:16 +000053
54template <class _NodePtr>
55struct __hash_node_base
56{
Eric Fiselier40492ba2016-07-23 20:36:55 +000057 typedef typename pointer_traits<_NodePtr>::element_type __node_type;
Howard Hinnant3e519522010-05-11 19:42:16 +000058 typedef __hash_node_base __first_node;
Eric Fiselier40492ba2016-07-23 20:36:55 +000059 typedef typename __rebind_pointer<_NodePtr, __first_node>::type __node_base_pointer;
60 typedef _NodePtr __node_pointer;
Howard Hinnant3e519522010-05-11 19:42:16 +000061
Eric Fiselier40492ba2016-07-23 20:36:55 +000062#if defined(_LIBCPP_ABI_FIX_UNORDERED_NODE_POINTER_UB)
63 typedef __node_base_pointer __next_pointer;
64#else
65 typedef typename conditional<
66 is_pointer<__node_pointer>::value,
67 __node_base_pointer,
68 __node_pointer>::type __next_pointer;
69#endif
70
71 __next_pointer __next_;
72
73 _LIBCPP_INLINE_VISIBILITY
74 __next_pointer __ptr() _NOEXCEPT {
75 return static_cast<__next_pointer>(
76 pointer_traits<__node_base_pointer>::pointer_to(*this));
77 }
78
79 _LIBCPP_INLINE_VISIBILITY
80 __node_pointer __upcast() _NOEXCEPT {
81 return static_cast<__node_pointer>(
82 pointer_traits<__node_base_pointer>::pointer_to(*this));
83 }
84
85 _LIBCPP_INLINE_VISIBILITY
86 size_t __hash() const _NOEXCEPT {
87 return static_cast<__node_type const&>(*this).__hash_;
88 }
Howard Hinnant3e519522010-05-11 19:42:16 +000089
Howard Hinnant37141072011-06-04 18:54:24 +000090 _LIBCPP_INLINE_VISIBILITY __hash_node_base() _NOEXCEPT : __next_(nullptr) {}
Howard Hinnant3e519522010-05-11 19:42:16 +000091};
92
93template <class _Tp, class _VoidPtr>
94struct __hash_node
95 : public __hash_node_base
96 <
Eric Fiselier934b0922015-12-30 21:52:00 +000097 typename __rebind_pointer<_VoidPtr, __hash_node<_Tp, _VoidPtr> >::type
Howard Hinnant3e519522010-05-11 19:42:16 +000098 >
99{
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000100 typedef _Tp __node_value_type;
Howard Hinnant3e519522010-05-11 19:42:16 +0000101
Eric Fiselier40492ba2016-07-23 20:36:55 +0000102 size_t __hash_;
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000103 __node_value_type __value_;
Howard Hinnant3e519522010-05-11 19:42:16 +0000104};
105
Howard Hinnant4cb38a82012-07-06 17:31:14 +0000106inline _LIBCPP_INLINE_VISIBILITY
107bool
Eric Fiselier9ba5c112015-02-02 21:31:48 +0000108__is_hash_power2(size_t __bc)
Howard Hinnant4cb38a82012-07-06 17:31:14 +0000109{
110 return __bc > 2 && !(__bc & (__bc - 1));
111}
112
113inline _LIBCPP_INLINE_VISIBILITY
114size_t
115__constrain_hash(size_t __h, size_t __bc)
116{
Eric Fiselier118cb412016-07-11 22:02:02 +0000117 return !(__bc & (__bc - 1)) ? __h & (__bc - 1) :
118 (__h < __bc ? __h : __h % __bc);
Howard Hinnant4cb38a82012-07-06 17:31:14 +0000119}
120
121inline _LIBCPP_INLINE_VISIBILITY
122size_t
Eric Fiselier9ba5c112015-02-02 21:31:48 +0000123__next_hash_pow2(size_t __n)
Howard Hinnant4cb38a82012-07-06 17:31:14 +0000124{
Marshall Clowf3b851f2019-07-12 01:01:55 +0000125 return __n < 2 ? __n : (size_t(1) << (std::numeric_limits<size_t>::digits - __libcpp_clz(__n-1)));
Howard Hinnant4cb38a82012-07-06 17:31:14 +0000126}
127
Duncan P. N. Exon Smithfde79b42016-03-17 20:45:20 +0000128
Howard Hinnantce534202011-06-14 19:58:17 +0000129template <class _Tp, class _Hash, class _Equal, class _Alloc> class __hash_table;
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000130
Eric Fiseliere2f2d1e2017-01-04 23:56:00 +0000131template <class _NodePtr> class _LIBCPP_TEMPLATE_VIS __hash_iterator;
132template <class _ConstNodePtr> class _LIBCPP_TEMPLATE_VIS __hash_const_iterator;
133template <class _NodePtr> class _LIBCPP_TEMPLATE_VIS __hash_local_iterator;
134template <class _ConstNodePtr> class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator;
135template <class _HashIterator> class _LIBCPP_TEMPLATE_VIS __hash_map_iterator;
136template <class _HashIterator> class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator;
Howard Hinnant3e519522010-05-11 19:42:16 +0000137
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000138template <class _Tp>
Eric Fiselier43b121d2016-02-20 07:59:16 +0000139struct __hash_key_value_types {
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000140 static_assert(!is_reference<_Tp>::value && !is_const<_Tp>::value, "");
141 typedef _Tp key_type;
142 typedef _Tp __node_value_type;
143 typedef _Tp __container_value_type;
144 static const bool __is_map = false;
Eric Fiselierfcd02212016-02-11 11:59:44 +0000145
146 _LIBCPP_INLINE_VISIBILITY
147 static key_type const& __get_key(_Tp const& __v) {
148 return __v;
149 }
150 _LIBCPP_INLINE_VISIBILITY
151 static __container_value_type const& __get_value(__node_value_type const& __v) {
152 return __v;
153 }
154 _LIBCPP_INLINE_VISIBILITY
155 static __container_value_type* __get_ptr(__node_value_type& __n) {
156 return _VSTD::addressof(__n);
157 }
158#ifndef _LIBCPP_CXX03_LANG
159 _LIBCPP_INLINE_VISIBILITY
Erik Pilkingtonf52318b2018-06-04 20:38:23 +0000160 static __container_value_type&& __move(__node_value_type& __v) {
Eric Fiselierfcd02212016-02-11 11:59:44 +0000161 return _VSTD::move(__v);
162 }
163#endif
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000164};
165
166template <class _Key, class _Tp>
Eric Fiselier43b121d2016-02-20 07:59:16 +0000167struct __hash_key_value_types<__hash_value_type<_Key, _Tp> > {
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000168 typedef _Key key_type;
169 typedef _Tp mapped_type;
170 typedef __hash_value_type<_Key, _Tp> __node_value_type;
171 typedef pair<const _Key, _Tp> __container_value_type;
172 typedef __container_value_type __map_value_type;
173 static const bool __is_map = true;
Eric Fiselierfcd02212016-02-11 11:59:44 +0000174
175 _LIBCPP_INLINE_VISIBILITY
176 static key_type const& __get_key(__container_value_type const& __v) {
177 return __v.first;
178 }
179
180 template <class _Up>
181 _LIBCPP_INLINE_VISIBILITY
182 static typename enable_if<__is_same_uncvref<_Up, __node_value_type>::value,
183 __container_value_type const&>::type
184 __get_value(_Up& __t) {
Erik Pilkingtonf52318b2018-06-04 20:38:23 +0000185 return __t.__get_value();
Eric Fiselierfcd02212016-02-11 11:59:44 +0000186 }
187
188 template <class _Up>
189 _LIBCPP_INLINE_VISIBILITY
190 static typename enable_if<__is_same_uncvref<_Up, __container_value_type>::value,
191 __container_value_type const&>::type
192 __get_value(_Up& __t) {
193 return __t;
194 }
195
196 _LIBCPP_INLINE_VISIBILITY
197 static __container_value_type* __get_ptr(__node_value_type& __n) {
Erik Pilkingtonf52318b2018-06-04 20:38:23 +0000198 return _VSTD::addressof(__n.__get_value());
Eric Fiselierfcd02212016-02-11 11:59:44 +0000199 }
200#ifndef _LIBCPP_CXX03_LANG
201 _LIBCPP_INLINE_VISIBILITY
Erik Pilkingtonf52318b2018-06-04 20:38:23 +0000202 static pair<key_type&&, mapped_type&&> __move(__node_value_type& __v) {
203 return __v.__move();
Eric Fiselierfcd02212016-02-11 11:59:44 +0000204 }
205#endif
206
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000207};
208
Eric Fiselier43b121d2016-02-20 07:59:16 +0000209template <class _Tp, class _AllocPtr, class _KVTypes = __hash_key_value_types<_Tp>,
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000210 bool = _KVTypes::__is_map>
Eric Fiselier43b121d2016-02-20 07:59:16 +0000211struct __hash_map_pointer_types {};
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000212
213template <class _Tp, class _AllocPtr, class _KVTypes>
Eric Fiselier43b121d2016-02-20 07:59:16 +0000214struct __hash_map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> {
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000215 typedef typename _KVTypes::__map_value_type _Mv;
216 typedef typename __rebind_pointer<_AllocPtr, _Mv>::type
217 __map_value_type_pointer;
218 typedef typename __rebind_pointer<_AllocPtr, const _Mv>::type
219 __const_map_value_type_pointer;
220};
221
222template <class _NodePtr, class _NodeT = typename pointer_traits<_NodePtr>::element_type>
223struct __hash_node_types;
224
225template <class _NodePtr, class _Tp, class _VoidPtr>
226struct __hash_node_types<_NodePtr, __hash_node<_Tp, _VoidPtr> >
Eric Fiselier43b121d2016-02-20 07:59:16 +0000227 : public __hash_key_value_types<_Tp>, __hash_map_pointer_types<_Tp, _VoidPtr>
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000228
229{
Eric Fiselier43b121d2016-02-20 07:59:16 +0000230 typedef __hash_key_value_types<_Tp> __base;
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000231
232public:
233 typedef ptrdiff_t difference_type;
234 typedef size_t size_type;
235
236 typedef typename __rebind_pointer<_NodePtr, void>::type __void_pointer;
237
238 typedef typename pointer_traits<_NodePtr>::element_type __node_type;
239 typedef _NodePtr __node_pointer;
240
241 typedef __hash_node_base<__node_pointer> __node_base_type;
242 typedef typename __rebind_pointer<_NodePtr, __node_base_type>::type
243 __node_base_pointer;
244
Eric Fiselier40492ba2016-07-23 20:36:55 +0000245 typedef typename __node_base_type::__next_pointer __next_pointer;
246
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000247 typedef _Tp __node_value_type;
248 typedef typename __rebind_pointer<_VoidPtr, __node_value_type>::type
249 __node_value_type_pointer;
250 typedef typename __rebind_pointer<_VoidPtr, const __node_value_type>::type
251 __const_node_value_type_pointer;
Eric Fiselier40492ba2016-07-23 20:36:55 +0000252
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000253private:
254 static_assert(!is_const<__node_type>::value,
255 "_NodePtr should never be a pointer to const");
256 static_assert((is_same<typename pointer_traits<_VoidPtr>::element_type, void>::value),
257 "_VoidPtr does not point to unqualified void type");
258 static_assert((is_same<typename __rebind_pointer<_VoidPtr, __node_type>::type,
259 _NodePtr>::value), "_VoidPtr does not rebind to _NodePtr.");
260};
261
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000262template <class _HashIterator>
263struct __hash_node_types_from_iterator;
264template <class _NodePtr>
265struct __hash_node_types_from_iterator<__hash_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
266template <class _NodePtr>
267struct __hash_node_types_from_iterator<__hash_const_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
268template <class _NodePtr>
269struct __hash_node_types_from_iterator<__hash_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
270template <class _NodePtr>
271struct __hash_node_types_from_iterator<__hash_const_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
272
273
274template <class _NodeValueTp, class _VoidPtr>
275struct __make_hash_node_types {
276 typedef __hash_node<_NodeValueTp, _VoidPtr> _NodeTp;
277 typedef typename __rebind_pointer<_VoidPtr, _NodeTp>::type _NodePtr;
278 typedef __hash_node_types<_NodePtr> type;
279};
280
Howard Hinnant3e519522010-05-11 19:42:16 +0000281template <class _NodePtr>
Eric Fiseliere2f2d1e2017-01-04 23:56:00 +0000282class _LIBCPP_TEMPLATE_VIS __hash_iterator
Howard Hinnant3e519522010-05-11 19:42:16 +0000283{
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000284 typedef __hash_node_types<_NodePtr> _NodeTypes;
Eric Fiselier40492ba2016-07-23 20:36:55 +0000285 typedef _NodePtr __node_pointer;
286 typedef typename _NodeTypes::__next_pointer __next_pointer;
Howard Hinnant3e519522010-05-11 19:42:16 +0000287
Eric Fiselier40492ba2016-07-23 20:36:55 +0000288 __next_pointer __node_;
Howard Hinnant3e519522010-05-11 19:42:16 +0000289
290public:
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000291 typedef forward_iterator_tag iterator_category;
292 typedef typename _NodeTypes::__node_value_type value_type;
293 typedef typename _NodeTypes::difference_type difference_type;
294 typedef value_type& reference;
295 typedef typename _NodeTypes::__node_value_type_pointer pointer;
Howard Hinnant3e519522010-05-11 19:42:16 +0000296
Eric Fiselier40492ba2016-07-23 20:36:55 +0000297 _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT : __node_(nullptr) {
Louis Dionne870827f2020-10-02 15:07:40 -0400298#if _LIBCPP_DEBUG_LEVEL == 2
299 __get_db()->__insert_i(this);
300#endif
Howard Hinnantb24c8022013-07-23 22:01:58 +0000301 }
302
Louis Dionne31e82032020-10-02 15:02:52 -0400303#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnant43d99232010-09-21 17:32:39 +0000304 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantb24c8022013-07-23 22:01:58 +0000305 __hash_iterator(const __hash_iterator& __i)
306 : __node_(__i.__node_)
307 {
308 __get_db()->__iterator_copy(this, &__i);
309 }
310
Howard Hinnant43d99232010-09-21 17:32:39 +0000311 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantb24c8022013-07-23 22:01:58 +0000312 ~__hash_iterator()
313 {
314 __get_db()->__erase_i(this);
315 }
316
317 _LIBCPP_INLINE_VISIBILITY
318 __hash_iterator& operator=(const __hash_iterator& __i)
319 {
320 if (this != &__i)
321 {
322 __get_db()->__iterator_copy(this, &__i);
323 __node_ = __i.__node_;
324 }
325 return *this;
326 }
Louis Dionne31e82032020-10-02 15:02:52 -0400327#endif // _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +0000328
329 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000330 reference operator*() const {
331 _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
332 "Attempted to dereference a non-dereferenceable unordered container iterator");
333 return __node_->__upcast()->__value_;
334 }
Howard Hinnant3e519522010-05-11 19:42:16 +0000335
Howard Hinnant43d99232010-09-21 17:32:39 +0000336 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000337 pointer operator->() const {
338 _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
339 "Attempted to dereference a non-dereferenceable unordered container iterator");
340 return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__value_);
341 }
342
343 _LIBCPP_INLINE_VISIBILITY
344 __hash_iterator& operator++() {
345 _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
Howard Hinnantb24c8022013-07-23 22:01:58 +0000346 "Attempted to increment non-incrementable unordered container iterator");
Howard Hinnant3e519522010-05-11 19:42:16 +0000347 __node_ = __node_->__next_;
348 return *this;
349 }
350
Howard Hinnant43d99232010-09-21 17:32:39 +0000351 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +0000352 __hash_iterator operator++(int)
353 {
354 __hash_iterator __t(*this);
355 ++(*this);
356 return __t;
357 }
358
Howard Hinnant43d99232010-09-21 17:32:39 +0000359 friend _LIBCPP_INLINE_VISIBILITY
360 bool operator==(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnantb24c8022013-07-23 22:01:58 +0000361 {
Howard Hinnantb24c8022013-07-23 22:01:58 +0000362 return __x.__node_ == __y.__node_;
363 }
Howard Hinnant43d99232010-09-21 17:32:39 +0000364 friend _LIBCPP_INLINE_VISIBILITY
365 bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnantb24c8022013-07-23 22:01:58 +0000366 {return !(__x == __y);}
Howard Hinnant3e519522010-05-11 19:42:16 +0000367
368private:
Louis Dionne31e82032020-10-02 15:02:52 -0400369#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +0000370 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000371 __hash_iterator(__next_pointer __node, const void* __c) _NOEXCEPT
Howard Hinnantb24c8022013-07-23 22:01:58 +0000372 : __node_(__node)
373 {
374 __get_db()->__insert_ic(this, __c);
375 }
376#else
Howard Hinnant43d99232010-09-21 17:32:39 +0000377 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000378 __hash_iterator(__next_pointer __node) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000379 : __node_(__node)
380 {}
Howard Hinnantb24c8022013-07-23 22:01:58 +0000381#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000382 template <class, class, class, class> friend class __hash_table;
Eric Fiseliere2f2d1e2017-01-04 23:56:00 +0000383 template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_const_iterator;
384 template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator;
385 template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_map;
386 template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_multimap;
Howard Hinnant3e519522010-05-11 19:42:16 +0000387};
388
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000389template <class _NodePtr>
Eric Fiseliere2f2d1e2017-01-04 23:56:00 +0000390class _LIBCPP_TEMPLATE_VIS __hash_const_iterator
Howard Hinnant3e519522010-05-11 19:42:16 +0000391{
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000392 static_assert(!is_const<typename pointer_traits<_NodePtr>::element_type>::value, "");
393 typedef __hash_node_types<_NodePtr> _NodeTypes;
Eric Fiselier40492ba2016-07-23 20:36:55 +0000394 typedef _NodePtr __node_pointer;
395 typedef typename _NodeTypes::__next_pointer __next_pointer;
Eric Fiselier757373e2016-02-18 00:20:34 +0000396
Eric Fiselier40492ba2016-07-23 20:36:55 +0000397 __next_pointer __node_;
Howard Hinnant3e519522010-05-11 19:42:16 +0000398
399public:
Eric Fiselier757373e2016-02-18 00:20:34 +0000400 typedef __hash_iterator<_NodePtr> __non_const_iterator;
401
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000402 typedef forward_iterator_tag iterator_category;
403 typedef typename _NodeTypes::__node_value_type value_type;
404 typedef typename _NodeTypes::difference_type difference_type;
405 typedef const value_type& reference;
406 typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
407
Howard Hinnant3e519522010-05-11 19:42:16 +0000408
Eric Fiselier40492ba2016-07-23 20:36:55 +0000409 _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT : __node_(nullptr) {
Louis Dionne870827f2020-10-02 15:07:40 -0400410#if _LIBCPP_DEBUG_LEVEL == 2
411 __get_db()->__insert_i(this);
412#endif
Howard Hinnantb24c8022013-07-23 22:01:58 +0000413 }
Eric Fiselier40492ba2016-07-23 20:36:55 +0000414
Louis Dionne3560fbf32018-12-06 21:46:17 +0000415 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant37141072011-06-04 18:54:24 +0000416 __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000417 : __node_(__x.__node_)
Howard Hinnantb24c8022013-07-23 22:01:58 +0000418 {
Louis Dionne870827f2020-10-02 15:07:40 -0400419#if _LIBCPP_DEBUG_LEVEL == 2
420 __get_db()->__iterator_copy(this, &__x);
421#endif
Howard Hinnantb24c8022013-07-23 22:01:58 +0000422 }
423
Louis Dionne31e82032020-10-02 15:02:52 -0400424#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnant43d99232010-09-21 17:32:39 +0000425 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantb24c8022013-07-23 22:01:58 +0000426 __hash_const_iterator(const __hash_const_iterator& __i)
427 : __node_(__i.__node_)
428 {
429 __get_db()->__iterator_copy(this, &__i);
430 }
431
Howard Hinnant43d99232010-09-21 17:32:39 +0000432 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantb24c8022013-07-23 22:01:58 +0000433 ~__hash_const_iterator()
434 {
435 __get_db()->__erase_i(this);
436 }
437
438 _LIBCPP_INLINE_VISIBILITY
439 __hash_const_iterator& operator=(const __hash_const_iterator& __i)
440 {
441 if (this != &__i)
442 {
443 __get_db()->__iterator_copy(this, &__i);
444 __node_ = __i.__node_;
445 }
446 return *this;
447 }
Louis Dionne31e82032020-10-02 15:02:52 -0400448#endif // _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +0000449
450 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000451 reference operator*() const {
452 _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
Howard Hinnantb24c8022013-07-23 22:01:58 +0000453 "Attempted to dereference a non-dereferenceable unordered container const_iterator");
Eric Fiselier40492ba2016-07-23 20:36:55 +0000454 return __node_->__upcast()->__value_;
455 }
Howard Hinnantb24c8022013-07-23 22:01:58 +0000456 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000457 pointer operator->() const {
458 _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
Howard Hinnantb24c8022013-07-23 22:01:58 +0000459 "Attempted to dereference a non-dereferenceable unordered container const_iterator");
Eric Fiselier40492ba2016-07-23 20:36:55 +0000460 return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__value_);
461 }
Howard Hinnant3e519522010-05-11 19:42:16 +0000462
Howard Hinnant43d99232010-09-21 17:32:39 +0000463 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000464 __hash_const_iterator& operator++() {
465 _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
466 "Attempted to increment non-incrementable unordered container const_iterator");
Howard Hinnant3e519522010-05-11 19:42:16 +0000467 __node_ = __node_->__next_;
468 return *this;
469 }
470
Howard Hinnant43d99232010-09-21 17:32:39 +0000471 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +0000472 __hash_const_iterator operator++(int)
473 {
474 __hash_const_iterator __t(*this);
475 ++(*this);
476 return __t;
477 }
478
Howard Hinnant43d99232010-09-21 17:32:39 +0000479 friend _LIBCPP_INLINE_VISIBILITY
480 bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnantb24c8022013-07-23 22:01:58 +0000481 {
Howard Hinnantb24c8022013-07-23 22:01:58 +0000482 return __x.__node_ == __y.__node_;
483 }
Howard Hinnant43d99232010-09-21 17:32:39 +0000484 friend _LIBCPP_INLINE_VISIBILITY
485 bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnantb24c8022013-07-23 22:01:58 +0000486 {return !(__x == __y);}
Howard Hinnant3e519522010-05-11 19:42:16 +0000487
488private:
Louis Dionne31e82032020-10-02 15:02:52 -0400489#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +0000490 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000491 __hash_const_iterator(__next_pointer __node, const void* __c) _NOEXCEPT
Howard Hinnantb24c8022013-07-23 22:01:58 +0000492 : __node_(__node)
493 {
494 __get_db()->__insert_ic(this, __c);
495 }
496#else
Howard Hinnant43d99232010-09-21 17:32:39 +0000497 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000498 __hash_const_iterator(__next_pointer __node) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000499 : __node_(__node)
500 {}
Howard Hinnantb24c8022013-07-23 22:01:58 +0000501#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000502 template <class, class, class, class> friend class __hash_table;
Eric Fiseliere2f2d1e2017-01-04 23:56:00 +0000503 template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator;
504 template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_map;
505 template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_multimap;
Howard Hinnant3e519522010-05-11 19:42:16 +0000506};
507
Howard Hinnant3e519522010-05-11 19:42:16 +0000508template <class _NodePtr>
Eric Fiseliere2f2d1e2017-01-04 23:56:00 +0000509class _LIBCPP_TEMPLATE_VIS __hash_local_iterator
Howard Hinnant3e519522010-05-11 19:42:16 +0000510{
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000511 typedef __hash_node_types<_NodePtr> _NodeTypes;
Eric Fiselier40492ba2016-07-23 20:36:55 +0000512 typedef _NodePtr __node_pointer;
513 typedef typename _NodeTypes::__next_pointer __next_pointer;
Howard Hinnant3e519522010-05-11 19:42:16 +0000514
Eric Fiselier40492ba2016-07-23 20:36:55 +0000515 __next_pointer __node_;
Howard Hinnant3e519522010-05-11 19:42:16 +0000516 size_t __bucket_;
517 size_t __bucket_count_;
518
Howard Hinnant3e519522010-05-11 19:42:16 +0000519public:
520 typedef forward_iterator_tag iterator_category;
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000521 typedef typename _NodeTypes::__node_value_type value_type;
522 typedef typename _NodeTypes::difference_type difference_type;
Howard Hinnant3e519522010-05-11 19:42:16 +0000523 typedef value_type& reference;
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000524 typedef typename _NodeTypes::__node_value_type_pointer pointer;
Howard Hinnant3e519522010-05-11 19:42:16 +0000525
Eric Fiselier40492ba2016-07-23 20:36:55 +0000526 _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT : __node_(nullptr) {
Louis Dionne870827f2020-10-02 15:07:40 -0400527#if _LIBCPP_DEBUG_LEVEL == 2
528 __get_db()->__insert_i(this);
529#endif
Howard Hinnantb24c8022013-07-23 22:01:58 +0000530 }
531
Louis Dionne31e82032020-10-02 15:02:52 -0400532#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnant43d99232010-09-21 17:32:39 +0000533 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantb24c8022013-07-23 22:01:58 +0000534 __hash_local_iterator(const __hash_local_iterator& __i)
535 : __node_(__i.__node_),
536 __bucket_(__i.__bucket_),
537 __bucket_count_(__i.__bucket_count_)
538 {
539 __get_db()->__iterator_copy(this, &__i);
540 }
541
Howard Hinnant43d99232010-09-21 17:32:39 +0000542 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantb24c8022013-07-23 22:01:58 +0000543 ~__hash_local_iterator()
544 {
545 __get_db()->__erase_i(this);
546 }
547
548 _LIBCPP_INLINE_VISIBILITY
549 __hash_local_iterator& operator=(const __hash_local_iterator& __i)
550 {
551 if (this != &__i)
552 {
553 __get_db()->__iterator_copy(this, &__i);
554 __node_ = __i.__node_;
555 __bucket_ = __i.__bucket_;
556 __bucket_count_ = __i.__bucket_count_;
557 }
558 return *this;
559 }
Louis Dionne31e82032020-10-02 15:02:52 -0400560#endif // _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +0000561
562 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000563 reference operator*() const {
564 _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
Howard Hinnantb24c8022013-07-23 22:01:58 +0000565 "Attempted to dereference a non-dereferenceable unordered container local_iterator");
Eric Fiselier40492ba2016-07-23 20:36:55 +0000566 return __node_->__upcast()->__value_;
567 }
Howard Hinnant3e519522010-05-11 19:42:16 +0000568
Howard Hinnant43d99232010-09-21 17:32:39 +0000569 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000570 pointer operator->() const {
571 _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
572 "Attempted to dereference a non-dereferenceable unordered container local_iterator");
573 return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__value_);
574 }
575
576 _LIBCPP_INLINE_VISIBILITY
577 __hash_local_iterator& operator++() {
578 _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
Howard Hinnantb24c8022013-07-23 22:01:58 +0000579 "Attempted to increment non-incrementable unordered container local_iterator");
Howard Hinnant3e519522010-05-11 19:42:16 +0000580 __node_ = __node_->__next_;
Eric Fiselier40492ba2016-07-23 20:36:55 +0000581 if (__node_ != nullptr && __constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_)
Howard Hinnant3e519522010-05-11 19:42:16 +0000582 __node_ = nullptr;
583 return *this;
584 }
585
Howard Hinnant43d99232010-09-21 17:32:39 +0000586 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +0000587 __hash_local_iterator operator++(int)
588 {
589 __hash_local_iterator __t(*this);
590 ++(*this);
591 return __t;
592 }
593
Howard Hinnant43d99232010-09-21 17:32:39 +0000594 friend _LIBCPP_INLINE_VISIBILITY
595 bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnantb24c8022013-07-23 22:01:58 +0000596 {
Howard Hinnantb24c8022013-07-23 22:01:58 +0000597 return __x.__node_ == __y.__node_;
598 }
Howard Hinnant43d99232010-09-21 17:32:39 +0000599 friend _LIBCPP_INLINE_VISIBILITY
600 bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnantb24c8022013-07-23 22:01:58 +0000601 {return !(__x == __y);}
Howard Hinnant3e519522010-05-11 19:42:16 +0000602
603private:
Louis Dionne31e82032020-10-02 15:02:52 -0400604#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +0000605 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000606 __hash_local_iterator(__next_pointer __node, size_t __bucket,
Howard Hinnantb24c8022013-07-23 22:01:58 +0000607 size_t __bucket_count, const void* __c) _NOEXCEPT
608 : __node_(__node),
609 __bucket_(__bucket),
610 __bucket_count_(__bucket_count)
611 {
612 __get_db()->__insert_ic(this, __c);
613 if (__node_ != nullptr)
614 __node_ = __node_->__next_;
615 }
616#else
Howard Hinnant43d99232010-09-21 17:32:39 +0000617 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000618 __hash_local_iterator(__next_pointer __node, size_t __bucket,
Howard Hinnant37141072011-06-04 18:54:24 +0000619 size_t __bucket_count) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000620 : __node_(__node),
621 __bucket_(__bucket),
622 __bucket_count_(__bucket_count)
623 {
624 if (__node_ != nullptr)
625 __node_ = __node_->__next_;
626 }
Howard Hinnantb24c8022013-07-23 22:01:58 +0000627#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000628 template <class, class, class, class> friend class __hash_table;
Eric Fiseliere2f2d1e2017-01-04 23:56:00 +0000629 template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator;
630 template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_map_iterator;
Howard Hinnant3e519522010-05-11 19:42:16 +0000631};
632
633template <class _ConstNodePtr>
Eric Fiseliere2f2d1e2017-01-04 23:56:00 +0000634class _LIBCPP_TEMPLATE_VIS __hash_const_local_iterator
Howard Hinnant3e519522010-05-11 19:42:16 +0000635{
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000636 typedef __hash_node_types<_ConstNodePtr> _NodeTypes;
Eric Fiselier40492ba2016-07-23 20:36:55 +0000637 typedef _ConstNodePtr __node_pointer;
638 typedef typename _NodeTypes::__next_pointer __next_pointer;
Howard Hinnant3e519522010-05-11 19:42:16 +0000639
Eric Fiselier40492ba2016-07-23 20:36:55 +0000640 __next_pointer __node_;
Howard Hinnant3e519522010-05-11 19:42:16 +0000641 size_t __bucket_;
642 size_t __bucket_count_;
643
644 typedef pointer_traits<__node_pointer> __pointer_traits;
645 typedef typename __pointer_traits::element_type __node;
646 typedef typename remove_const<__node>::type __non_const_node;
Eric Fiselier934b0922015-12-30 21:52:00 +0000647 typedef typename __rebind_pointer<__node_pointer, __non_const_node>::type
648 __non_const_node_pointer;
Eric Fiselier757373e2016-02-18 00:20:34 +0000649public:
Howard Hinnant3e519522010-05-11 19:42:16 +0000650 typedef __hash_local_iterator<__non_const_node_pointer>
651 __non_const_iterator;
Eric Fiselier757373e2016-02-18 00:20:34 +0000652
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000653 typedef forward_iterator_tag iterator_category;
654 typedef typename _NodeTypes::__node_value_type value_type;
655 typedef typename _NodeTypes::difference_type difference_type;
656 typedef const value_type& reference;
657 typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
Eric Fiselier934b0922015-12-30 21:52:00 +0000658
Howard Hinnant3e519522010-05-11 19:42:16 +0000659
Eric Fiselier40492ba2016-07-23 20:36:55 +0000660 _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT : __node_(nullptr) {
Louis Dionne870827f2020-10-02 15:07:40 -0400661#if _LIBCPP_DEBUG_LEVEL == 2
662 __get_db()->__insert_i(this);
663#endif
Howard Hinnantb24c8022013-07-23 22:01:58 +0000664 }
665
Howard Hinnant43d99232010-09-21 17:32:39 +0000666 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant37141072011-06-04 18:54:24 +0000667 __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000668 : __node_(__x.__node_),
669 __bucket_(__x.__bucket_),
670 __bucket_count_(__x.__bucket_count_)
Howard Hinnantb24c8022013-07-23 22:01:58 +0000671 {
Louis Dionne870827f2020-10-02 15:07:40 -0400672#if _LIBCPP_DEBUG_LEVEL == 2
673 __get_db()->__iterator_copy(this, &__x);
674#endif
Howard Hinnantb24c8022013-07-23 22:01:58 +0000675 }
676
Louis Dionne31e82032020-10-02 15:02:52 -0400677#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnant43d99232010-09-21 17:32:39 +0000678 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantb24c8022013-07-23 22:01:58 +0000679 __hash_const_local_iterator(const __hash_const_local_iterator& __i)
680 : __node_(__i.__node_),
681 __bucket_(__i.__bucket_),
682 __bucket_count_(__i.__bucket_count_)
683 {
684 __get_db()->__iterator_copy(this, &__i);
685 }
686
Howard Hinnant43d99232010-09-21 17:32:39 +0000687 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantb24c8022013-07-23 22:01:58 +0000688 ~__hash_const_local_iterator()
689 {
690 __get_db()->__erase_i(this);
691 }
692
693 _LIBCPP_INLINE_VISIBILITY
694 __hash_const_local_iterator& operator=(const __hash_const_local_iterator& __i)
695 {
696 if (this != &__i)
697 {
698 __get_db()->__iterator_copy(this, &__i);
699 __node_ = __i.__node_;
700 __bucket_ = __i.__bucket_;
701 __bucket_count_ = __i.__bucket_count_;
702 }
703 return *this;
704 }
Louis Dionne31e82032020-10-02 15:02:52 -0400705#endif // _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +0000706
707 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000708 reference operator*() const {
709 _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
Howard Hinnantb24c8022013-07-23 22:01:58 +0000710 "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
Eric Fiselier40492ba2016-07-23 20:36:55 +0000711 return __node_->__upcast()->__value_;
712 }
Howard Hinnant3e519522010-05-11 19:42:16 +0000713
Howard Hinnant43d99232010-09-21 17:32:39 +0000714 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000715 pointer operator->() const {
716 _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
717 "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
718 return pointer_traits<pointer>::pointer_to(__node_->__upcast()->__value_);
719 }
720
721 _LIBCPP_INLINE_VISIBILITY
722 __hash_const_local_iterator& operator++() {
723 _LIBCPP_DEBUG_ASSERT(__get_const_db()->__dereferenceable(this),
Howard Hinnantb24c8022013-07-23 22:01:58 +0000724 "Attempted to increment non-incrementable unordered container const_local_iterator");
Howard Hinnant3e519522010-05-11 19:42:16 +0000725 __node_ = __node_->__next_;
Eric Fiselier40492ba2016-07-23 20:36:55 +0000726 if (__node_ != nullptr && __constrain_hash(__node_->__hash(), __bucket_count_) != __bucket_)
Howard Hinnant3e519522010-05-11 19:42:16 +0000727 __node_ = nullptr;
728 return *this;
729 }
730
Howard Hinnant43d99232010-09-21 17:32:39 +0000731 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +0000732 __hash_const_local_iterator operator++(int)
733 {
734 __hash_const_local_iterator __t(*this);
735 ++(*this);
736 return __t;
737 }
738
Howard Hinnant43d99232010-09-21 17:32:39 +0000739 friend _LIBCPP_INLINE_VISIBILITY
740 bool operator==(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
Howard Hinnantb24c8022013-07-23 22:01:58 +0000741 {
Howard Hinnantb24c8022013-07-23 22:01:58 +0000742 return __x.__node_ == __y.__node_;
743 }
Howard Hinnant43d99232010-09-21 17:32:39 +0000744 friend _LIBCPP_INLINE_VISIBILITY
745 bool operator!=(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
Howard Hinnantb24c8022013-07-23 22:01:58 +0000746 {return !(__x == __y);}
Howard Hinnant3e519522010-05-11 19:42:16 +0000747
748private:
Louis Dionne31e82032020-10-02 15:02:52 -0400749#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +0000750 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000751 __hash_const_local_iterator(__next_pointer __node, size_t __bucket,
Howard Hinnantb24c8022013-07-23 22:01:58 +0000752 size_t __bucket_count, const void* __c) _NOEXCEPT
753 : __node_(__node),
754 __bucket_(__bucket),
755 __bucket_count_(__bucket_count)
756 {
757 __get_db()->__insert_ic(this, __c);
758 if (__node_ != nullptr)
759 __node_ = __node_->__next_;
760 }
761#else
Howard Hinnant43d99232010-09-21 17:32:39 +0000762 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier40492ba2016-07-23 20:36:55 +0000763 __hash_const_local_iterator(__next_pointer __node, size_t __bucket,
Howard Hinnant37141072011-06-04 18:54:24 +0000764 size_t __bucket_count) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000765 : __node_(__node),
766 __bucket_(__bucket),
767 __bucket_count_(__bucket_count)
768 {
769 if (__node_ != nullptr)
770 __node_ = __node_->__next_;
771 }
Howard Hinnantb24c8022013-07-23 22:01:58 +0000772#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000773 template <class, class, class, class> friend class __hash_table;
Eric Fiseliere2f2d1e2017-01-04 23:56:00 +0000774 template <class> friend class _LIBCPP_TEMPLATE_VIS __hash_map_const_iterator;
Howard Hinnant3e519522010-05-11 19:42:16 +0000775};
776
777template <class _Alloc>
778class __bucket_list_deallocator
779{
780 typedef _Alloc allocator_type;
781 typedef allocator_traits<allocator_type> __alloc_traits;
782 typedef typename __alloc_traits::size_type size_type;
783
784 __compressed_pair<size_type, allocator_type> __data_;
785public:
786 typedef typename __alloc_traits::pointer pointer;
787
Howard Hinnant43d99232010-09-21 17:32:39 +0000788 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +0000789 __bucket_list_deallocator()
Howard Hinnant37141072011-06-04 18:54:24 +0000790 _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
Eric Fiselier549545b2019-12-16 18:23:39 -0500791 : __data_(0, __default_init_tag()) {}
Howard Hinnant43d99232010-09-21 17:32:39 +0000792
793 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +0000794 __bucket_list_deallocator(const allocator_type& __a, size_type __size)
Howard Hinnant37141072011-06-04 18:54:24 +0000795 _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
Howard Hinnant3e519522010-05-11 19:42:16 +0000796 : __data_(__size, __a) {}
797
Eric Fiselierafa7a952017-04-19 01:23:04 +0000798#ifndef _LIBCPP_CXX03_LANG
Howard Hinnant43d99232010-09-21 17:32:39 +0000799 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +0000800 __bucket_list_deallocator(__bucket_list_deallocator&& __x)
Howard Hinnant37141072011-06-04 18:54:24 +0000801 _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
Howard Hinnantce48a112011-06-30 21:18:19 +0000802 : __data_(_VSTD::move(__x.__data_))
Howard Hinnant3e519522010-05-11 19:42:16 +0000803 {
804 __x.size() = 0;
805 }
Eric Fiselierafa7a952017-04-19 01:23:04 +0000806#endif
Howard Hinnant3e519522010-05-11 19:42:16 +0000807
Howard Hinnant37141072011-06-04 18:54:24 +0000808 _LIBCPP_INLINE_VISIBILITY
809 size_type& size() _NOEXCEPT {return __data_.first();}
810 _LIBCPP_INLINE_VISIBILITY
811 size_type size() const _NOEXCEPT {return __data_.first();}
Howard Hinnant3e519522010-05-11 19:42:16 +0000812
Howard Hinnant43d99232010-09-21 17:32:39 +0000813 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant37141072011-06-04 18:54:24 +0000814 allocator_type& __alloc() _NOEXCEPT {return __data_.second();}
815 _LIBCPP_INLINE_VISIBILITY
816 const allocator_type& __alloc() const _NOEXCEPT {return __data_.second();}
817
818 _LIBCPP_INLINE_VISIBILITY
819 void operator()(pointer __p) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000820 {
821 __alloc_traits::deallocate(__alloc(), __p, size());
822 }
823};
824
Howard Hinnantce534202011-06-14 19:58:17 +0000825template <class _Alloc> class __hash_map_node_destructor;
Howard Hinnant3e519522010-05-11 19:42:16 +0000826
827template <class _Alloc>
828class __hash_node_destructor
829{
830 typedef _Alloc allocator_type;
831 typedef allocator_traits<allocator_type> __alloc_traits;
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000832
Howard Hinnant3e519522010-05-11 19:42:16 +0000833public:
834 typedef typename __alloc_traits::pointer pointer;
835private:
Eric Fiselierfcd02212016-02-11 11:59:44 +0000836 typedef __hash_node_types<pointer> _NodeTypes;
Howard Hinnant3e519522010-05-11 19:42:16 +0000837
838 allocator_type& __na_;
839
Howard Hinnant3e519522010-05-11 19:42:16 +0000840public:
841 bool __value_constructed;
842
Eric Fiselierf97936f2019-12-12 20:48:11 -0500843 __hash_node_destructor(__hash_node_destructor const&) = default;
844 __hash_node_destructor& operator=(const __hash_node_destructor&) = delete;
845
846
Howard Hinnant43d99232010-09-21 17:32:39 +0000847 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantf622b582011-07-31 17:04:30 +0000848 explicit __hash_node_destructor(allocator_type& __na,
849 bool __constructed = false) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000850 : __na_(__na),
Howard Hinnantf622b582011-07-31 17:04:30 +0000851 __value_constructed(__constructed)
Howard Hinnant3e519522010-05-11 19:42:16 +0000852 {}
853
Howard Hinnant43d99232010-09-21 17:32:39 +0000854 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant37141072011-06-04 18:54:24 +0000855 void operator()(pointer __p) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +0000856 {
857 if (__value_constructed)
Eric Fiselierfcd02212016-02-11 11:59:44 +0000858 __alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__value_));
Howard Hinnant3e519522010-05-11 19:42:16 +0000859 if (__p)
860 __alloc_traits::deallocate(__na_, __p, 1);
861 }
862
863 template <class> friend class __hash_map_node_destructor;
864};
865
Erik Pilkingtonb0386a52018-08-01 01:33:38 +0000866#if _LIBCPP_STD_VER > 14
867template <class _NodeType, class _Alloc>
868struct __generic_container_node_destructor;
869
870template <class _Tp, class _VoidPtr, class _Alloc>
871struct __generic_container_node_destructor<__hash_node<_Tp, _VoidPtr>, _Alloc>
872 : __hash_node_destructor<_Alloc>
873{
874 using __hash_node_destructor<_Alloc>::__hash_node_destructor;
875};
876#endif
Eric Fiselier04333f92017-01-13 22:42:53 +0000877
Louis Dionne3560fbf32018-12-06 21:46:17 +0000878template <class _Key, class _Hash, class _Equal>
879struct __enforce_unordered_container_requirements {
Eric Fiselier04333f92017-01-13 22:42:53 +0000880#ifndef _LIBCPP_CXX03_LANG
Eric Fiselierbd6a2d82017-03-03 22:35:58 +0000881 static_assert(__check_hash_requirements<_Key, _Hash>::value,
Louis Dionne3560fbf32018-12-06 21:46:17 +0000882 "the specified hash does not meet the Hash requirements");
Eric Fiselieracb21582017-03-01 02:02:28 +0000883 static_assert(is_copy_constructible<_Equal>::value,
Louis Dionne3560fbf32018-12-06 21:46:17 +0000884 "the specified comparator is required to be copy constructible");
885#endif
886 typedef int type;
Eric Fiselier04333f92017-01-13 22:42:53 +0000887};
888
Louis Dionne3560fbf32018-12-06 21:46:17 +0000889template <class _Key, class _Hash, class _Equal>
890#ifndef _LIBCPP_CXX03_LANG
891 _LIBCPP_DIAGNOSE_WARNING(!__invokable<_Equal const&, _Key const&, _Key const&>::value,
Louis Dionne7c142fc2019-04-11 16:14:56 +0000892 "the specified comparator type does not provide a viable const call operator")
Louis Dionne3560fbf32018-12-06 21:46:17 +0000893 _LIBCPP_DIAGNOSE_WARNING(!__invokable<_Hash const&, _Key const&>::value,
Louis Dionne7c142fc2019-04-11 16:14:56 +0000894 "the specified hash functor does not provide a viable const call operator")
Louis Dionne3560fbf32018-12-06 21:46:17 +0000895#endif
896typename __enforce_unordered_container_requirements<_Key, _Hash, _Equal>::type
897__diagnose_unordered_container_requirements(int);
898
899// This dummy overload is used so that the compiler won't emit a spurious
900// "no matching function for call to __diagnose_unordered_xxx" diagnostic
901// when the overload above causes a hard error.
902template <class _Key, class _Hash, class _Equal>
903int __diagnose_unordered_container_requirements(void*);
Eric Fiselier04333f92017-01-13 22:42:53 +0000904
Howard Hinnant3e519522010-05-11 19:42:16 +0000905template <class _Tp, class _Hash, class _Equal, class _Alloc>
906class __hash_table
907{
908public:
909 typedef _Tp value_type;
910 typedef _Hash hasher;
911 typedef _Equal key_equal;
912 typedef _Alloc allocator_type;
913
914private:
915 typedef allocator_traits<allocator_type> __alloc_traits;
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000916 typedef typename
917 __make_hash_node_types<value_type, typename __alloc_traits::void_pointer>::type
918 _NodeTypes;
Howard Hinnant3e519522010-05-11 19:42:16 +0000919public:
Eric Fiselierfcd02212016-02-11 11:59:44 +0000920
921 typedef typename _NodeTypes::__node_value_type __node_value_type;
922 typedef typename _NodeTypes::__container_value_type __container_value_type;
Duncan P. N. Exon Smithfde79b42016-03-17 20:45:20 +0000923 typedef typename _NodeTypes::key_type key_type;
Howard Hinnant3e519522010-05-11 19:42:16 +0000924 typedef value_type& reference;
925 typedef const value_type& const_reference;
926 typedef typename __alloc_traits::pointer pointer;
927 typedef typename __alloc_traits::const_pointer const_pointer;
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000928#ifndef _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
Howard Hinnant3e519522010-05-11 19:42:16 +0000929 typedef typename __alloc_traits::size_type size_type;
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000930#else
931 typedef typename _NodeTypes::size_type size_type;
932#endif
933 typedef typename _NodeTypes::difference_type difference_type;
Howard Hinnant3e519522010-05-11 19:42:16 +0000934public:
935 // Create __node
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000936
937 typedef typename _NodeTypes::__node_type __node;
Marshall Clow1f508012015-04-07 05:21:38 +0000938 typedef typename __rebind_alloc_helper<__alloc_traits, __node>::type __node_allocator;
Howard Hinnant3e519522010-05-11 19:42:16 +0000939 typedef allocator_traits<__node_allocator> __node_traits;
Eric Fiselier8e397682016-02-11 15:22:37 +0000940 typedef typename _NodeTypes::__void_pointer __void_pointer;
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000941 typedef typename _NodeTypes::__node_pointer __node_pointer;
942 typedef typename _NodeTypes::__node_pointer __node_const_pointer;
943 typedef typename _NodeTypes::__node_base_type __first_node;
944 typedef typename _NodeTypes::__node_base_pointer __node_base_pointer;
Eric Fiselier40492ba2016-07-23 20:36:55 +0000945 typedef typename _NodeTypes::__next_pointer __next_pointer;
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000946
947private:
948 // check for sane allocator pointer rebinding semantics. Rebinding the
949 // allocator for a new pointer type should be exactly the same as rebinding
950 // the pointer using 'pointer_traits'.
951 static_assert((is_same<__node_pointer, typename __node_traits::pointer>::value),
952 "Allocator does not rebind pointers in a sane manner.");
953 typedef typename __rebind_alloc_helper<__node_traits, __first_node>::type
954 __node_base_allocator;
955 typedef allocator_traits<__node_base_allocator> __node_base_traits;
956 static_assert((is_same<__node_base_pointer, typename __node_base_traits::pointer>::value),
957 "Allocator does not rebind pointers in a sane manner.");
Howard Hinnant3e519522010-05-11 19:42:16 +0000958
959private:
960
Eric Fiselier40492ba2016-07-23 20:36:55 +0000961 typedef typename __rebind_alloc_helper<__node_traits, __next_pointer>::type __pointer_allocator;
Howard Hinnant3e519522010-05-11 19:42:16 +0000962 typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter;
Eric Fiselier40492ba2016-07-23 20:36:55 +0000963 typedef unique_ptr<__next_pointer[], __bucket_list_deleter> __bucket_list;
Howard Hinnant3e519522010-05-11 19:42:16 +0000964 typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits;
Eric Fiselier40492ba2016-07-23 20:36:55 +0000965 typedef typename __bucket_list_deleter::pointer __node_pointer_pointer;
Howard Hinnant3e519522010-05-11 19:42:16 +0000966
967 // --- Member data begin ---
Eric Fiselier75d0dcf2016-02-10 20:46:23 +0000968 __bucket_list __bucket_list_;
969 __compressed_pair<__first_node, __node_allocator> __p1_;
970 __compressed_pair<size_type, hasher> __p2_;
971 __compressed_pair<float, key_equal> __p3_;
Howard Hinnant3e519522010-05-11 19:42:16 +0000972 // --- Member data end ---
973
Howard Hinnant37141072011-06-04 18:54:24 +0000974 _LIBCPP_INLINE_VISIBILITY
975 size_type& size() _NOEXCEPT {return __p2_.first();}
Howard Hinnant3e519522010-05-11 19:42:16 +0000976public:
Howard Hinnant37141072011-06-04 18:54:24 +0000977 _LIBCPP_INLINE_VISIBILITY
978 size_type size() const _NOEXCEPT {return __p2_.first();}
Howard Hinnant3e519522010-05-11 19:42:16 +0000979
Howard Hinnant37141072011-06-04 18:54:24 +0000980 _LIBCPP_INLINE_VISIBILITY
981 hasher& hash_function() _NOEXCEPT {return __p2_.second();}
982 _LIBCPP_INLINE_VISIBILITY
983 const hasher& hash_function() const _NOEXCEPT {return __p2_.second();}
Howard Hinnant3e519522010-05-11 19:42:16 +0000984
Howard Hinnant37141072011-06-04 18:54:24 +0000985 _LIBCPP_INLINE_VISIBILITY
986 float& max_load_factor() _NOEXCEPT {return __p3_.first();}
987 _LIBCPP_INLINE_VISIBILITY
988 float max_load_factor() const _NOEXCEPT {return __p3_.first();}
Howard Hinnant3e519522010-05-11 19:42:16 +0000989
Howard Hinnant37141072011-06-04 18:54:24 +0000990 _LIBCPP_INLINE_VISIBILITY
991 key_equal& key_eq() _NOEXCEPT {return __p3_.second();}
992 _LIBCPP_INLINE_VISIBILITY
993 const key_equal& key_eq() const _NOEXCEPT {return __p3_.second();}
Howard Hinnant3e519522010-05-11 19:42:16 +0000994
Howard Hinnant37141072011-06-04 18:54:24 +0000995 _LIBCPP_INLINE_VISIBILITY
996 __node_allocator& __node_alloc() _NOEXCEPT {return __p1_.second();}
997 _LIBCPP_INLINE_VISIBILITY
998 const __node_allocator& __node_alloc() const _NOEXCEPT
999 {return __p1_.second();}
Howard Hinnant3e519522010-05-11 19:42:16 +00001000
1001public:
1002 typedef __hash_iterator<__node_pointer> iterator;
Howard Hinnant307f8142013-06-22 15:21:29 +00001003 typedef __hash_const_iterator<__node_pointer> const_iterator;
Howard Hinnant3e519522010-05-11 19:42:16 +00001004 typedef __hash_local_iterator<__node_pointer> local_iterator;
Howard Hinnant307f8142013-06-22 15:21:29 +00001005 typedef __hash_const_local_iterator<__node_pointer> const_local_iterator;
Howard Hinnant3e519522010-05-11 19:42:16 +00001006
Evgeniy Stepanov906c8722015-11-07 01:22:13 +00001007 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant37141072011-06-04 18:54:24 +00001008 __hash_table()
1009 _NOEXCEPT_(
1010 is_nothrow_default_constructible<__bucket_list>::value &&
1011 is_nothrow_default_constructible<__first_node>::value &&
1012 is_nothrow_default_constructible<__node_allocator>::value &&
1013 is_nothrow_default_constructible<hasher>::value &&
1014 is_nothrow_default_constructible<key_equal>::value);
Evgeniy Stepanov906c8722015-11-07 01:22:13 +00001015 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00001016 __hash_table(const hasher& __hf, const key_equal& __eql);
1017 __hash_table(const hasher& __hf, const key_equal& __eql,
1018 const allocator_type& __a);
1019 explicit __hash_table(const allocator_type& __a);
1020 __hash_table(const __hash_table& __u);
1021 __hash_table(const __hash_table& __u, const allocator_type& __a);
Eric Fiselierfcd02212016-02-11 11:59:44 +00001022#ifndef _LIBCPP_CXX03_LANG
Howard Hinnant37141072011-06-04 18:54:24 +00001023 __hash_table(__hash_table&& __u)
1024 _NOEXCEPT_(
1025 is_nothrow_move_constructible<__bucket_list>::value &&
1026 is_nothrow_move_constructible<__first_node>::value &&
1027 is_nothrow_move_constructible<__node_allocator>::value &&
1028 is_nothrow_move_constructible<hasher>::value &&
1029 is_nothrow_move_constructible<key_equal>::value);
Howard Hinnant3e519522010-05-11 19:42:16 +00001030 __hash_table(__hash_table&& __u, const allocator_type& __a);
Eric Fiselierfcd02212016-02-11 11:59:44 +00001031#endif // _LIBCPP_CXX03_LANG
Howard Hinnant3e519522010-05-11 19:42:16 +00001032 ~__hash_table();
1033
1034 __hash_table& operator=(const __hash_table& __u);
Eric Fiselierfcd02212016-02-11 11:59:44 +00001035#ifndef _LIBCPP_CXX03_LANG
Evgeniy Stepanov906c8722015-11-07 01:22:13 +00001036 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant37141072011-06-04 18:54:24 +00001037 __hash_table& operator=(__hash_table&& __u)
1038 _NOEXCEPT_(
1039 __node_traits::propagate_on_container_move_assignment::value &&
1040 is_nothrow_move_assignable<__node_allocator>::value &&
1041 is_nothrow_move_assignable<hasher>::value &&
1042 is_nothrow_move_assignable<key_equal>::value);
Howard Hinnant3e519522010-05-11 19:42:16 +00001043#endif
1044 template <class _InputIterator>
1045 void __assign_unique(_InputIterator __first, _InputIterator __last);
1046 template <class _InputIterator>
1047 void __assign_multi(_InputIterator __first, _InputIterator __last);
1048
Howard Hinnant43d99232010-09-21 17:32:39 +00001049 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant37141072011-06-04 18:54:24 +00001050 size_type max_size() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +00001051 {
Eric Fiselier55b31b4e2016-11-23 01:18:56 +00001052 return std::min<size_type>(
Eric Fiselier341c9dd2016-11-23 09:16:12 +00001053 __node_traits::max_size(__node_alloc()),
Eric Fiselier55b31b4e2016-11-23 01:18:56 +00001054 numeric_limits<difference_type >::max()
1055 );
Howard Hinnant3e519522010-05-11 19:42:16 +00001056 }
1057
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001058private:
1059 _LIBCPP_INLINE_VISIBILITY
1060 __next_pointer __node_insert_multi_prepare(size_t __cp_hash,
1061 value_type& __cp_val);
1062 _LIBCPP_INLINE_VISIBILITY
1063 void __node_insert_multi_perform(__node_pointer __cp,
1064 __next_pointer __pn) _NOEXCEPT;
1065
1066 _LIBCPP_INLINE_VISIBILITY
1067 __next_pointer __node_insert_unique_prepare(size_t __nd_hash,
1068 value_type& __nd_val);
1069 _LIBCPP_INLINE_VISIBILITY
1070 void __node_insert_unique_perform(__node_pointer __ptr) _NOEXCEPT;
1071
1072public:
1073 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00001074 pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001075 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00001076 iterator __node_insert_multi(__node_pointer __nd);
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001077 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00001078 iterator __node_insert_multi(const_iterator __p,
1079 __node_pointer __nd);
1080
Eric Fiselierfcd02212016-02-11 11:59:44 +00001081#ifndef _LIBCPP_CXX03_LANG
1082 template <class _Key, class ..._Args>
Duncan P. N. Exon Smithfde79b42016-03-17 20:45:20 +00001083 _LIBCPP_INLINE_VISIBILITY
Eric Fiselierfcd02212016-02-11 11:59:44 +00001084 pair<iterator, bool> __emplace_unique_key_args(_Key const& __k, _Args&&... __args);
Howard Hinnant3e519522010-05-11 19:42:16 +00001085
Eric Fiselierfcd02212016-02-11 11:59:44 +00001086 template <class... _Args>
Duncan P. N. Exon Smithfde79b42016-03-17 20:45:20 +00001087 _LIBCPP_INLINE_VISIBILITY
1088 pair<iterator, bool> __emplace_unique_impl(_Args&&... __args);
1089
1090 template <class _Pp>
1091 _LIBCPP_INLINE_VISIBILITY
1092 pair<iterator, bool> __emplace_unique(_Pp&& __x) {
1093 return __emplace_unique_extract_key(_VSTD::forward<_Pp>(__x),
1094 __can_extract_key<_Pp, key_type>());
1095 }
Eric Fiselier50088682016-04-16 00:23:12 +00001096
1097 template <class _First, class _Second>
1098 _LIBCPP_INLINE_VISIBILITY
1099 typename enable_if<
1100 __can_extract_map_key<_First, key_type, __container_value_type>::value,
1101 pair<iterator, bool>
1102 >::type __emplace_unique(_First&& __f, _Second&& __s) {
1103 return __emplace_unique_key_args(__f, _VSTD::forward<_First>(__f),
1104 _VSTD::forward<_Second>(__s));
1105 }
1106
Eric Fiselierfcd02212016-02-11 11:59:44 +00001107 template <class... _Args>
Duncan P. N. Exon Smithfde79b42016-03-17 20:45:20 +00001108 _LIBCPP_INLINE_VISIBILITY
1109 pair<iterator, bool> __emplace_unique(_Args&&... __args) {
1110 return __emplace_unique_impl(_VSTD::forward<_Args>(__args)...);
1111 }
1112
1113 template <class _Pp>
1114 _LIBCPP_INLINE_VISIBILITY
1115 pair<iterator, bool>
1116 __emplace_unique_extract_key(_Pp&& __x, __extract_key_fail_tag) {
1117 return __emplace_unique_impl(_VSTD::forward<_Pp>(__x));
1118 }
1119 template <class _Pp>
1120 _LIBCPP_INLINE_VISIBILITY
1121 pair<iterator, bool>
1122 __emplace_unique_extract_key(_Pp&& __x, __extract_key_self_tag) {
1123 return __emplace_unique_key_args(__x, _VSTD::forward<_Pp>(__x));
1124 }
1125 template <class _Pp>
1126 _LIBCPP_INLINE_VISIBILITY
1127 pair<iterator, bool>
1128 __emplace_unique_extract_key(_Pp&& __x, __extract_key_first_tag) {
1129 return __emplace_unique_key_args(__x.first, _VSTD::forward<_Pp>(__x));
1130 }
1131
1132 template <class... _Args>
1133 _LIBCPP_INLINE_VISIBILITY
Eric Fiselierfcd02212016-02-11 11:59:44 +00001134 iterator __emplace_multi(_Args&&... __args);
1135 template <class... _Args>
Duncan P. N. Exon Smithfde79b42016-03-17 20:45:20 +00001136 _LIBCPP_INLINE_VISIBILITY
Eric Fiselierfcd02212016-02-11 11:59:44 +00001137 iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args);
1138
1139
Eric Fiselierde3f2b32015-06-13 07:18:32 +00001140 _LIBCPP_INLINE_VISIBILITY
Eric Fiselierfcd02212016-02-11 11:59:44 +00001141 pair<iterator, bool>
1142 __insert_unique(__container_value_type&& __x) {
1143 return __emplace_unique_key_args(_NodeTypes::__get_key(__x), _VSTD::move(__x));
1144 }
1145
1146 template <class _Pp, class = typename enable_if<
1147 !__is_same_uncvref<_Pp, __container_value_type>::value
1148 >::type>
Eric Fiselierde3f2b32015-06-13 07:18:32 +00001149 _LIBCPP_INLINE_VISIBILITY
Eric Fiselierfcd02212016-02-11 11:59:44 +00001150 pair<iterator, bool> __insert_unique(_Pp&& __x) {
1151 return __emplace_unique(_VSTD::forward<_Pp>(__x));
1152 }
1153
1154 template <class _Pp>
1155 _LIBCPP_INLINE_VISIBILITY
1156 iterator __insert_multi(_Pp&& __x) {
1157 return __emplace_multi(_VSTD::forward<_Pp>(__x));
1158 }
1159
1160 template <class _Pp>
1161 _LIBCPP_INLINE_VISIBILITY
1162 iterator __insert_multi(const_iterator __p, _Pp&& __x) {
1163 return __emplace_hint_multi(__p, _VSTD::forward<_Pp>(__x));
1164 }
1165
1166#else // !defined(_LIBCPP_CXX03_LANG)
1167 template <class _Key, class _Args>
Eric Fiselier4271d012016-09-25 04:05:46 +00001168 _LIBCPP_INLINE_VISIBILITY
Eric Fiselierfcd02212016-02-11 11:59:44 +00001169 pair<iterator, bool> __emplace_unique_key_args(_Key const&, _Args& __args);
1170
1171 iterator __insert_multi(const __container_value_type& __x);
1172 iterator __insert_multi(const_iterator __p, const __container_value_type& __x);
Eric Fiselierde3f2b32015-06-13 07:18:32 +00001173#endif
1174
Eric Fiselierfcd02212016-02-11 11:59:44 +00001175 _LIBCPP_INLINE_VISIBILITY
1176 pair<iterator, bool> __insert_unique(const __container_value_type& __x) {
1177 return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x);
1178 }
Howard Hinnant3e519522010-05-11 19:42:16 +00001179
Erik Pilkingtonb0386a52018-08-01 01:33:38 +00001180#if _LIBCPP_STD_VER > 14
1181 template <class _NodeHandle, class _InsertReturnType>
1182 _LIBCPP_INLINE_VISIBILITY
1183 _InsertReturnType __node_handle_insert_unique(_NodeHandle&& __nh);
1184 template <class _NodeHandle>
1185 _LIBCPP_INLINE_VISIBILITY
1186 iterator __node_handle_insert_unique(const_iterator __hint,
1187 _NodeHandle&& __nh);
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001188 template <class _Table>
1189 _LIBCPP_INLINE_VISIBILITY
1190 void __node_handle_merge_unique(_Table& __source);
Erik Pilkingtonb0386a52018-08-01 01:33:38 +00001191
1192 template <class _NodeHandle>
1193 _LIBCPP_INLINE_VISIBILITY
1194 iterator __node_handle_insert_multi(_NodeHandle&& __nh);
1195 template <class _NodeHandle>
1196 _LIBCPP_INLINE_VISIBILITY
1197 iterator __node_handle_insert_multi(const_iterator __hint, _NodeHandle&& __nh);
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001198 template <class _Table>
1199 _LIBCPP_INLINE_VISIBILITY
1200 void __node_handle_merge_multi(_Table& __source);
Erik Pilkingtonb0386a52018-08-01 01:33:38 +00001201
1202 template <class _NodeHandle>
1203 _LIBCPP_INLINE_VISIBILITY
1204 _NodeHandle __node_handle_extract(key_type const& __key);
1205 template <class _NodeHandle>
1206 _LIBCPP_INLINE_VISIBILITY
1207 _NodeHandle __node_handle_extract(const_iterator __it);
1208#endif
1209
Howard Hinnant37141072011-06-04 18:54:24 +00001210 void clear() _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +00001211 void rehash(size_type __n);
Howard Hinnant43d99232010-09-21 17:32:39 +00001212 _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n)
Howard Hinnant3e519522010-05-11 19:42:16 +00001213 {rehash(static_cast<size_type>(ceil(__n / max_load_factor())));}
Howard Hinnant43d99232010-09-21 17:32:39 +00001214
1215 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant37141072011-06-04 18:54:24 +00001216 size_type bucket_count() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +00001217 {
1218 return __bucket_list_.get_deleter().size();
1219 }
1220
Evgeniy Stepanov906c8722015-11-07 01:22:13 +00001221 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant37141072011-06-04 18:54:24 +00001222 iterator begin() _NOEXCEPT;
Evgeniy Stepanov906c8722015-11-07 01:22:13 +00001223 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant37141072011-06-04 18:54:24 +00001224 iterator end() _NOEXCEPT;
Evgeniy Stepanov906c8722015-11-07 01:22:13 +00001225 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant37141072011-06-04 18:54:24 +00001226 const_iterator begin() const _NOEXCEPT;
Evgeniy Stepanov906c8722015-11-07 01:22:13 +00001227 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant37141072011-06-04 18:54:24 +00001228 const_iterator end() const _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +00001229
1230 template <class _Key>
Howard Hinnant43d99232010-09-21 17:32:39 +00001231 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00001232 size_type bucket(const _Key& __k) const
Howard Hinnante5c13de2013-07-29 19:05:47 +00001233 {
1234 _LIBCPP_ASSERT(bucket_count() > 0,
1235 "unordered container::bucket(key) called when bucket_count() == 0");
1236 return __constrain_hash(hash_function()(__k), bucket_count());
1237 }
Howard Hinnant3e519522010-05-11 19:42:16 +00001238
1239 template <class _Key>
1240 iterator find(const _Key& __x);
1241 template <class _Key>
1242 const_iterator find(const _Key& __x) const;
1243
Howard Hinnantc003db12011-11-29 18:15:50 +00001244 typedef __hash_node_destructor<__node_allocator> _Dp;
1245 typedef unique_ptr<__node, _Dp> __node_holder;
Howard Hinnant3e519522010-05-11 19:42:16 +00001246
1247 iterator erase(const_iterator __p);
1248 iterator erase(const_iterator __first, const_iterator __last);
1249 template <class _Key>
1250 size_type __erase_unique(const _Key& __k);
1251 template <class _Key>
1252 size_type __erase_multi(const _Key& __k);
Howard Hinnant37141072011-06-04 18:54:24 +00001253 __node_holder remove(const_iterator __p) _NOEXCEPT;
Howard Hinnant3e519522010-05-11 19:42:16 +00001254
1255 template <class _Key>
Evgeniy Stepanov906c8722015-11-07 01:22:13 +00001256 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00001257 size_type __count_unique(const _Key& __k) const;
1258 template <class _Key>
1259 size_type __count_multi(const _Key& __k) const;
1260
1261 template <class _Key>
1262 pair<iterator, iterator>
1263 __equal_range_unique(const _Key& __k);
1264 template <class _Key>
1265 pair<const_iterator, const_iterator>
1266 __equal_range_unique(const _Key& __k) const;
1267
1268 template <class _Key>
1269 pair<iterator, iterator>
1270 __equal_range_multi(const _Key& __k);
1271 template <class _Key>
1272 pair<const_iterator, const_iterator>
1273 __equal_range_multi(const _Key& __k) const;
1274
Howard Hinnant37141072011-06-04 18:54:24 +00001275 void swap(__hash_table& __u)
Eric Fiselier87a82492015-07-18 20:40:46 +00001276#if _LIBCPP_STD_VER <= 11
Eric Fiselier61b302f2019-03-18 21:50:12 +00001277 _NOEXCEPT_(
Marshall Clowe3fbe142015-07-13 20:04:56 +00001278 __is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value
Marshall Clowe3fbe142015-07-13 20:04:56 +00001279 && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value
1280 || __is_nothrow_swappable<__pointer_allocator>::value)
1281 && (!__node_traits::propagate_on_container_swap::value
1282 || __is_nothrow_swappable<__node_allocator>::value)
Marshall Clowe3fbe142015-07-13 20:04:56 +00001283 );
Eric Fiselier87a82492015-07-18 20:40:46 +00001284#else
Eric Fiselier61b302f2019-03-18 21:50:12 +00001285 _NOEXCEPT_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value);
Eric Fiselier87a82492015-07-18 20:40:46 +00001286#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001287
Howard Hinnant43d99232010-09-21 17:32:39 +00001288 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant37141072011-06-04 18:54:24 +00001289 size_type max_bucket_count() const _NOEXCEPT
Eric Fiselier55b31b4e2016-11-23 01:18:56 +00001290 {return max_size(); }
Howard Hinnant3e519522010-05-11 19:42:16 +00001291 size_type bucket_size(size_type __n) const;
Howard Hinnant37141072011-06-04 18:54:24 +00001292 _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +00001293 {
1294 size_type __bc = bucket_count();
1295 return __bc != 0 ? (float)size() / __bc : 0.f;
1296 }
Howard Hinnant37141072011-06-04 18:54:24 +00001297 _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT
Howard Hinnante5c13de2013-07-29 19:05:47 +00001298 {
1299 _LIBCPP_ASSERT(__mlf > 0,
1300 "unordered container::max_load_factor(lf) called with lf <= 0");
1301 max_load_factor() = _VSTD::max(__mlf, load_factor());
1302 }
Howard Hinnant3e519522010-05-11 19:42:16 +00001303
Howard Hinnantb24c8022013-07-23 22:01:58 +00001304 _LIBCPP_INLINE_VISIBILITY
1305 local_iterator
1306 begin(size_type __n)
1307 {
Howard Hinnante5c13de2013-07-29 19:05:47 +00001308 _LIBCPP_ASSERT(__n < bucket_count(),
1309 "unordered container::begin(n) called with n >= bucket_count()");
Louis Dionne31e82032020-10-02 15:02:52 -04001310#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00001311 return local_iterator(__bucket_list_[__n], __n, bucket_count(), this);
1312#else
1313 return local_iterator(__bucket_list_[__n], __n, bucket_count());
1314#endif
1315 }
1316
1317 _LIBCPP_INLINE_VISIBILITY
1318 local_iterator
1319 end(size_type __n)
1320 {
Howard Hinnante5c13de2013-07-29 19:05:47 +00001321 _LIBCPP_ASSERT(__n < bucket_count(),
1322 "unordered container::end(n) called with n >= bucket_count()");
Louis Dionne31e82032020-10-02 15:02:52 -04001323#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00001324 return local_iterator(nullptr, __n, bucket_count(), this);
1325#else
1326 return local_iterator(nullptr, __n, bucket_count());
1327#endif
1328 }
1329
1330 _LIBCPP_INLINE_VISIBILITY
1331 const_local_iterator
1332 cbegin(size_type __n) const
1333 {
Howard Hinnante5c13de2013-07-29 19:05:47 +00001334 _LIBCPP_ASSERT(__n < bucket_count(),
1335 "unordered container::cbegin(n) called with n >= bucket_count()");
Louis Dionne31e82032020-10-02 15:02:52 -04001336#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00001337 return const_local_iterator(__bucket_list_[__n], __n, bucket_count(), this);
1338#else
1339 return const_local_iterator(__bucket_list_[__n], __n, bucket_count());
1340#endif
1341 }
1342
1343 _LIBCPP_INLINE_VISIBILITY
1344 const_local_iterator
1345 cend(size_type __n) const
1346 {
Howard Hinnante5c13de2013-07-29 19:05:47 +00001347 _LIBCPP_ASSERT(__n < bucket_count(),
1348 "unordered container::cend(n) called with n >= bucket_count()");
Louis Dionne31e82032020-10-02 15:02:52 -04001349#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00001350 return const_local_iterator(nullptr, __n, bucket_count(), this);
1351#else
1352 return const_local_iterator(nullptr, __n, bucket_count());
1353#endif
1354 }
1355
Louis Dionne31e82032020-10-02 15:02:52 -04001356#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00001357
1358 bool __dereferenceable(const const_iterator* __i) const;
1359 bool __decrementable(const const_iterator* __i) const;
1360 bool __addable(const const_iterator* __i, ptrdiff_t __n) const;
1361 bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const;
1362
Louis Dionne31e82032020-10-02 15:02:52 -04001363#endif // _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00001364
Howard Hinnant3e519522010-05-11 19:42:16 +00001365private:
1366 void __rehash(size_type __n);
1367
Eric Fiselierfcd02212016-02-11 11:59:44 +00001368#ifndef _LIBCPP_CXX03_LANG
Howard Hinnant3e519522010-05-11 19:42:16 +00001369 template <class ..._Args>
Eric Fiselierfcd02212016-02-11 11:59:44 +00001370 __node_holder __construct_node(_Args&& ...__args);
1371
1372 template <class _First, class ..._Rest>
1373 __node_holder __construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest);
1374#else // _LIBCPP_CXX03_LANG
1375 __node_holder __construct_node(const __container_value_type& __v);
1376 __node_holder __construct_node_hash(size_t __hash, const __container_value_type& __v);
Howard Hinnant3e519522010-05-11 19:42:16 +00001377#endif
Eric Fiselierfcd02212016-02-11 11:59:44 +00001378
Howard Hinnant3e519522010-05-11 19:42:16 +00001379
Howard Hinnant43d99232010-09-21 17:32:39 +00001380 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00001381 void __copy_assign_alloc(const __hash_table& __u)
1382 {__copy_assign_alloc(__u, integral_constant<bool,
1383 __node_traits::propagate_on_container_copy_assignment::value>());}
1384 void __copy_assign_alloc(const __hash_table& __u, true_type);
Howard Hinnant43d99232010-09-21 17:32:39 +00001385 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantc2063662011-12-01 20:21:04 +00001386 void __copy_assign_alloc(const __hash_table&, false_type) {}
Howard Hinnant3e519522010-05-11 19:42:16 +00001387
Eric Fiselierfcd02212016-02-11 11:59:44 +00001388#ifndef _LIBCPP_CXX03_LANG
Howard Hinnant3e519522010-05-11 19:42:16 +00001389 void __move_assign(__hash_table& __u, false_type);
Howard Hinnant37141072011-06-04 18:54:24 +00001390 void __move_assign(__hash_table& __u, true_type)
1391 _NOEXCEPT_(
1392 is_nothrow_move_assignable<__node_allocator>::value &&
1393 is_nothrow_move_assignable<hasher>::value &&
1394 is_nothrow_move_assignable<key_equal>::value);
1395 _LIBCPP_INLINE_VISIBILITY
1396 void __move_assign_alloc(__hash_table& __u)
1397 _NOEXCEPT_(
1398 !__node_traits::propagate_on_container_move_assignment::value ||
1399 (is_nothrow_move_assignable<__pointer_allocator>::value &&
1400 is_nothrow_move_assignable<__node_allocator>::value))
Howard Hinnant3e519522010-05-11 19:42:16 +00001401 {__move_assign_alloc(__u, integral_constant<bool,
1402 __node_traits::propagate_on_container_move_assignment::value>());}
Howard Hinnant43d99232010-09-21 17:32:39 +00001403 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant3e519522010-05-11 19:42:16 +00001404 void __move_assign_alloc(__hash_table& __u, true_type)
Howard Hinnant37141072011-06-04 18:54:24 +00001405 _NOEXCEPT_(
1406 is_nothrow_move_assignable<__pointer_allocator>::value &&
1407 is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnant3e519522010-05-11 19:42:16 +00001408 {
1409 __bucket_list_.get_deleter().__alloc() =
Howard Hinnantce48a112011-06-30 21:18:19 +00001410 _VSTD::move(__u.__bucket_list_.get_deleter().__alloc());
1411 __node_alloc() = _VSTD::move(__u.__node_alloc());
Howard Hinnant3e519522010-05-11 19:42:16 +00001412 }
Howard Hinnant43d99232010-09-21 17:32:39 +00001413 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant37141072011-06-04 18:54:24 +00001414 void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {}
Eric Fiselierfcd02212016-02-11 11:59:44 +00001415#endif // _LIBCPP_CXX03_LANG
Howard Hinnant3e519522010-05-11 19:42:16 +00001416
Eric Fiseliercd71f442017-01-07 03:01:24 +00001417 void __deallocate_node(__next_pointer __np) _NOEXCEPT;
Eric Fiselier40492ba2016-07-23 20:36:55 +00001418 __next_pointer __detach() _NOEXCEPT;
Howard Hinnant307f8142013-06-22 15:21:29 +00001419
Eric Fiseliere2f2d1e2017-01-04 23:56:00 +00001420 template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_map;
1421 template <class, class, class, class, class> friend class _LIBCPP_TEMPLATE_VIS unordered_multimap;
Howard Hinnant3e519522010-05-11 19:42:16 +00001422};
1423
1424template <class _Tp, class _Hash, class _Equal, class _Alloc>
Evgeniy Stepanov906c8722015-11-07 01:22:13 +00001425inline
Howard Hinnant3e519522010-05-11 19:42:16 +00001426__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table()
Howard Hinnant37141072011-06-04 18:54:24 +00001427 _NOEXCEPT_(
1428 is_nothrow_default_constructible<__bucket_list>::value &&
1429 is_nothrow_default_constructible<__first_node>::value &&
Eric Fiseliere2e332a2015-12-16 00:53:04 +00001430 is_nothrow_default_constructible<__node_allocator>::value &&
Howard Hinnant37141072011-06-04 18:54:24 +00001431 is_nothrow_default_constructible<hasher>::value &&
1432 is_nothrow_default_constructible<key_equal>::value)
Eric Fiselier549545b2019-12-16 18:23:39 -05001433 : __p2_(0, __default_init_tag()),
1434 __p3_(1.0f, __default_init_tag())
Howard Hinnant3e519522010-05-11 19:42:16 +00001435{
1436}
1437
1438template <class _Tp, class _Hash, class _Equal, class _Alloc>
Evgeniy Stepanov906c8722015-11-07 01:22:13 +00001439inline
Howard Hinnant3e519522010-05-11 19:42:16 +00001440__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
1441 const key_equal& __eql)
1442 : __bucket_list_(nullptr, __bucket_list_deleter()),
1443 __p1_(),
1444 __p2_(0, __hf),
1445 __p3_(1.0f, __eql)
1446{
1447}
1448
1449template <class _Tp, class _Hash, class _Equal, class _Alloc>
1450__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
1451 const key_equal& __eql,
1452 const allocator_type& __a)
1453 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
Eric Fiselier549545b2019-12-16 18:23:39 -05001454 __p1_(__default_init_tag(), __node_allocator(__a)),
Howard Hinnant3e519522010-05-11 19:42:16 +00001455 __p2_(0, __hf),
1456 __p3_(1.0f, __eql)
1457{
1458}
1459
1460template <class _Tp, class _Hash, class _Equal, class _Alloc>
1461__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
1462 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
Eric Fiselier549545b2019-12-16 18:23:39 -05001463 __p1_(__default_init_tag(), __node_allocator(__a)),
1464 __p2_(0, __default_init_tag()),
1465 __p3_(1.0f, __default_init_tag())
Howard Hinnant3e519522010-05-11 19:42:16 +00001466{
1467}
1468
1469template <class _Tp, class _Hash, class _Equal, class _Alloc>
1470__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
1471 : __bucket_list_(nullptr,
1472 __bucket_list_deleter(allocator_traits<__pointer_allocator>::
1473 select_on_container_copy_construction(
1474 __u.__bucket_list_.get_deleter().__alloc()), 0)),
Eric Fiselier549545b2019-12-16 18:23:39 -05001475 __p1_(__default_init_tag(), allocator_traits<__node_allocator>::
Howard Hinnant3e519522010-05-11 19:42:16 +00001476 select_on_container_copy_construction(__u.__node_alloc())),
1477 __p2_(0, __u.hash_function()),
1478 __p3_(__u.__p3_)
1479{
1480}
1481
1482template <class _Tp, class _Hash, class _Equal, class _Alloc>
1483__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u,
1484 const allocator_type& __a)
1485 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
Eric Fiselier549545b2019-12-16 18:23:39 -05001486 __p1_(__default_init_tag(), __node_allocator(__a)),
Howard Hinnant3e519522010-05-11 19:42:16 +00001487 __p2_(0, __u.hash_function()),
1488 __p3_(__u.__p3_)
1489{
1490}
1491
Eric Fiselierfcd02212016-02-11 11:59:44 +00001492#ifndef _LIBCPP_CXX03_LANG
Howard Hinnant3e519522010-05-11 19:42:16 +00001493
1494template <class _Tp, class _Hash, class _Equal, class _Alloc>
1495__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u)
Howard Hinnant37141072011-06-04 18:54:24 +00001496 _NOEXCEPT_(
1497 is_nothrow_move_constructible<__bucket_list>::value &&
1498 is_nothrow_move_constructible<__first_node>::value &&
Eric Fiseliere2e332a2015-12-16 00:53:04 +00001499 is_nothrow_move_constructible<__node_allocator>::value &&
Howard Hinnant37141072011-06-04 18:54:24 +00001500 is_nothrow_move_constructible<hasher>::value &&
1501 is_nothrow_move_constructible<key_equal>::value)
Howard Hinnantce48a112011-06-30 21:18:19 +00001502 : __bucket_list_(_VSTD::move(__u.__bucket_list_)),
1503 __p1_(_VSTD::move(__u.__p1_)),
1504 __p2_(_VSTD::move(__u.__p2_)),
1505 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnant3e519522010-05-11 19:42:16 +00001506{
1507 if (size() > 0)
1508 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00001509 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] =
1510 __p1_.first().__ptr();
Howard Hinnant3e519522010-05-11 19:42:16 +00001511 __u.__p1_.first().__next_ = nullptr;
1512 __u.size() = 0;
1513 }
1514}
1515
1516template <class _Tp, class _Hash, class _Equal, class _Alloc>
1517__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u,
1518 const allocator_type& __a)
1519 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
Eric Fiselier549545b2019-12-16 18:23:39 -05001520 __p1_(__default_init_tag(), __node_allocator(__a)),
Howard Hinnantce48a112011-06-30 21:18:19 +00001521 __p2_(0, _VSTD::move(__u.hash_function())),
1522 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnant3e519522010-05-11 19:42:16 +00001523{
1524 if (__a == allocator_type(__u.__node_alloc()))
1525 {
1526 __bucket_list_.reset(__u.__bucket_list_.release());
1527 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
1528 __u.__bucket_list_.get_deleter().size() = 0;
1529 if (__u.size() > 0)
1530 {
1531 __p1_.first().__next_ = __u.__p1_.first().__next_;
1532 __u.__p1_.first().__next_ = nullptr;
Eric Fiselier40492ba2016-07-23 20:36:55 +00001533 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] =
1534 __p1_.first().__ptr();
Howard Hinnant3e519522010-05-11 19:42:16 +00001535 size() = __u.size();
1536 __u.size() = 0;
1537 }
1538 }
1539}
1540
Eric Fiselierfcd02212016-02-11 11:59:44 +00001541#endif // _LIBCPP_CXX03_LANG
Howard Hinnant3e519522010-05-11 19:42:16 +00001542
1543template <class _Tp, class _Hash, class _Equal, class _Alloc>
1544__hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table()
1545{
Eric Fiselieracb21582017-03-01 02:02:28 +00001546#if defined(_LIBCPP_CXX03_LANG)
Marshall Clow3b8669e2016-06-30 22:05:45 +00001547 static_assert((is_copy_constructible<key_equal>::value),
1548 "Predicate must be copy-constructible.");
1549 static_assert((is_copy_constructible<hasher>::value),
1550 "Hasher must be copy-constructible.");
Eric Fiselier04333f92017-01-13 22:42:53 +00001551#endif
Eric Fiselieracb21582017-03-01 02:02:28 +00001552
Eric Fiseliercd71f442017-01-07 03:01:24 +00001553 __deallocate_node(__p1_.first().__next_);
Louis Dionne31e82032020-10-02 15:02:52 -04001554#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00001555 __get_db()->__erase_c(this);
1556#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001557}
1558
1559template <class _Tp, class _Hash, class _Equal, class _Alloc>
1560void
1561__hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc(
1562 const __hash_table& __u, true_type)
1563{
1564 if (__node_alloc() != __u.__node_alloc())
1565 {
1566 clear();
1567 __bucket_list_.reset();
1568 __bucket_list_.get_deleter().size() = 0;
1569 }
1570 __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc();
1571 __node_alloc() = __u.__node_alloc();
1572}
1573
1574template <class _Tp, class _Hash, class _Equal, class _Alloc>
1575__hash_table<_Tp, _Hash, _Equal, _Alloc>&
1576__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u)
1577{
1578 if (this != &__u)
1579 {
1580 __copy_assign_alloc(__u);
1581 hash_function() = __u.hash_function();
1582 key_eq() = __u.key_eq();
1583 max_load_factor() = __u.max_load_factor();
1584 __assign_multi(__u.begin(), __u.end());
1585 }
1586 return *this;
1587}
1588
1589template <class _Tp, class _Hash, class _Equal, class _Alloc>
1590void
Eric Fiseliercd71f442017-01-07 03:01:24 +00001591__hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate_node(__next_pointer __np)
Howard Hinnant37141072011-06-04 18:54:24 +00001592 _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +00001593{
1594 __node_allocator& __na = __node_alloc();
1595 while (__np != nullptr)
1596 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00001597 __next_pointer __next = __np->__next_;
Louis Dionne31e82032020-10-02 15:02:52 -04001598#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00001599 __c_node* __c = __get_db()->__find_c_and_lock(this);
1600 for (__i_node** __p = __c->end_; __p != __c->beg_; )
1601 {
1602 --__p;
1603 iterator* __i = static_cast<iterator*>((*__p)->__i_);
1604 if (__i->__node_ == __np)
1605 {
1606 (*__p)->__c_ = nullptr;
1607 if (--__c->end_ != __p)
1608 memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*));
1609 }
1610 }
1611 __get_db()->unlock();
1612#endif
Eric Fiselier40492ba2016-07-23 20:36:55 +00001613 __node_pointer __real_np = __np->__upcast();
1614 __node_traits::destroy(__na, _NodeTypes::__get_ptr(__real_np->__value_));
1615 __node_traits::deallocate(__na, __real_np, 1);
Howard Hinnant3e519522010-05-11 19:42:16 +00001616 __np = __next;
1617 }
1618}
1619
1620template <class _Tp, class _Hash, class _Equal, class _Alloc>
Eric Fiselier40492ba2016-07-23 20:36:55 +00001621typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
Howard Hinnant37141072011-06-04 18:54:24 +00001622__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +00001623{
1624 size_type __bc = bucket_count();
1625 for (size_type __i = 0; __i < __bc; ++__i)
1626 __bucket_list_[__i] = nullptr;
1627 size() = 0;
Eric Fiselier40492ba2016-07-23 20:36:55 +00001628 __next_pointer __cache = __p1_.first().__next_;
Howard Hinnant3e519522010-05-11 19:42:16 +00001629 __p1_.first().__next_ = nullptr;
1630 return __cache;
1631}
1632
Eric Fiselierfcd02212016-02-11 11:59:44 +00001633#ifndef _LIBCPP_CXX03_LANG
Howard Hinnant3e519522010-05-11 19:42:16 +00001634
1635template <class _Tp, class _Hash, class _Equal, class _Alloc>
1636void
1637__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
1638 __hash_table& __u, true_type)
Howard Hinnant37141072011-06-04 18:54:24 +00001639 _NOEXCEPT_(
1640 is_nothrow_move_assignable<__node_allocator>::value &&
1641 is_nothrow_move_assignable<hasher>::value &&
1642 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnant3e519522010-05-11 19:42:16 +00001643{
1644 clear();
1645 __bucket_list_.reset(__u.__bucket_list_.release());
1646 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
1647 __u.__bucket_list_.get_deleter().size() = 0;
1648 __move_assign_alloc(__u);
1649 size() = __u.size();
Howard Hinnantce48a112011-06-30 21:18:19 +00001650 hash_function() = _VSTD::move(__u.hash_function());
Howard Hinnant3e519522010-05-11 19:42:16 +00001651 max_load_factor() = __u.max_load_factor();
Howard Hinnantce48a112011-06-30 21:18:19 +00001652 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnant3e519522010-05-11 19:42:16 +00001653 __p1_.first().__next_ = __u.__p1_.first().__next_;
1654 if (size() > 0)
1655 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00001656 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] =
1657 __p1_.first().__ptr();
Howard Hinnant3e519522010-05-11 19:42:16 +00001658 __u.__p1_.first().__next_ = nullptr;
1659 __u.size() = 0;
1660 }
Louis Dionne31e82032020-10-02 15:02:52 -04001661#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00001662 __get_db()->swap(this, &__u);
1663#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001664}
1665
1666template <class _Tp, class _Hash, class _Equal, class _Alloc>
1667void
1668__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
1669 __hash_table& __u, false_type)
1670{
1671 if (__node_alloc() == __u.__node_alloc())
1672 __move_assign(__u, true_type());
1673 else
1674 {
Howard Hinnantce48a112011-06-30 21:18:19 +00001675 hash_function() = _VSTD::move(__u.hash_function());
1676 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnant3e519522010-05-11 19:42:16 +00001677 max_load_factor() = __u.max_load_factor();
1678 if (bucket_count() != 0)
1679 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00001680 __next_pointer __cache = __detach();
Howard Hinnant3e519522010-05-11 19:42:16 +00001681#ifndef _LIBCPP_NO_EXCEPTIONS
1682 try
1683 {
Howard Hinnantb3371f62010-08-22 00:02:43 +00001684#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16 +00001685 const_iterator __i = __u.begin();
1686 while (__cache != nullptr && __u.size() != 0)
1687 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00001688 __cache->__upcast()->__value_ =
1689 _VSTD::move(__u.remove(__i++)->__value_);
1690 __next_pointer __next = __cache->__next_;
1691 __node_insert_multi(__cache->__upcast());
Howard Hinnant3e519522010-05-11 19:42:16 +00001692 __cache = __next;
1693 }
1694#ifndef _LIBCPP_NO_EXCEPTIONS
1695 }
1696 catch (...)
1697 {
Eric Fiseliercd71f442017-01-07 03:01:24 +00001698 __deallocate_node(__cache);
Howard Hinnant3e519522010-05-11 19:42:16 +00001699 throw;
1700 }
Howard Hinnantb3371f62010-08-22 00:02:43 +00001701#endif // _LIBCPP_NO_EXCEPTIONS
Eric Fiseliercd71f442017-01-07 03:01:24 +00001702 __deallocate_node(__cache);
Howard Hinnant3e519522010-05-11 19:42:16 +00001703 }
1704 const_iterator __i = __u.begin();
1705 while (__u.size() != 0)
1706 {
Eric Fiselierfcd02212016-02-11 11:59:44 +00001707 __node_holder __h = __construct_node(_NodeTypes::__move(__u.remove(__i++)->__value_));
Howard Hinnant3e519522010-05-11 19:42:16 +00001708 __node_insert_multi(__h.get());
1709 __h.release();
1710 }
1711 }
1712}
1713
1714template <class _Tp, class _Hash, class _Equal, class _Alloc>
Evgeniy Stepanov906c8722015-11-07 01:22:13 +00001715inline
Howard Hinnant3e519522010-05-11 19:42:16 +00001716__hash_table<_Tp, _Hash, _Equal, _Alloc>&
1717__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u)
Howard Hinnant37141072011-06-04 18:54:24 +00001718 _NOEXCEPT_(
1719 __node_traits::propagate_on_container_move_assignment::value &&
1720 is_nothrow_move_assignable<__node_allocator>::value &&
1721 is_nothrow_move_assignable<hasher>::value &&
1722 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnant3e519522010-05-11 19:42:16 +00001723{
1724 __move_assign(__u, integral_constant<bool,
1725 __node_traits::propagate_on_container_move_assignment::value>());
1726 return *this;
1727}
1728
Eric Fiselierfcd02212016-02-11 11:59:44 +00001729#endif // _LIBCPP_CXX03_LANG
Howard Hinnant3e519522010-05-11 19:42:16 +00001730
1731template <class _Tp, class _Hash, class _Equal, class _Alloc>
1732template <class _InputIterator>
1733void
1734__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first,
1735 _InputIterator __last)
1736{
Eric Fiselierfcd02212016-02-11 11:59:44 +00001737 typedef iterator_traits<_InputIterator> _ITraits;
1738 typedef typename _ITraits::value_type _ItValueType;
1739 static_assert((is_same<_ItValueType, __container_value_type>::value),
1740 "__assign_unique may only be called with the containers value type");
1741
Howard Hinnant3e519522010-05-11 19:42:16 +00001742 if (bucket_count() != 0)
1743 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00001744 __next_pointer __cache = __detach();
Howard Hinnant3e519522010-05-11 19:42:16 +00001745#ifndef _LIBCPP_NO_EXCEPTIONS
1746 try
1747 {
Howard Hinnantb3371f62010-08-22 00:02:43 +00001748#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16 +00001749 for (; __cache != nullptr && __first != __last; ++__first)
1750 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00001751 __cache->__upcast()->__value_ = *__first;
1752 __next_pointer __next = __cache->__next_;
1753 __node_insert_unique(__cache->__upcast());
Howard Hinnant3e519522010-05-11 19:42:16 +00001754 __cache = __next;
1755 }
1756#ifndef _LIBCPP_NO_EXCEPTIONS
1757 }
1758 catch (...)
1759 {
Eric Fiseliercd71f442017-01-07 03:01:24 +00001760 __deallocate_node(__cache);
Howard Hinnant3e519522010-05-11 19:42:16 +00001761 throw;
1762 }
Howard Hinnantb3371f62010-08-22 00:02:43 +00001763#endif // _LIBCPP_NO_EXCEPTIONS
Eric Fiseliercd71f442017-01-07 03:01:24 +00001764 __deallocate_node(__cache);
Howard Hinnant3e519522010-05-11 19:42:16 +00001765 }
1766 for (; __first != __last; ++__first)
1767 __insert_unique(*__first);
1768}
1769
1770template <class _Tp, class _Hash, class _Equal, class _Alloc>
1771template <class _InputIterator>
1772void
1773__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first,
1774 _InputIterator __last)
1775{
Eric Fiselierfcd02212016-02-11 11:59:44 +00001776 typedef iterator_traits<_InputIterator> _ITraits;
1777 typedef typename _ITraits::value_type _ItValueType;
1778 static_assert((is_same<_ItValueType, __container_value_type>::value ||
1779 is_same<_ItValueType, __node_value_type>::value),
1780 "__assign_multi may only be called with the containers value type"
1781 " or the nodes value type");
Howard Hinnant3e519522010-05-11 19:42:16 +00001782 if (bucket_count() != 0)
1783 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00001784 __next_pointer __cache = __detach();
Howard Hinnant3e519522010-05-11 19:42:16 +00001785#ifndef _LIBCPP_NO_EXCEPTIONS
1786 try
1787 {
Howard Hinnantb3371f62010-08-22 00:02:43 +00001788#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnant3e519522010-05-11 19:42:16 +00001789 for (; __cache != nullptr && __first != __last; ++__first)
1790 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00001791 __cache->__upcast()->__value_ = *__first;
1792 __next_pointer __next = __cache->__next_;
1793 __node_insert_multi(__cache->__upcast());
Howard Hinnant3e519522010-05-11 19:42:16 +00001794 __cache = __next;
1795 }
1796#ifndef _LIBCPP_NO_EXCEPTIONS
1797 }
1798 catch (...)
1799 {
Eric Fiseliercd71f442017-01-07 03:01:24 +00001800 __deallocate_node(__cache);
Howard Hinnant3e519522010-05-11 19:42:16 +00001801 throw;
1802 }
Howard Hinnantb3371f62010-08-22 00:02:43 +00001803#endif // _LIBCPP_NO_EXCEPTIONS
Eric Fiseliercd71f442017-01-07 03:01:24 +00001804 __deallocate_node(__cache);
Howard Hinnant3e519522010-05-11 19:42:16 +00001805 }
1806 for (; __first != __last; ++__first)
Eric Fiselierfcd02212016-02-11 11:59:44 +00001807 __insert_multi(_NodeTypes::__get_value(*__first));
Howard Hinnant3e519522010-05-11 19:42:16 +00001808}
1809
1810template <class _Tp, class _Hash, class _Equal, class _Alloc>
Evgeniy Stepanov906c8722015-11-07 01:22:13 +00001811inline
Howard Hinnant3e519522010-05-11 19:42:16 +00001812typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant37141072011-06-04 18:54:24 +00001813__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +00001814{
Louis Dionne31e82032020-10-02 15:02:52 -04001815#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00001816 return iterator(__p1_.first().__next_, this);
1817#else
Howard Hinnant3e519522010-05-11 19:42:16 +00001818 return iterator(__p1_.first().__next_);
Howard Hinnantb24c8022013-07-23 22:01:58 +00001819#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001820}
1821
1822template <class _Tp, class _Hash, class _Equal, class _Alloc>
Evgeniy Stepanov906c8722015-11-07 01:22:13 +00001823inline
Howard Hinnant3e519522010-05-11 19:42:16 +00001824typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant37141072011-06-04 18:54:24 +00001825__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +00001826{
Louis Dionne31e82032020-10-02 15:02:52 -04001827#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00001828 return iterator(nullptr, this);
1829#else
Howard Hinnant3e519522010-05-11 19:42:16 +00001830 return iterator(nullptr);
Howard Hinnantb24c8022013-07-23 22:01:58 +00001831#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001832}
1833
1834template <class _Tp, class _Hash, class _Equal, class _Alloc>
Evgeniy Stepanov906c8722015-11-07 01:22:13 +00001835inline
Howard Hinnant3e519522010-05-11 19:42:16 +00001836typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant37141072011-06-04 18:54:24 +00001837__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +00001838{
Louis Dionne31e82032020-10-02 15:02:52 -04001839#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00001840 return const_iterator(__p1_.first().__next_, this);
1841#else
Howard Hinnant3e519522010-05-11 19:42:16 +00001842 return const_iterator(__p1_.first().__next_);
Howard Hinnantb24c8022013-07-23 22:01:58 +00001843#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001844}
1845
1846template <class _Tp, class _Hash, class _Equal, class _Alloc>
Evgeniy Stepanov906c8722015-11-07 01:22:13 +00001847inline
Howard Hinnant3e519522010-05-11 19:42:16 +00001848typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant37141072011-06-04 18:54:24 +00001849__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +00001850{
Louis Dionne31e82032020-10-02 15:02:52 -04001851#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00001852 return const_iterator(nullptr, this);
1853#else
Howard Hinnant3e519522010-05-11 19:42:16 +00001854 return const_iterator(nullptr);
Howard Hinnantb24c8022013-07-23 22:01:58 +00001855#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00001856}
1857
1858template <class _Tp, class _Hash, class _Equal, class _Alloc>
1859void
Howard Hinnant37141072011-06-04 18:54:24 +00001860__hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +00001861{
1862 if (size() > 0)
1863 {
Eric Fiseliercd71f442017-01-07 03:01:24 +00001864 __deallocate_node(__p1_.first().__next_);
Howard Hinnant3e519522010-05-11 19:42:16 +00001865 __p1_.first().__next_ = nullptr;
1866 size_type __bc = bucket_count();
Howard Hinnant1f8da842011-07-05 14:14:17 +00001867 for (size_type __i = 0; __i < __bc; ++__i)
Howard Hinnant3e519522010-05-11 19:42:16 +00001868 __bucket_list_[__i] = nullptr;
1869 size() = 0;
1870 }
1871}
1872
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001873
1874// Prepare the container for an insertion of the value __value with the hash
1875// __hash. This does a lookup into the container to see if __value is already
1876// present, and performs a rehash if necessary. Returns a pointer to the
1877// existing element if it exists, otherwise nullptr.
1878//
1879// Note that this function does forward exceptions if key_eq() throws, and never
1880// mutates __value or actually inserts into the map.
Howard Hinnant3e519522010-05-11 19:42:16 +00001881template <class _Tp, class _Hash, class _Equal, class _Alloc>
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001882_LIBCPP_INLINE_VISIBILITY
1883typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
1884__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_prepare(
1885 size_t __hash, value_type& __value)
Howard Hinnant3e519522010-05-11 19:42:16 +00001886{
Howard Hinnant3e519522010-05-11 19:42:16 +00001887 size_type __bc = bucket_count();
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001888
Howard Hinnant3e519522010-05-11 19:42:16 +00001889 if (__bc != 0)
1890 {
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001891 size_t __chash = __constrain_hash(__hash, __bc);
1892 __next_pointer __ndptr = __bucket_list_[__chash];
Howard Hinnant3e519522010-05-11 19:42:16 +00001893 if (__ndptr != nullptr)
1894 {
1895 for (__ndptr = __ndptr->__next_; __ndptr != nullptr &&
Eric Fiselier40492ba2016-07-23 20:36:55 +00001896 __constrain_hash(__ndptr->__hash(), __bc) == __chash;
Howard Hinnant3e519522010-05-11 19:42:16 +00001897 __ndptr = __ndptr->__next_)
1898 {
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001899 if (key_eq()(__ndptr->__upcast()->__value_, __value))
1900 return __ndptr;
Howard Hinnant3e519522010-05-11 19:42:16 +00001901 }
1902 }
1903 }
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001904 if (size()+1 > __bc * max_load_factor() || __bc == 0)
Howard Hinnant3e519522010-05-11 19:42:16 +00001905 {
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001906 rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc),
1907 size_type(ceil(float(size() + 1) / max_load_factor()))));
Howard Hinnant3e519522010-05-11 19:42:16 +00001908 }
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001909 return nullptr;
1910}
1911
1912// Insert the node __nd into the container by pushing it into the right bucket,
1913// and updating size(). Assumes that __nd->__hash is up-to-date, and that
1914// rehashing has already occurred and that no element with the same key exists
1915// in the map.
1916template <class _Tp, class _Hash, class _Equal, class _Alloc>
1917_LIBCPP_INLINE_VISIBILITY
1918void
1919__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique_perform(
1920 __node_pointer __nd) _NOEXCEPT
1921{
1922 size_type __bc = bucket_count();
1923 size_t __chash = __constrain_hash(__nd->__hash(), __bc);
1924 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1925 __next_pointer __pn = __bucket_list_[__chash];
1926 if (__pn == nullptr)
1927 {
1928 __pn =__p1_.first().__ptr();
1929 __nd->__next_ = __pn->__next_;
1930 __pn->__next_ = __nd->__ptr();
1931 // fix up __bucket_list_
1932 __bucket_list_[__chash] = __pn;
1933 if (__nd->__next_ != nullptr)
1934 __bucket_list_[__constrain_hash(__nd->__next_->__hash(), __bc)] = __nd->__ptr();
1935 }
1936 else
1937 {
1938 __nd->__next_ = __pn->__next_;
1939 __pn->__next_ = __nd->__ptr();
1940 }
1941 ++size();
Howard Hinnant3e519522010-05-11 19:42:16 +00001942}
1943
1944template <class _Tp, class _Hash, class _Equal, class _Alloc>
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001945pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1946__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd)
Howard Hinnant3e519522010-05-11 19:42:16 +00001947{
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001948 __nd->__hash_ = hash_function()(__nd->__value_);
1949 __next_pointer __existing_node =
1950 __node_insert_unique_prepare(__nd->__hash(), __nd->__value_);
1951
1952 // Insert the node, unless it already exists in the container.
1953 bool __inserted = false;
1954 if (__existing_node == nullptr)
1955 {
1956 __node_insert_unique_perform(__nd);
1957 __existing_node = __nd->__ptr();
1958 __inserted = true;
1959 }
Louis Dionne31e82032020-10-02 15:02:52 -04001960#if _LIBCPP_DEBUG_LEVEL == 2
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001961 return pair<iterator, bool>(iterator(__existing_node, this), __inserted);
1962#else
1963 return pair<iterator, bool>(iterator(__existing_node), __inserted);
1964#endif
1965}
1966
1967// Prepare the container for an insertion of the value __cp_val with the hash
1968// __cp_hash. This does a lookup into the container to see if __cp_value is
1969// already present, and performs a rehash if necessary. Returns a pointer to the
1970// last occurance of __cp_val in the map.
1971//
1972// Note that this function does forward exceptions if key_eq() throws, and never
1973// mutates __value or actually inserts into the map.
1974template <class _Tp, class _Hash, class _Equal, class _Alloc>
1975typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__next_pointer
1976__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_prepare(
1977 size_t __cp_hash, value_type& __cp_val)
1978{
Howard Hinnant3e519522010-05-11 19:42:16 +00001979 size_type __bc = bucket_count();
1980 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1981 {
Eric Fiselier9ba5c112015-02-02 21:31:48 +00001982 rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc),
Howard Hinnant3e519522010-05-11 19:42:16 +00001983 size_type(ceil(float(size() + 1) / max_load_factor()))));
1984 __bc = bucket_count();
1985 }
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001986 size_t __chash = __constrain_hash(__cp_hash, __bc);
Eric Fiselier40492ba2016-07-23 20:36:55 +00001987 __next_pointer __pn = __bucket_list_[__chash];
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00001988 if (__pn != nullptr)
1989 {
1990 for (bool __found = false; __pn->__next_ != nullptr &&
1991 __constrain_hash(__pn->__next_->__hash(), __bc) == __chash;
1992 __pn = __pn->__next_)
1993 {
1994 // __found key_eq() action
1995 // false false loop
1996 // true true loop
1997 // false true set __found to true
1998 // true false break
1999 if (__found != (__pn->__next_->__hash() == __cp_hash &&
2000 key_eq()(__pn->__next_->__upcast()->__value_, __cp_val)))
2001 {
2002 if (!__found)
2003 __found = true;
2004 else
2005 break;
2006 }
2007 }
2008 }
2009 return __pn;
2010}
2011
2012// Insert the node __cp into the container after __pn (which is the last node in
2013// the bucket that compares equal to __cp). Rehashing, and checking for
2014// uniqueness has already been performed (in __node_insert_multi_prepare), so
2015// all we need to do is update the bucket and size(). Assumes that __cp->__hash
2016// is up-to-date.
2017template <class _Tp, class _Hash, class _Equal, class _Alloc>
2018void
2019__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi_perform(
2020 __node_pointer __cp, __next_pointer __pn) _NOEXCEPT
2021{
2022 size_type __bc = bucket_count();
2023 size_t __chash = __constrain_hash(__cp->__hash_, __bc);
Howard Hinnant3e519522010-05-11 19:42:16 +00002024 if (__pn == nullptr)
2025 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00002026 __pn =__p1_.first().__ptr();
Howard Hinnant3e519522010-05-11 19:42:16 +00002027 __cp->__next_ = __pn->__next_;
Eric Fiselier40492ba2016-07-23 20:36:55 +00002028 __pn->__next_ = __cp->__ptr();
Howard Hinnant3e519522010-05-11 19:42:16 +00002029 // fix up __bucket_list_
2030 __bucket_list_[__chash] = __pn;
2031 if (__cp->__next_ != nullptr)
Eric Fiselier40492ba2016-07-23 20:36:55 +00002032 __bucket_list_[__constrain_hash(__cp->__next_->__hash(), __bc)]
2033 = __cp->__ptr();
Howard Hinnant3e519522010-05-11 19:42:16 +00002034 }
2035 else
2036 {
Howard Hinnant3e519522010-05-11 19:42:16 +00002037 __cp->__next_ = __pn->__next_;
Eric Fiselier40492ba2016-07-23 20:36:55 +00002038 __pn->__next_ = __cp->__ptr();
Howard Hinnant3e519522010-05-11 19:42:16 +00002039 if (__cp->__next_ != nullptr)
2040 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00002041 size_t __nhash = __constrain_hash(__cp->__next_->__hash(), __bc);
Howard Hinnant3e519522010-05-11 19:42:16 +00002042 if (__nhash != __chash)
Eric Fiselier40492ba2016-07-23 20:36:55 +00002043 __bucket_list_[__nhash] = __cp->__ptr();
Howard Hinnant3e519522010-05-11 19:42:16 +00002044 }
2045 }
2046 ++size();
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00002047}
2048
2049
2050template <class _Tp, class _Hash, class _Equal, class _Alloc>
2051typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2052__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp)
2053{
2054 __cp->__hash_ = hash_function()(__cp->__value_);
2055 __next_pointer __pn = __node_insert_multi_prepare(__cp->__hash(), __cp->__value_);
2056 __node_insert_multi_perform(__cp, __pn);
2057
Louis Dionne31e82032020-10-02 15:02:52 -04002058#if _LIBCPP_DEBUG_LEVEL == 2
Eric Fiselier40492ba2016-07-23 20:36:55 +00002059 return iterator(__cp->__ptr(), this);
Howard Hinnantb24c8022013-07-23 22:01:58 +00002060#else
Eric Fiselier40492ba2016-07-23 20:36:55 +00002061 return iterator(__cp->__ptr());
Howard Hinnantb24c8022013-07-23 22:01:58 +00002062#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00002063}
2064
2065template <class _Tp, class _Hash, class _Equal, class _Alloc>
2066typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2067__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(
2068 const_iterator __p, __node_pointer __cp)
2069{
Louis Dionne31e82032020-10-02 15:02:52 -04002070#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnant2f51de52013-08-02 17:50:49 +00002071 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
2072 "unordered container::emplace_hint(const_iterator, args...) called with an iterator not"
2073 " referring to this unordered container");
2074#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00002075 if (__p != end() && key_eq()(*__p, __cp->__value_))
2076 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00002077 __next_pointer __np = __p.__node_;
2078 __cp->__hash_ = __np->__hash();
Howard Hinnant3e519522010-05-11 19:42:16 +00002079 size_type __bc = bucket_count();
2080 if (size()+1 > __bc * max_load_factor() || __bc == 0)
2081 {
Eric Fiselier9ba5c112015-02-02 21:31:48 +00002082 rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc),
Howard Hinnant3e519522010-05-11 19:42:16 +00002083 size_type(ceil(float(size() + 1) / max_load_factor()))));
2084 __bc = bucket_count();
2085 }
Howard Hinnant4cb38a82012-07-06 17:31:14 +00002086 size_t __chash = __constrain_hash(__cp->__hash_, __bc);
Eric Fiselier40492ba2016-07-23 20:36:55 +00002087 __next_pointer __pp = __bucket_list_[__chash];
Howard Hinnant3e519522010-05-11 19:42:16 +00002088 while (__pp->__next_ != __np)
2089 __pp = __pp->__next_;
2090 __cp->__next_ = __np;
Eric Fiselier40492ba2016-07-23 20:36:55 +00002091 __pp->__next_ = static_cast<__next_pointer>(__cp);
Howard Hinnant3e519522010-05-11 19:42:16 +00002092 ++size();
Louis Dionne31e82032020-10-02 15:02:52 -04002093#if _LIBCPP_DEBUG_LEVEL == 2
Eric Fiselier40492ba2016-07-23 20:36:55 +00002094 return iterator(static_cast<__next_pointer>(__cp), this);
Howard Hinnantb24c8022013-07-23 22:01:58 +00002095#else
Eric Fiselier40492ba2016-07-23 20:36:55 +00002096 return iterator(static_cast<__next_pointer>(__cp));
Howard Hinnantb24c8022013-07-23 22:01:58 +00002097#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00002098 }
2099 return __node_insert_multi(__cp);
2100}
2101
Eric Fiselierde3f2b32015-06-13 07:18:32 +00002102
2103
Eric Fiselierfcd02212016-02-11 11:59:44 +00002104#ifndef _LIBCPP_CXX03_LANG
Eric Fiselierde3f2b32015-06-13 07:18:32 +00002105template <class _Tp, class _Hash, class _Equal, class _Alloc>
Eric Fiselierfcd02212016-02-11 11:59:44 +00002106template <class _Key, class ..._Args>
Eric Fiselierde3f2b32015-06-13 07:18:32 +00002107pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
Eric Fiselierfcd02212016-02-11 11:59:44 +00002108__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args)
Eric Fiselierde3f2b32015-06-13 07:18:32 +00002109#else
2110template <class _Tp, class _Hash, class _Equal, class _Alloc>
Eric Fiselierfcd02212016-02-11 11:59:44 +00002111template <class _Key, class _Args>
Eric Fiselierde3f2b32015-06-13 07:18:32 +00002112pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
Eric Fiselierfcd02212016-02-11 11:59:44 +00002113__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __k, _Args& __args)
Eric Fiselierde3f2b32015-06-13 07:18:32 +00002114#endif
2115{
Eric Fiselierfcd02212016-02-11 11:59:44 +00002116
2117 size_t __hash = hash_function()(__k);
Howard Hinnant3e519522010-05-11 19:42:16 +00002118 size_type __bc = bucket_count();
2119 bool __inserted = false;
Eric Fiselier40492ba2016-07-23 20:36:55 +00002120 __next_pointer __nd;
Howard Hinnant3e519522010-05-11 19:42:16 +00002121 size_t __chash;
2122 if (__bc != 0)
2123 {
Howard Hinnant4cb38a82012-07-06 17:31:14 +00002124 __chash = __constrain_hash(__hash, __bc);
Howard Hinnant3e519522010-05-11 19:42:16 +00002125 __nd = __bucket_list_[__chash];
2126 if (__nd != nullptr)
2127 {
2128 for (__nd = __nd->__next_; __nd != nullptr &&
Eric Fiselier1a06fe52016-07-24 06:22:25 +00002129 (__nd->__hash() == __hash || __constrain_hash(__nd->__hash(), __bc) == __chash);
Howard Hinnant3e519522010-05-11 19:42:16 +00002130 __nd = __nd->__next_)
2131 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00002132 if (key_eq()(__nd->__upcast()->__value_, __k))
Howard Hinnant3e519522010-05-11 19:42:16 +00002133 goto __done;
2134 }
2135 }
2136 }
2137 {
Eric Fiselierfcd02212016-02-11 11:59:44 +00002138#ifndef _LIBCPP_CXX03_LANG
2139 __node_holder __h = __construct_node_hash(__hash, _VSTD::forward<_Args>(__args)...);
2140#else
2141 __node_holder __h = __construct_node_hash(__hash, __args);
2142#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00002143 if (size()+1 > __bc * max_load_factor() || __bc == 0)
2144 {
Eric Fiselier9ba5c112015-02-02 21:31:48 +00002145 rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc),
Howard Hinnant3e519522010-05-11 19:42:16 +00002146 size_type(ceil(float(size() + 1) / max_load_factor()))));
2147 __bc = bucket_count();
Howard Hinnant4cb38a82012-07-06 17:31:14 +00002148 __chash = __constrain_hash(__hash, __bc);
Howard Hinnant3e519522010-05-11 19:42:16 +00002149 }
2150 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
Eric Fiselier40492ba2016-07-23 20:36:55 +00002151 __next_pointer __pn = __bucket_list_[__chash];
Howard Hinnant3e519522010-05-11 19:42:16 +00002152 if (__pn == nullptr)
2153 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00002154 __pn = __p1_.first().__ptr();
Howard Hinnant3e519522010-05-11 19:42:16 +00002155 __h->__next_ = __pn->__next_;
Eric Fiselier40492ba2016-07-23 20:36:55 +00002156 __pn->__next_ = __h.get()->__ptr();
Howard Hinnant3e519522010-05-11 19:42:16 +00002157 // fix up __bucket_list_
2158 __bucket_list_[__chash] = __pn;
2159 if (__h->__next_ != nullptr)
Eric Fiselier40492ba2016-07-23 20:36:55 +00002160 __bucket_list_[__constrain_hash(__h->__next_->__hash(), __bc)]
2161 = __h.get()->__ptr();
Howard Hinnant3e519522010-05-11 19:42:16 +00002162 }
2163 else
2164 {
2165 __h->__next_ = __pn->__next_;
Eric Fiselier40492ba2016-07-23 20:36:55 +00002166 __pn->__next_ = static_cast<__next_pointer>(__h.get());
Howard Hinnant3e519522010-05-11 19:42:16 +00002167 }
Eric Fiselier40492ba2016-07-23 20:36:55 +00002168 __nd = static_cast<__next_pointer>(__h.release());
Howard Hinnant3e519522010-05-11 19:42:16 +00002169 // increment size
2170 ++size();
2171 __inserted = true;
2172 }
2173__done:
Louis Dionne31e82032020-10-02 15:02:52 -04002174#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00002175 return pair<iterator, bool>(iterator(__nd, this), __inserted);
2176#else
Howard Hinnant3e519522010-05-11 19:42:16 +00002177 return pair<iterator, bool>(iterator(__nd), __inserted);
Howard Hinnantb24c8022013-07-23 22:01:58 +00002178#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00002179}
2180
Eric Fiselierfcd02212016-02-11 11:59:44 +00002181#ifndef _LIBCPP_CXX03_LANG
Howard Hinnant3e519522010-05-11 19:42:16 +00002182
2183template <class _Tp, class _Hash, class _Equal, class _Alloc>
2184template <class... _Args>
2185pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
Duncan P. N. Exon Smithfde79b42016-03-17 20:45:20 +00002186__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_impl(_Args&&... __args)
Howard Hinnant3e519522010-05-11 19:42:16 +00002187{
Howard Hinnantce48a112011-06-30 21:18:19 +00002188 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnant3e519522010-05-11 19:42:16 +00002189 pair<iterator, bool> __r = __node_insert_unique(__h.get());
2190 if (__r.second)
2191 __h.release();
2192 return __r;
2193}
2194
2195template <class _Tp, class _Hash, class _Equal, class _Alloc>
2196template <class... _Args>
2197typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2198__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args)
2199{
Howard Hinnantce48a112011-06-30 21:18:19 +00002200 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnant3e519522010-05-11 19:42:16 +00002201 iterator __r = __node_insert_multi(__h.get());
2202 __h.release();
2203 return __r;
2204}
2205
2206template <class _Tp, class _Hash, class _Equal, class _Alloc>
2207template <class... _Args>
2208typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2209__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi(
2210 const_iterator __p, _Args&&... __args)
2211{
Louis Dionne31e82032020-10-02 15:02:52 -04002212#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnante5c13de2013-07-29 19:05:47 +00002213 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
2214 "unordered container::emplace_hint(const_iterator, args...) called with an iterator not"
2215 " referring to this unordered container");
2216#endif
Howard Hinnantce48a112011-06-30 21:18:19 +00002217 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnant3e519522010-05-11 19:42:16 +00002218 iterator __r = __node_insert_multi(__p, __h.get());
2219 __h.release();
2220 return __r;
2221}
2222
Eric Fiselierfcd02212016-02-11 11:59:44 +00002223#else // _LIBCPP_CXX03_LANG
Howard Hinnant3e519522010-05-11 19:42:16 +00002224
2225template <class _Tp, class _Hash, class _Equal, class _Alloc>
2226typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Eric Fiselierfcd02212016-02-11 11:59:44 +00002227__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const __container_value_type& __x)
Howard Hinnant3e519522010-05-11 19:42:16 +00002228{
2229 __node_holder __h = __construct_node(__x);
2230 iterator __r = __node_insert_multi(__h.get());
2231 __h.release();
2232 return __r;
2233}
2234
2235template <class _Tp, class _Hash, class _Equal, class _Alloc>
2236typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2237__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
Eric Fiselierfcd02212016-02-11 11:59:44 +00002238 const __container_value_type& __x)
Howard Hinnant3e519522010-05-11 19:42:16 +00002239{
Louis Dionne31e82032020-10-02 15:02:52 -04002240#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnante5c13de2013-07-29 19:05:47 +00002241 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
2242 "unordered container::insert(const_iterator, lvalue) called with an iterator not"
2243 " referring to this unordered container");
2244#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00002245 __node_holder __h = __construct_node(__x);
2246 iterator __r = __node_insert_multi(__p, __h.get());
2247 __h.release();
2248 return __r;
2249}
2250
Eric Fiselierfcd02212016-02-11 11:59:44 +00002251#endif // _LIBCPP_CXX03_LANG
Howard Hinnant3e519522010-05-11 19:42:16 +00002252
Erik Pilkingtonb0386a52018-08-01 01:33:38 +00002253#if _LIBCPP_STD_VER > 14
2254template <class _Tp, class _Hash, class _Equal, class _Alloc>
2255template <class _NodeHandle, class _InsertReturnType>
2256_LIBCPP_INLINE_VISIBILITY
2257_InsertReturnType
2258__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(
2259 _NodeHandle&& __nh)
2260{
2261 if (__nh.empty())
2262 return _InsertReturnType{end(), false, _NodeHandle()};
2263 pair<iterator, bool> __result = __node_insert_unique(__nh.__ptr_);
2264 if (__result.second)
Eric Fiselier6886f1e2019-04-24 09:43:44 +00002265 __nh.__release_ptr();
Erik Pilkingtonb0386a52018-08-01 01:33:38 +00002266 return _InsertReturnType{__result.first, __result.second, _VSTD::move(__nh)};
2267}
2268
2269template <class _Tp, class _Hash, class _Equal, class _Alloc>
2270template <class _NodeHandle>
2271_LIBCPP_INLINE_VISIBILITY
2272typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2273__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_unique(
2274 const_iterator, _NodeHandle&& __nh)
2275{
2276 if (__nh.empty())
2277 return end();
2278 pair<iterator, bool> __result = __node_insert_unique(__nh.__ptr_);
2279 if (__result.second)
Eric Fiselier6886f1e2019-04-24 09:43:44 +00002280 __nh.__release_ptr();
Erik Pilkingtonb0386a52018-08-01 01:33:38 +00002281 return __result.first;
2282}
2283
2284template <class _Tp, class _Hash, class _Equal, class _Alloc>
2285template <class _NodeHandle>
2286_LIBCPP_INLINE_VISIBILITY
2287_NodeHandle
2288__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(
2289 key_type const& __key)
2290{
2291 iterator __i = find(__key);
2292 if (__i == end())
2293 return _NodeHandle();
2294 return __node_handle_extract<_NodeHandle>(__i);
2295}
2296
2297template <class _Tp, class _Hash, class _Equal, class _Alloc>
2298template <class _NodeHandle>
2299_LIBCPP_INLINE_VISIBILITY
2300_NodeHandle
2301__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_extract(
2302 const_iterator __p)
2303{
2304 allocator_type __alloc(__node_alloc());
2305 return _NodeHandle(remove(__p).release(), __alloc);
2306}
2307
2308template <class _Tp, class _Hash, class _Equal, class _Alloc>
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00002309template <class _Table>
2310_LIBCPP_INLINE_VISIBILITY
2311void
2312__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_unique(
2313 _Table& __source)
2314{
2315 static_assert(is_same<__node, typename _Table::__node>::value, "");
2316
2317 for (typename _Table::iterator __it = __source.begin();
2318 __it != __source.end();)
2319 {
2320 __node_pointer __src_ptr = __it.__node_->__upcast();
2321 size_t __hash = hash_function()(__src_ptr->__value_);
2322 __next_pointer __existing_node =
2323 __node_insert_unique_prepare(__hash, __src_ptr->__value_);
2324 auto __prev_iter = __it++;
2325 if (__existing_node == nullptr)
2326 {
2327 (void)__source.remove(__prev_iter).release();
2328 __src_ptr->__hash_ = __hash;
2329 __node_insert_unique_perform(__src_ptr);
2330 }
2331 }
2332}
2333
2334template <class _Tp, class _Hash, class _Equal, class _Alloc>
Erik Pilkingtonb0386a52018-08-01 01:33:38 +00002335template <class _NodeHandle>
2336_LIBCPP_INLINE_VISIBILITY
2337typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2338__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(
2339 _NodeHandle&& __nh)
2340{
2341 if (__nh.empty())
2342 return end();
2343 iterator __result = __node_insert_multi(__nh.__ptr_);
Eric Fiselier6886f1e2019-04-24 09:43:44 +00002344 __nh.__release_ptr();
Erik Pilkingtonb0386a52018-08-01 01:33:38 +00002345 return __result;
2346}
2347
2348template <class _Tp, class _Hash, class _Equal, class _Alloc>
2349template <class _NodeHandle>
2350_LIBCPP_INLINE_VISIBILITY
2351typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2352__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_insert_multi(
2353 const_iterator __hint, _NodeHandle&& __nh)
2354{
2355 if (__nh.empty())
2356 return end();
2357 iterator __result = __node_insert_multi(__hint, __nh.__ptr_);
Eric Fiselier6886f1e2019-04-24 09:43:44 +00002358 __nh.__release_ptr();
Erik Pilkingtonb0386a52018-08-01 01:33:38 +00002359 return __result;
2360}
2361
Erik Pilkington5c4e07a2018-10-31 17:31:35 +00002362template <class _Tp, class _Hash, class _Equal, class _Alloc>
2363template <class _Table>
2364_LIBCPP_INLINE_VISIBILITY
2365void
2366__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_handle_merge_multi(
2367 _Table& __source)
2368{
2369 static_assert(is_same<typename _Table::__node, __node>::value, "");
2370
2371 for (typename _Table::iterator __it = __source.begin();
2372 __it != __source.end();)
2373 {
2374 __node_pointer __src_ptr = __it.__node_->__upcast();
2375 size_t __src_hash = hash_function()(__src_ptr->__value_);
2376 __next_pointer __pn =
2377 __node_insert_multi_prepare(__src_hash, __src_ptr->__value_);
2378 (void)__source.remove(__it++).release();
2379 __src_ptr->__hash_ = __src_hash;
2380 __node_insert_multi_perform(__src_ptr, __pn);
2381 }
2382}
Erik Pilkingtonb0386a52018-08-01 01:33:38 +00002383#endif // _LIBCPP_STD_VER > 14
2384
Howard Hinnant3e519522010-05-11 19:42:16 +00002385template <class _Tp, class _Hash, class _Equal, class _Alloc>
2386void
2387__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n)
Marshall Clow954966c2019-02-07 18:53:58 +00002388_LIBCPP_DISABLE_UBSAN_UNSIGNED_INTEGER_CHECK
Howard Hinnant3e519522010-05-11 19:42:16 +00002389{
Dan Albert553b09b2018-01-08 22:57:12 +00002390 if (__n == 1)
Howard Hinnant4cb38a82012-07-06 17:31:14 +00002391 __n = 2;
2392 else if (__n & (__n - 1))
2393 __n = __next_prime(__n);
Howard Hinnant3e519522010-05-11 19:42:16 +00002394 size_type __bc = bucket_count();
2395 if (__n > __bc)
2396 __rehash(__n);
Howard Hinnant4cb38a82012-07-06 17:31:14 +00002397 else if (__n < __bc)
Howard Hinnant3e519522010-05-11 19:42:16 +00002398 {
Howard Hinnantce48a112011-06-30 21:18:19 +00002399 __n = _VSTD::max<size_type>
Howard Hinnant3e519522010-05-11 19:42:16 +00002400 (
2401 __n,
Eric Fiselier9ba5c112015-02-02 21:31:48 +00002402 __is_hash_power2(__bc) ? __next_hash_pow2(size_t(ceil(float(size()) / max_load_factor()))) :
2403 __next_prime(size_t(ceil(float(size()) / max_load_factor())))
Howard Hinnant3e519522010-05-11 19:42:16 +00002404 );
2405 if (__n < __bc)
2406 __rehash(__n);
2407 }
2408}
2409
2410template <class _Tp, class _Hash, class _Equal, class _Alloc>
2411void
2412__hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc)
2413{
Louis Dionne31e82032020-10-02 15:02:52 -04002414#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00002415 __get_db()->__invalidate_all(this);
Louis Dionne31e82032020-10-02 15:02:52 -04002416#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00002417 __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc();
2418 __bucket_list_.reset(__nbc > 0 ?
2419 __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr);
2420 __bucket_list_.get_deleter().size() = __nbc;
2421 if (__nbc > 0)
2422 {
2423 for (size_type __i = 0; __i < __nbc; ++__i)
2424 __bucket_list_[__i] = nullptr;
Eric Fiselier40492ba2016-07-23 20:36:55 +00002425 __next_pointer __pp = __p1_.first().__ptr();
2426 __next_pointer __cp = __pp->__next_;
Howard Hinnant3e519522010-05-11 19:42:16 +00002427 if (__cp != nullptr)
2428 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00002429 size_type __chash = __constrain_hash(__cp->__hash(), __nbc);
Howard Hinnant3e519522010-05-11 19:42:16 +00002430 __bucket_list_[__chash] = __pp;
2431 size_type __phash = __chash;
2432 for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr;
2433 __cp = __pp->__next_)
2434 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00002435 __chash = __constrain_hash(__cp->__hash(), __nbc);
Howard Hinnant3e519522010-05-11 19:42:16 +00002436 if (__chash == __phash)
2437 __pp = __cp;
2438 else
2439 {
2440 if (__bucket_list_[__chash] == nullptr)
2441 {
2442 __bucket_list_[__chash] = __pp;
2443 __pp = __cp;
2444 __phash = __chash;
2445 }
2446 else
2447 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00002448 __next_pointer __np = __cp;
Howard Hinnant3e519522010-05-11 19:42:16 +00002449 for (; __np->__next_ != nullptr &&
Eric Fiselier40492ba2016-07-23 20:36:55 +00002450 key_eq()(__cp->__upcast()->__value_,
2451 __np->__next_->__upcast()->__value_);
Howard Hinnant3e519522010-05-11 19:42:16 +00002452 __np = __np->__next_)
2453 ;
2454 __pp->__next_ = __np->__next_;
2455 __np->__next_ = __bucket_list_[__chash]->__next_;
2456 __bucket_list_[__chash]->__next_ = __cp;
Howard Hinnantb3371f62010-08-22 00:02:43 +00002457
Howard Hinnant3e519522010-05-11 19:42:16 +00002458 }
2459 }
2460 }
2461 }
2462 }
2463}
2464
2465template <class _Tp, class _Hash, class _Equal, class _Alloc>
2466template <class _Key>
2467typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2468__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k)
2469{
2470 size_t __hash = hash_function()(__k);
2471 size_type __bc = bucket_count();
2472 if (__bc != 0)
2473 {
Howard Hinnant4cb38a82012-07-06 17:31:14 +00002474 size_t __chash = __constrain_hash(__hash, __bc);
Eric Fiselier40492ba2016-07-23 20:36:55 +00002475 __next_pointer __nd = __bucket_list_[__chash];
Howard Hinnant3e519522010-05-11 19:42:16 +00002476 if (__nd != nullptr)
2477 {
2478 for (__nd = __nd->__next_; __nd != nullptr &&
Eric Fiselier40492ba2016-07-23 20:36:55 +00002479 (__nd->__hash() == __hash
2480 || __constrain_hash(__nd->__hash(), __bc) == __chash);
Howard Hinnant3e519522010-05-11 19:42:16 +00002481 __nd = __nd->__next_)
2482 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00002483 if ((__nd->__hash() == __hash)
2484 && key_eq()(__nd->__upcast()->__value_, __k))
Louis Dionne31e82032020-10-02 15:02:52 -04002485#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00002486 return iterator(__nd, this);
2487#else
Howard Hinnant3e519522010-05-11 19:42:16 +00002488 return iterator(__nd);
Howard Hinnantb24c8022013-07-23 22:01:58 +00002489#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00002490 }
2491 }
2492 }
2493 return end();
2494}
2495
2496template <class _Tp, class _Hash, class _Equal, class _Alloc>
2497template <class _Key>
2498typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
2499__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const
2500{
2501 size_t __hash = hash_function()(__k);
2502 size_type __bc = bucket_count();
2503 if (__bc != 0)
2504 {
Howard Hinnant4cb38a82012-07-06 17:31:14 +00002505 size_t __chash = __constrain_hash(__hash, __bc);
Eric Fiselier40492ba2016-07-23 20:36:55 +00002506 __next_pointer __nd = __bucket_list_[__chash];
Howard Hinnant3e519522010-05-11 19:42:16 +00002507 if (__nd != nullptr)
2508 {
2509 for (__nd = __nd->__next_; __nd != nullptr &&
Eric Fiselier40492ba2016-07-23 20:36:55 +00002510 (__hash == __nd->__hash()
2511 || __constrain_hash(__nd->__hash(), __bc) == __chash);
Howard Hinnant3e519522010-05-11 19:42:16 +00002512 __nd = __nd->__next_)
2513 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00002514 if ((__nd->__hash() == __hash)
2515 && key_eq()(__nd->__upcast()->__value_, __k))
Louis Dionne31e82032020-10-02 15:02:52 -04002516#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00002517 return const_iterator(__nd, this);
2518#else
Howard Hinnant3e519522010-05-11 19:42:16 +00002519 return const_iterator(__nd);
Howard Hinnantb24c8022013-07-23 22:01:58 +00002520#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00002521 }
2522 }
Howard Hinnantb3371f62010-08-22 00:02:43 +00002523
Howard Hinnant3e519522010-05-11 19:42:16 +00002524 }
2525 return end();
2526}
2527
Eric Fiselierfcd02212016-02-11 11:59:44 +00002528#ifndef _LIBCPP_CXX03_LANG
Howard Hinnant3e519522010-05-11 19:42:16 +00002529
2530template <class _Tp, class _Hash, class _Equal, class _Alloc>
2531template <class ..._Args>
2532typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
2533__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args)
2534{
Eric Fiselierfcd02212016-02-11 11:59:44 +00002535 static_assert(!__is_hash_value_type<_Args...>::value,
2536 "Construct cannot be called with a hash value type");
Howard Hinnant3e519522010-05-11 19:42:16 +00002537 __node_allocator& __na = __node_alloc();
Howard Hinnantc003db12011-11-29 18:15:50 +00002538 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Eric Fiselierfcd02212016-02-11 11:59:44 +00002539 __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), _VSTD::forward<_Args>(__args)...);
Howard Hinnant3e519522010-05-11 19:42:16 +00002540 __h.get_deleter().__value_constructed = true;
2541 __h->__hash_ = hash_function()(__h->__value_);
2542 __h->__next_ = nullptr;
2543 return __h;
2544}
2545
2546template <class _Tp, class _Hash, class _Equal, class _Alloc>
Eric Fiselierfcd02212016-02-11 11:59:44 +00002547template <class _First, class ..._Rest>
Howard Hinnant3e519522010-05-11 19:42:16 +00002548typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
Eric Fiselierfcd02212016-02-11 11:59:44 +00002549__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(
2550 size_t __hash, _First&& __f, _Rest&& ...__rest)
Howard Hinnant3e519522010-05-11 19:42:16 +00002551{
Eric Fiselierfcd02212016-02-11 11:59:44 +00002552 static_assert(!__is_hash_value_type<_First, _Rest...>::value,
2553 "Construct cannot be called with a hash value type");
Howard Hinnant3e519522010-05-11 19:42:16 +00002554 __node_allocator& __na = __node_alloc();
Howard Hinnantc003db12011-11-29 18:15:50 +00002555 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Eric Fiselierfcd02212016-02-11 11:59:44 +00002556 __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_),
2557 _VSTD::forward<_First>(__f),
2558 _VSTD::forward<_Rest>(__rest)...);
Howard Hinnant3e519522010-05-11 19:42:16 +00002559 __h.get_deleter().__value_constructed = true;
2560 __h->__hash_ = __hash;
2561 __h->__next_ = nullptr;
Howard Hinnant179b1f82013-08-22 18:29:50 +00002562 return __h;
Howard Hinnant3e519522010-05-11 19:42:16 +00002563}
2564
Eric Fiselierfcd02212016-02-11 11:59:44 +00002565#else // _LIBCPP_CXX03_LANG
Howard Hinnant3e519522010-05-11 19:42:16 +00002566
2567template <class _Tp, class _Hash, class _Equal, class _Alloc>
2568typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
Eric Fiselierfcd02212016-02-11 11:59:44 +00002569__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const __container_value_type& __v)
Howard Hinnant3e519522010-05-11 19:42:16 +00002570{
2571 __node_allocator& __na = __node_alloc();
Howard Hinnantc003db12011-11-29 18:15:50 +00002572 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Eric Fiselierfcd02212016-02-11 11:59:44 +00002573 __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), __v);
Howard Hinnant3e519522010-05-11 19:42:16 +00002574 __h.get_deleter().__value_constructed = true;
2575 __h->__hash_ = hash_function()(__h->__value_);
2576 __h->__next_ = nullptr;
Louis Dionne8d4860a2020-07-30 09:42:23 -04002577 return __h;
Howard Hinnant3e519522010-05-11 19:42:16 +00002578}
2579
Howard Hinnant3e519522010-05-11 19:42:16 +00002580template <class _Tp, class _Hash, class _Equal, class _Alloc>
2581typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
Eric Fiselierfcd02212016-02-11 11:59:44 +00002582__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash,
2583 const __container_value_type& __v)
Howard Hinnant3e519522010-05-11 19:42:16 +00002584{
2585 __node_allocator& __na = __node_alloc();
Howard Hinnantc003db12011-11-29 18:15:50 +00002586 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Eric Fiselierfcd02212016-02-11 11:59:44 +00002587 __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), __v);
Howard Hinnant3e519522010-05-11 19:42:16 +00002588 __h.get_deleter().__value_constructed = true;
2589 __h->__hash_ = __hash;
2590 __h->__next_ = nullptr;
Louis Dionne8d4860a2020-07-30 09:42:23 -04002591 return __h;
Howard Hinnant3e519522010-05-11 19:42:16 +00002592}
2593
Eric Fiselierfcd02212016-02-11 11:59:44 +00002594#endif // _LIBCPP_CXX03_LANG
2595
Howard Hinnant3e519522010-05-11 19:42:16 +00002596template <class _Tp, class _Hash, class _Equal, class _Alloc>
2597typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2598__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p)
2599{
Eric Fiselier40492ba2016-07-23 20:36:55 +00002600 __next_pointer __np = __p.__node_;
Louis Dionne31e82032020-10-02 15:02:52 -04002601#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00002602 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
2603 "unordered container erase(iterator) called with an iterator not"
2604 " referring to this container");
2605 _LIBCPP_ASSERT(__p != end(),
2606 "unordered container erase(iterator) called with a non-dereferenceable iterator");
2607 iterator __r(__np, this);
2608#else
Howard Hinnant3e519522010-05-11 19:42:16 +00002609 iterator __r(__np);
Howard Hinnantb24c8022013-07-23 22:01:58 +00002610#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00002611 ++__r;
2612 remove(__p);
2613 return __r;
2614}
2615
2616template <class _Tp, class _Hash, class _Equal, class _Alloc>
2617typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2618__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first,
2619 const_iterator __last)
2620{
Louis Dionne31e82032020-10-02 15:02:52 -04002621#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00002622 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this,
2623 "unodered container::erase(iterator, iterator) called with an iterator not"
2624 " referring to this unodered container");
2625 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__last) == this,
2626 "unodered container::erase(iterator, iterator) called with an iterator not"
2627 " referring to this unodered container");
2628#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00002629 for (const_iterator __p = __first; __first != __last; __p = __first)
2630 {
2631 ++__first;
2632 erase(__p);
2633 }
Eric Fiselier40492ba2016-07-23 20:36:55 +00002634 __next_pointer __np = __last.__node_;
Louis Dionne31e82032020-10-02 15:02:52 -04002635#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00002636 return iterator (__np, this);
2637#else
Howard Hinnant3e519522010-05-11 19:42:16 +00002638 return iterator (__np);
Howard Hinnantb24c8022013-07-23 22:01:58 +00002639#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00002640}
2641
2642template <class _Tp, class _Hash, class _Equal, class _Alloc>
2643template <class _Key>
2644typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2645__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k)
2646{
2647 iterator __i = find(__k);
2648 if (__i == end())
2649 return 0;
2650 erase(__i);
2651 return 1;
2652}
2653
2654template <class _Tp, class _Hash, class _Equal, class _Alloc>
2655template <class _Key>
2656typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2657__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k)
2658{
2659 size_type __r = 0;
2660 iterator __i = find(__k);
2661 if (__i != end())
2662 {
2663 iterator __e = end();
2664 do
2665 {
2666 erase(__i++);
2667 ++__r;
2668 } while (__i != __e && key_eq()(*__i, __k));
2669 }
2670 return __r;
2671}
2672
2673template <class _Tp, class _Hash, class _Equal, class _Alloc>
2674typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
Howard Hinnant37141072011-06-04 18:54:24 +00002675__hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT
Howard Hinnant3e519522010-05-11 19:42:16 +00002676{
2677 // current node
Eric Fiselier40492ba2016-07-23 20:36:55 +00002678 __next_pointer __cn = __p.__node_;
Howard Hinnant3e519522010-05-11 19:42:16 +00002679 size_type __bc = bucket_count();
Eric Fiselier40492ba2016-07-23 20:36:55 +00002680 size_t __chash = __constrain_hash(__cn->__hash(), __bc);
Howard Hinnant3e519522010-05-11 19:42:16 +00002681 // find previous node
Eric Fiselier40492ba2016-07-23 20:36:55 +00002682 __next_pointer __pn = __bucket_list_[__chash];
Howard Hinnant3e519522010-05-11 19:42:16 +00002683 for (; __pn->__next_ != __cn; __pn = __pn->__next_)
2684 ;
2685 // Fix up __bucket_list_
2686 // if __pn is not in same bucket (before begin is not in same bucket) &&
2687 // if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
Eric Fiselier40492ba2016-07-23 20:36:55 +00002688 if (__pn == __p1_.first().__ptr()
2689 || __constrain_hash(__pn->__hash(), __bc) != __chash)
Howard Hinnant3e519522010-05-11 19:42:16 +00002690 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00002691 if (__cn->__next_ == nullptr
2692 || __constrain_hash(__cn->__next_->__hash(), __bc) != __chash)
Howard Hinnant3e519522010-05-11 19:42:16 +00002693 __bucket_list_[__chash] = nullptr;
2694 }
2695 // if __cn->__next_ is not in same bucket (nullptr is in same bucket)
2696 if (__cn->__next_ != nullptr)
2697 {
Eric Fiselier40492ba2016-07-23 20:36:55 +00002698 size_t __nhash = __constrain_hash(__cn->__next_->__hash(), __bc);
Howard Hinnant3e519522010-05-11 19:42:16 +00002699 if (__nhash != __chash)
2700 __bucket_list_[__nhash] = __pn;
2701 }
2702 // remove __cn
2703 __pn->__next_ = __cn->__next_;
2704 __cn->__next_ = nullptr;
2705 --size();
Louis Dionne31e82032020-10-02 15:02:52 -04002706#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00002707 __c_node* __c = __get_db()->__find_c_and_lock(this);
Eric Fiselier780b51d2016-12-28 05:53:01 +00002708 for (__i_node** __dp = __c->end_; __dp != __c->beg_; )
Howard Hinnantb24c8022013-07-23 22:01:58 +00002709 {
Eric Fiselier780b51d2016-12-28 05:53:01 +00002710 --__dp;
2711 iterator* __i = static_cast<iterator*>((*__dp)->__i_);
Howard Hinnantb24c8022013-07-23 22:01:58 +00002712 if (__i->__node_ == __cn)
2713 {
Eric Fiselier780b51d2016-12-28 05:53:01 +00002714 (*__dp)->__c_ = nullptr;
2715 if (--__c->end_ != __dp)
2716 memmove(__dp, __dp+1, (__c->end_ - __dp)*sizeof(__i_node*));
Howard Hinnantb24c8022013-07-23 22:01:58 +00002717 }
2718 }
2719 __get_db()->unlock();
2720#endif
Eric Fiselier40492ba2016-07-23 20:36:55 +00002721 return __node_holder(__cn->__upcast(), _Dp(__node_alloc(), true));
Howard Hinnant3e519522010-05-11 19:42:16 +00002722}
2723
2724template <class _Tp, class _Hash, class _Equal, class _Alloc>
2725template <class _Key>
Evgeniy Stepanov906c8722015-11-07 01:22:13 +00002726inline
Howard Hinnant3e519522010-05-11 19:42:16 +00002727typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2728__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const
2729{
2730 return static_cast<size_type>(find(__k) != end());
2731}
2732
2733template <class _Tp, class _Hash, class _Equal, class _Alloc>
2734template <class _Key>
2735typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2736__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const
2737{
2738 size_type __r = 0;
2739 const_iterator __i = find(__k);
2740 if (__i != end())
2741 {
2742 const_iterator __e = end();
2743 do
2744 {
2745 ++__i;
2746 ++__r;
2747 } while (__i != __e && key_eq()(*__i, __k));
2748 }
2749 return __r;
2750}
2751
2752template <class _Tp, class _Hash, class _Equal, class _Alloc>
2753template <class _Key>
2754pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
2755 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
2756__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
2757 const _Key& __k)
2758{
2759 iterator __i = find(__k);
2760 iterator __j = __i;
2761 if (__i != end())
2762 ++__j;
2763 return pair<iterator, iterator>(__i, __j);
2764}
2765
2766template <class _Tp, class _Hash, class _Equal, class _Alloc>
2767template <class _Key>
2768pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
2769 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
2770__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
2771 const _Key& __k) const
2772{
2773 const_iterator __i = find(__k);
2774 const_iterator __j = __i;
2775 if (__i != end())
2776 ++__j;
2777 return pair<const_iterator, const_iterator>(__i, __j);
2778}
2779
2780template <class _Tp, class _Hash, class _Equal, class _Alloc>
2781template <class _Key>
2782pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
2783 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
2784__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
2785 const _Key& __k)
2786{
2787 iterator __i = find(__k);
2788 iterator __j = __i;
2789 if (__i != end())
2790 {
2791 iterator __e = end();
2792 do
2793 {
2794 ++__j;
2795 } while (__j != __e && key_eq()(*__j, __k));
2796 }
2797 return pair<iterator, iterator>(__i, __j);
2798}
2799
2800template <class _Tp, class _Hash, class _Equal, class _Alloc>
2801template <class _Key>
2802pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
2803 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
2804__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
2805 const _Key& __k) const
2806{
2807 const_iterator __i = find(__k);
2808 const_iterator __j = __i;
2809 if (__i != end())
2810 {
2811 const_iterator __e = end();
2812 do
2813 {
2814 ++__j;
2815 } while (__j != __e && key_eq()(*__j, __k));
2816 }
2817 return pair<const_iterator, const_iterator>(__i, __j);
2818}
2819
2820template <class _Tp, class _Hash, class _Equal, class _Alloc>
2821void
2822__hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
Eric Fiselier87a82492015-07-18 20:40:46 +00002823#if _LIBCPP_STD_VER <= 11
Eric Fiselier61b302f2019-03-18 21:50:12 +00002824 _NOEXCEPT_(
Marshall Clowe3fbe142015-07-13 20:04:56 +00002825 __is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value
Marshall Clowe3fbe142015-07-13 20:04:56 +00002826 && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value
2827 || __is_nothrow_swappable<__pointer_allocator>::value)
2828 && (!__node_traits::propagate_on_container_swap::value
2829 || __is_nothrow_swappable<__node_allocator>::value)
Marshall Clowe3fbe142015-07-13 20:04:56 +00002830 )
Eric Fiselier87a82492015-07-18 20:40:46 +00002831#else
Eric Fiselier61b302f2019-03-18 21:50:12 +00002832 _NOEXCEPT_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value)
Eric Fiselier87a82492015-07-18 20:40:46 +00002833#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00002834{
Eric Fiselier780b51d2016-12-28 05:53:01 +00002835 _LIBCPP_ASSERT(__node_traits::propagate_on_container_swap::value ||
2836 this->__node_alloc() == __u.__node_alloc(),
2837 "list::swap: Either propagate_on_container_swap must be true"
2838 " or the allocators must compare equal");
Howard Hinnant3e519522010-05-11 19:42:16 +00002839 {
2840 __node_pointer_pointer __npp = __bucket_list_.release();
2841 __bucket_list_.reset(__u.__bucket_list_.release());
2842 __u.__bucket_list_.reset(__npp);
2843 }
Howard Hinnantce48a112011-06-30 21:18:19 +00002844 _VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
Marshall Clowe3fbe142015-07-13 20:04:56 +00002845 __swap_allocator(__bucket_list_.get_deleter().__alloc(),
Howard Hinnant3e519522010-05-11 19:42:16 +00002846 __u.__bucket_list_.get_deleter().__alloc());
Marshall Clowe3fbe142015-07-13 20:04:56 +00002847 __swap_allocator(__node_alloc(), __u.__node_alloc());
Howard Hinnantce48a112011-06-30 21:18:19 +00002848 _VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
Howard Hinnant3e519522010-05-11 19:42:16 +00002849 __p2_.swap(__u.__p2_);
2850 __p3_.swap(__u.__p3_);
2851 if (size() > 0)
Eric Fiselier40492ba2016-07-23 20:36:55 +00002852 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash(), bucket_count())] =
2853 __p1_.first().__ptr();
Howard Hinnant3e519522010-05-11 19:42:16 +00002854 if (__u.size() > 0)
Eric Fiselier40492ba2016-07-23 20:36:55 +00002855 __u.__bucket_list_[__constrain_hash(__u.__p1_.first().__next_->__hash(), __u.bucket_count())] =
2856 __u.__p1_.first().__ptr();
Louis Dionne31e82032020-10-02 15:02:52 -04002857#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00002858 __get_db()->swap(this, &__u);
2859#endif
Howard Hinnant3e519522010-05-11 19:42:16 +00002860}
2861
2862template <class _Tp, class _Hash, class _Equal, class _Alloc>
2863typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2864__hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const
2865{
Howard Hinnante5c13de2013-07-29 19:05:47 +00002866 _LIBCPP_ASSERT(__n < bucket_count(),
2867 "unordered container::bucket_size(n) called with n >= bucket_count()");
Eric Fiselier40492ba2016-07-23 20:36:55 +00002868 __next_pointer __np = __bucket_list_[__n];
Howard Hinnant3e519522010-05-11 19:42:16 +00002869 size_type __bc = bucket_count();
2870 size_type __r = 0;
2871 if (__np != nullptr)
2872 {
2873 for (__np = __np->__next_; __np != nullptr &&
Eric Fiselier40492ba2016-07-23 20:36:55 +00002874 __constrain_hash(__np->__hash(), __bc) == __n;
Howard Hinnant3e519522010-05-11 19:42:16 +00002875 __np = __np->__next_, ++__r)
2876 ;
2877 }
2878 return __r;
2879}
2880
Howard Hinnant37141072011-06-04 18:54:24 +00002881template <class _Tp, class _Hash, class _Equal, class _Alloc>
2882inline _LIBCPP_INLINE_VISIBILITY
2883void
2884swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x,
2885 __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y)
2886 _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
2887{
2888 __x.swap(__y);
2889}
2890
Louis Dionne31e82032020-10-02 15:02:52 -04002891#if _LIBCPP_DEBUG_LEVEL == 2
Howard Hinnantb24c8022013-07-23 22:01:58 +00002892
2893template <class _Tp, class _Hash, class _Equal, class _Alloc>
2894bool
2895__hash_table<_Tp, _Hash, _Equal, _Alloc>::__dereferenceable(const const_iterator* __i) const
2896{
2897 return __i->__node_ != nullptr;
2898}
2899
2900template <class _Tp, class _Hash, class _Equal, class _Alloc>
2901bool
2902__hash_table<_Tp, _Hash, _Equal, _Alloc>::__decrementable(const const_iterator*) const
2903{
2904 return false;
2905}
2906
2907template <class _Tp, class _Hash, class _Equal, class _Alloc>
2908bool
2909__hash_table<_Tp, _Hash, _Equal, _Alloc>::__addable(const const_iterator*, ptrdiff_t) const
2910{
2911 return false;
2912}
2913
2914template <class _Tp, class _Hash, class _Equal, class _Alloc>
2915bool
2916__hash_table<_Tp, _Hash, _Equal, _Alloc>::__subscriptable(const const_iterator*, ptrdiff_t) const
2917{
2918 return false;
2919}
2920
Louis Dionne31e82032020-10-02 15:02:52 -04002921#endif // _LIBCPP_DEBUG_LEVEL == 2
Eric Fiseliera016efb2017-05-31 22:07:49 +00002922
Howard Hinnant3e519522010-05-11 19:42:16 +00002923_LIBCPP_END_NAMESPACE_STD
2924
Eric Fiseliera016efb2017-05-31 22:07:49 +00002925_LIBCPP_POP_MACROS
2926
Howard Hinnant3e519522010-05-11 19:42:16 +00002927#endif // _LIBCPP__HASH_TABLE