blob: b358d94873a3d9ff1388b68f6bfe2de3c12f6e36 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00006// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00008//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP__HASH_TABLE
12#define _LIBCPP__HASH_TABLE
13
14#include <__config>
15#include <initializer_list>
16#include <memory>
17#include <iterator>
18#include <algorithm>
19#include <cmath>
Eric Fiselier774c7c52016-02-10 20:46:23 +000020#include <utility>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000021
Howard Hinnant66c6f972011-11-29 16:45:27 +000022#include <__undef_min_max>
Saleem Abdulrasoolf1b30c42015-02-13 22:15:32 +000023#include <__undef___deallocate>
Howard Hinnant66c6f972011-11-29 16:45:27 +000024
Eric Fiselierb9536102014-08-10 23:53:08 +000025#include <__debug>
Howard Hinnant8b00e6c2013-08-02 00:26:35 +000026
Howard Hinnant08e17472011-10-17 20:05:10 +000027#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000028#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:10 +000029#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000030
31_LIBCPP_BEGIN_NAMESPACE_STD
32
Eric Fiselier2960ae22016-02-11 11:59:44 +000033
34#ifndef _LIBCPP_CXX03_LANG
35template <class _Key, class _Tp>
36union __hash_value_type;
37#else
38template <class _Key, class _Tp>
39struct __hash_value_type;
40#endif
41
42#ifndef _LIBCPP_CXX03_LANG
43template <class _Tp>
44struct __is_hash_value_type_imp : false_type {};
45
46template <class _Key, class _Value>
47struct __is_hash_value_type_imp<__hash_value_type<_Key, _Value>> : true_type {};
48
49template <class ..._Args>
50struct __is_hash_value_type : false_type {};
51
52template <class _One>
53struct __is_hash_value_type<_One> : __is_hash_value_type_imp<typename __uncvref<_One>::type> {};
54#endif
55
Howard Hinnant83eade62013-03-06 23:30:19 +000056_LIBCPP_FUNC_VIS
Howard Hinnant2b1b2d42011-06-14 19:58:17 +000057size_t __next_prime(size_t __n);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000058
59template <class _NodePtr>
60struct __hash_node_base
61{
62 typedef __hash_node_base __first_node;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000063
Howard Hinnantdf85e572011-02-27 18:02:02 +000064 _NodePtr __next_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000065
Howard Hinnant5f2f14c2011-06-04 18:54:24 +000066 _LIBCPP_INLINE_VISIBILITY __hash_node_base() _NOEXCEPT : __next_(nullptr) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000067};
68
69template <class _Tp, class _VoidPtr>
70struct __hash_node
71 : public __hash_node_base
72 <
Eric Fiselier5cf84e02015-12-30 21:52:00 +000073 typename __rebind_pointer<_VoidPtr, __hash_node<_Tp, _VoidPtr> >::type
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000074 >
75{
Eric Fiselier774c7c52016-02-10 20:46:23 +000076 typedef _Tp __node_value_type;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000077
78 size_t __hash_;
Eric Fiselier774c7c52016-02-10 20:46:23 +000079 __node_value_type __value_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000080};
81
Howard Hinnant7a445152012-07-06 17:31:14 +000082inline _LIBCPP_INLINE_VISIBILITY
83bool
Eric Fiselier57947ca2015-02-02 21:31:48 +000084__is_hash_power2(size_t __bc)
Howard Hinnant7a445152012-07-06 17:31:14 +000085{
86 return __bc > 2 && !(__bc & (__bc - 1));
87}
88
89inline _LIBCPP_INLINE_VISIBILITY
90size_t
91__constrain_hash(size_t __h, size_t __bc)
92{
93 return !(__bc & (__bc - 1)) ? __h & (__bc - 1) : __h % __bc;
94}
95
96inline _LIBCPP_INLINE_VISIBILITY
97size_t
Eric Fiselier57947ca2015-02-02 21:31:48 +000098__next_hash_pow2(size_t __n)
Howard Hinnant7a445152012-07-06 17:31:14 +000099{
100 return size_t(1) << (std::numeric_limits<size_t>::digits - __clz(__n-1));
101}
102
Howard Hinnant2b1b2d42011-06-14 19:58:17 +0000103template <class _Tp, class _Hash, class _Equal, class _Alloc> class __hash_table;
Eric Fiselier774c7c52016-02-10 20:46:23 +0000104
105template <class _NodePtr> class _LIBCPP_TYPE_VIS_ONLY __hash_iterator;
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000106template <class _ConstNodePtr> class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator;
Eric Fiselier774c7c52016-02-10 20:46:23 +0000107template <class _NodePtr> class _LIBCPP_TYPE_VIS_ONLY __hash_local_iterator;
108template <class _ConstNodePtr> class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator;
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000109template <class _HashIterator> class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator;
110template <class _HashIterator> class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000111
Eric Fiselier774c7c52016-02-10 20:46:23 +0000112template <class _Tp>
113struct __key_value_types {
114 static_assert(!is_reference<_Tp>::value && !is_const<_Tp>::value, "");
115 typedef _Tp key_type;
116 typedef _Tp __node_value_type;
117 typedef _Tp __container_value_type;
118 static const bool __is_map = false;
Eric Fiselier2960ae22016-02-11 11:59:44 +0000119
120 _LIBCPP_INLINE_VISIBILITY
121 static key_type const& __get_key(_Tp const& __v) {
122 return __v;
123 }
124 _LIBCPP_INLINE_VISIBILITY
125 static __container_value_type const& __get_value(__node_value_type const& __v) {
126 return __v;
127 }
128 _LIBCPP_INLINE_VISIBILITY
129 static __container_value_type* __get_ptr(__node_value_type& __n) {
130 return _VSTD::addressof(__n);
131 }
132#ifndef _LIBCPP_CXX03_LANG
133 _LIBCPP_INLINE_VISIBILITY
134 static __container_value_type&& __move(__node_value_type& __v) {
135 return _VSTD::move(__v);
136 }
137#endif
Eric Fiselier774c7c52016-02-10 20:46:23 +0000138};
139
140template <class _Key, class _Tp>
141struct __key_value_types<__hash_value_type<_Key, _Tp> > {
142 typedef _Key key_type;
143 typedef _Tp mapped_type;
144 typedef __hash_value_type<_Key, _Tp> __node_value_type;
145 typedef pair<const _Key, _Tp> __container_value_type;
Eric Fiselier2960ae22016-02-11 11:59:44 +0000146 typedef pair<_Key, _Tp> __nc_value_type;
Eric Fiselier774c7c52016-02-10 20:46:23 +0000147 typedef __container_value_type __map_value_type;
148 static const bool __is_map = true;
Eric Fiselier2960ae22016-02-11 11:59:44 +0000149
150 _LIBCPP_INLINE_VISIBILITY
151 static key_type const& __get_key(__container_value_type const& __v) {
152 return __v.first;
153 }
154
155 template <class _Up>
156 _LIBCPP_INLINE_VISIBILITY
157 static typename enable_if<__is_same_uncvref<_Up, __node_value_type>::value,
158 __container_value_type const&>::type
159 __get_value(_Up& __t) {
160 return __t.__cc;
161 }
162
163 template <class _Up>
164 _LIBCPP_INLINE_VISIBILITY
165 static typename enable_if<__is_same_uncvref<_Up, __container_value_type>::value,
166 __container_value_type const&>::type
167 __get_value(_Up& __t) {
168 return __t;
169 }
170
171 _LIBCPP_INLINE_VISIBILITY
172 static __container_value_type* __get_ptr(__node_value_type& __n) {
173 return _VSTD::addressof(__n.__cc);
174 }
175#ifndef _LIBCPP_CXX03_LANG
176 _LIBCPP_INLINE_VISIBILITY
177 static __nc_value_type&& __move(__node_value_type& __v) {
178 return _VSTD::move(__v.__nc);
179 }
180#endif
181
Eric Fiselier774c7c52016-02-10 20:46:23 +0000182};
183
184template <class _Tp, class _AllocPtr, class _KVTypes = __key_value_types<_Tp>,
185 bool = _KVTypes::__is_map>
186struct __map_pointer_types {};
187
188template <class _Tp, class _AllocPtr, class _KVTypes>
189struct __map_pointer_types<_Tp, _AllocPtr, _KVTypes, true> {
190 typedef typename _KVTypes::__map_value_type _Mv;
191 typedef typename __rebind_pointer<_AllocPtr, _Mv>::type
192 __map_value_type_pointer;
193 typedef typename __rebind_pointer<_AllocPtr, const _Mv>::type
194 __const_map_value_type_pointer;
195};
196
197template <class _NodePtr, class _NodeT = typename pointer_traits<_NodePtr>::element_type>
198struct __hash_node_types;
199
200template <class _NodePtr, class _Tp, class _VoidPtr>
201struct __hash_node_types<_NodePtr, __hash_node<_Tp, _VoidPtr> >
202 : public __key_value_types<_Tp>, __map_pointer_types<_Tp, _VoidPtr>
203
204{
205 typedef __key_value_types<_Tp> __base;
206
207public:
208 typedef ptrdiff_t difference_type;
209 typedef size_t size_type;
210
211 typedef typename __rebind_pointer<_NodePtr, void>::type __void_pointer;
212
213 typedef typename pointer_traits<_NodePtr>::element_type __node_type;
214 typedef _NodePtr __node_pointer;
215
216 typedef __hash_node_base<__node_pointer> __node_base_type;
217 typedef typename __rebind_pointer<_NodePtr, __node_base_type>::type
218 __node_base_pointer;
219
220 typedef _Tp __node_value_type;
221 typedef typename __rebind_pointer<_VoidPtr, __node_value_type>::type
222 __node_value_type_pointer;
223 typedef typename __rebind_pointer<_VoidPtr, const __node_value_type>::type
224 __const_node_value_type_pointer;
225private:
226 static_assert(!is_const<__node_type>::value,
227 "_NodePtr should never be a pointer to const");
228 static_assert((is_same<typename pointer_traits<_VoidPtr>::element_type, void>::value),
229 "_VoidPtr does not point to unqualified void type");
230 static_assert((is_same<typename __rebind_pointer<_VoidPtr, __node_type>::type,
231 _NodePtr>::value), "_VoidPtr does not rebind to _NodePtr.");
232};
233
234
235
236template <class _HashIterator>
237struct __hash_node_types_from_iterator;
238template <class _NodePtr>
239struct __hash_node_types_from_iterator<__hash_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
240template <class _NodePtr>
241struct __hash_node_types_from_iterator<__hash_const_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
242template <class _NodePtr>
243struct __hash_node_types_from_iterator<__hash_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
244template <class _NodePtr>
245struct __hash_node_types_from_iterator<__hash_const_local_iterator<_NodePtr> > : __hash_node_types<_NodePtr> {};
246
247
248template <class _NodeValueTp, class _VoidPtr>
249struct __make_hash_node_types {
250 typedef __hash_node<_NodeValueTp, _VoidPtr> _NodeTp;
251 typedef typename __rebind_pointer<_VoidPtr, _NodeTp>::type _NodePtr;
252 typedef __hash_node_types<_NodePtr> type;
253};
254
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000255template <class _NodePtr>
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000256class _LIBCPP_TYPE_VIS_ONLY __hash_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000257{
Eric Fiselier774c7c52016-02-10 20:46:23 +0000258 typedef __hash_node_types<_NodePtr> _NodeTypes;
259 typedef _NodePtr __node_pointer;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000260
261 __node_pointer __node_;
262
263public:
Eric Fiselier774c7c52016-02-10 20:46:23 +0000264 typedef forward_iterator_tag iterator_category;
265 typedef typename _NodeTypes::__node_value_type value_type;
266 typedef typename _NodeTypes::difference_type difference_type;
267 typedef value_type& reference;
268 typedef typename _NodeTypes::__node_value_type_pointer pointer;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000269
Howard Hinnant39213642013-07-23 22:01:58 +0000270 _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT
Marshall Clow193ef032013-08-07 21:30:44 +0000271#if _LIBCPP_STD_VER > 11
272 : __node_(nullptr)
273#endif
Howard Hinnant39213642013-07-23 22:01:58 +0000274 {
275#if _LIBCPP_DEBUG_LEVEL >= 2
276 __get_db()->__insert_i(this);
277#endif
278 }
279
280#if _LIBCPP_DEBUG_LEVEL >= 2
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000281
Howard Hinnant99acc502010-09-21 17:32:39 +0000282 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58 +0000283 __hash_iterator(const __hash_iterator& __i)
284 : __node_(__i.__node_)
285 {
286 __get_db()->__iterator_copy(this, &__i);
287 }
288
Howard Hinnant99acc502010-09-21 17:32:39 +0000289 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58 +0000290 ~__hash_iterator()
291 {
292 __get_db()->__erase_i(this);
293 }
294
295 _LIBCPP_INLINE_VISIBILITY
296 __hash_iterator& operator=(const __hash_iterator& __i)
297 {
298 if (this != &__i)
299 {
300 __get_db()->__iterator_copy(this, &__i);
301 __node_ = __i.__node_;
302 }
303 return *this;
304 }
305
306#endif // _LIBCPP_DEBUG_LEVEL >= 2
307
308 _LIBCPP_INLINE_VISIBILITY
309 reference operator*() const
310 {
311#if _LIBCPP_DEBUG_LEVEL >= 2
312 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
313 "Attempted to dereference a non-dereferenceable unordered container iterator");
314#endif
315 return __node_->__value_;
316 }
317 _LIBCPP_INLINE_VISIBILITY
318 pointer operator->() const
319 {
320#if _LIBCPP_DEBUG_LEVEL >= 2
321 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
322 "Attempted to dereference a non-dereferenceable unordered container iterator");
323#endif
324 return pointer_traits<pointer>::pointer_to(__node_->__value_);
325 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000326
Howard Hinnant99acc502010-09-21 17:32:39 +0000327 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000328 __hash_iterator& operator++()
329 {
Howard Hinnant39213642013-07-23 22:01:58 +0000330#if _LIBCPP_DEBUG_LEVEL >= 2
331 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
332 "Attempted to increment non-incrementable unordered container iterator");
333#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000334 __node_ = __node_->__next_;
335 return *this;
336 }
337
Howard Hinnant99acc502010-09-21 17:32:39 +0000338 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000339 __hash_iterator operator++(int)
340 {
341 __hash_iterator __t(*this);
342 ++(*this);
343 return __t;
344 }
345
Howard Hinnant99acc502010-09-21 17:32:39 +0000346 friend _LIBCPP_INLINE_VISIBILITY
347 bool operator==(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58 +0000348 {
Howard Hinnant39213642013-07-23 22:01:58 +0000349 return __x.__node_ == __y.__node_;
350 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000351 friend _LIBCPP_INLINE_VISIBILITY
352 bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58 +0000353 {return !(__x == __y);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000354
355private:
Howard Hinnant39213642013-07-23 22:01:58 +0000356#if _LIBCPP_DEBUG_LEVEL >= 2
357 _LIBCPP_INLINE_VISIBILITY
358 __hash_iterator(__node_pointer __node, const void* __c) _NOEXCEPT
359 : __node_(__node)
360 {
361 __get_db()->__insert_ic(this, __c);
362 }
363#else
Howard Hinnant99acc502010-09-21 17:32:39 +0000364 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000365 __hash_iterator(__node_pointer __node) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000366 : __node_(__node)
367 {}
Howard Hinnant39213642013-07-23 22:01:58 +0000368#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000369
370 template <class, class, class, class> friend class __hash_table;
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000371 template <class> friend class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator;
372 template <class> friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator;
373 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY unordered_map;
374 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000375};
376
Eric Fiselier774c7c52016-02-10 20:46:23 +0000377template <class _NodePtr>
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000378class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000379{
Eric Fiselier774c7c52016-02-10 20:46:23 +0000380 static_assert(!is_const<typename pointer_traits<_NodePtr>::element_type>::value, "");
381 typedef __hash_node_types<_NodePtr> _NodeTypes;
382 typedef _NodePtr __node_pointer;
383 typedef __hash_iterator<_NodePtr> __non_const_iterator;
384 __node_pointer __node_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000385
386public:
Eric Fiselier774c7c52016-02-10 20:46:23 +0000387 typedef forward_iterator_tag iterator_category;
388 typedef typename _NodeTypes::__node_value_type value_type;
389 typedef typename _NodeTypes::difference_type difference_type;
390 typedef const value_type& reference;
391 typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
392
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000393
Howard Hinnant39213642013-07-23 22:01:58 +0000394 _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT
Marshall Clow193ef032013-08-07 21:30:44 +0000395#if _LIBCPP_STD_VER > 11
396 : __node_(nullptr)
397#endif
Howard Hinnant39213642013-07-23 22:01:58 +0000398 {
399#if _LIBCPP_DEBUG_LEVEL >= 2
400 __get_db()->__insert_i(this);
401#endif
402 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000403 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000404 __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000405 : __node_(__x.__node_)
Howard Hinnant39213642013-07-23 22:01:58 +0000406 {
407#if _LIBCPP_DEBUG_LEVEL >= 2
408 __get_db()->__iterator_copy(this, &__x);
409#endif
410 }
411
412#if _LIBCPP_DEBUG_LEVEL >= 2
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000413
Howard Hinnant99acc502010-09-21 17:32:39 +0000414 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58 +0000415 __hash_const_iterator(const __hash_const_iterator& __i)
416 : __node_(__i.__node_)
417 {
418 __get_db()->__iterator_copy(this, &__i);
419 }
420
Howard Hinnant99acc502010-09-21 17:32:39 +0000421 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58 +0000422 ~__hash_const_iterator()
423 {
424 __get_db()->__erase_i(this);
425 }
426
427 _LIBCPP_INLINE_VISIBILITY
428 __hash_const_iterator& operator=(const __hash_const_iterator& __i)
429 {
430 if (this != &__i)
431 {
432 __get_db()->__iterator_copy(this, &__i);
433 __node_ = __i.__node_;
434 }
435 return *this;
436 }
437
438#endif // _LIBCPP_DEBUG_LEVEL >= 2
439
440 _LIBCPP_INLINE_VISIBILITY
441 reference operator*() const
442 {
443#if _LIBCPP_DEBUG_LEVEL >= 2
444 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
445 "Attempted to dereference a non-dereferenceable unordered container const_iterator");
446#endif
447 return __node_->__value_;
448 }
449 _LIBCPP_INLINE_VISIBILITY
450 pointer operator->() const
451 {
452#if _LIBCPP_DEBUG_LEVEL >= 2
453 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
454 "Attempted to dereference a non-dereferenceable unordered container const_iterator");
455#endif
456 return pointer_traits<pointer>::pointer_to(__node_->__value_);
457 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000458
Howard Hinnant99acc502010-09-21 17:32:39 +0000459 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000460 __hash_const_iterator& operator++()
461 {
Howard Hinnant39213642013-07-23 22:01:58 +0000462#if _LIBCPP_DEBUG_LEVEL >= 2
463 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
464 "Attempted to increment non-incrementable unordered container const_iterator");
465#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000466 __node_ = __node_->__next_;
467 return *this;
468 }
469
Howard Hinnant99acc502010-09-21 17:32:39 +0000470 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000471 __hash_const_iterator operator++(int)
472 {
473 __hash_const_iterator __t(*this);
474 ++(*this);
475 return __t;
476 }
477
Howard Hinnant99acc502010-09-21 17:32:39 +0000478 friend _LIBCPP_INLINE_VISIBILITY
479 bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58 +0000480 {
Howard Hinnant39213642013-07-23 22:01:58 +0000481 return __x.__node_ == __y.__node_;
482 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000483 friend _LIBCPP_INLINE_VISIBILITY
484 bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58 +0000485 {return !(__x == __y);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000486
487private:
Howard Hinnant39213642013-07-23 22:01:58 +0000488#if _LIBCPP_DEBUG_LEVEL >= 2
489 _LIBCPP_INLINE_VISIBILITY
490 __hash_const_iterator(__node_pointer __node, const void* __c) _NOEXCEPT
491 : __node_(__node)
492 {
493 __get_db()->__insert_ic(this, __c);
494 }
495#else
Howard Hinnant99acc502010-09-21 17:32:39 +0000496 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000497 __hash_const_iterator(__node_pointer __node) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000498 : __node_(__node)
499 {}
Howard Hinnant39213642013-07-23 22:01:58 +0000500#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000501
502 template <class, class, class, class> friend class __hash_table;
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000503 template <class> friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator;
504 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY unordered_map;
505 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000506};
507
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000508template <class _NodePtr>
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000509class _LIBCPP_TYPE_VIS_ONLY __hash_local_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000510{
Eric Fiselier774c7c52016-02-10 20:46:23 +0000511 typedef __hash_node_types<_NodePtr> _NodeTypes;
512 typedef _NodePtr __node_pointer;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000513
514 __node_pointer __node_;
515 size_t __bucket_;
516 size_t __bucket_count_;
517
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000518public:
519 typedef forward_iterator_tag iterator_category;
Eric Fiselier774c7c52016-02-10 20:46:23 +0000520 typedef typename _NodeTypes::__node_value_type value_type;
521 typedef typename _NodeTypes::difference_type difference_type;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000522 typedef value_type& reference;
Eric Fiselier774c7c52016-02-10 20:46:23 +0000523 typedef typename _NodeTypes::__node_value_type_pointer pointer;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000524
Howard Hinnant39213642013-07-23 22:01:58 +0000525 _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT
526 {
527#if _LIBCPP_DEBUG_LEVEL >= 2
528 __get_db()->__insert_i(this);
529#endif
530 }
531
532#if _LIBCPP_DEBUG_LEVEL >= 2
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000533
Howard Hinnant99acc502010-09-21 17:32:39 +0000534 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58 +0000535 __hash_local_iterator(const __hash_local_iterator& __i)
536 : __node_(__i.__node_),
537 __bucket_(__i.__bucket_),
538 __bucket_count_(__i.__bucket_count_)
539 {
540 __get_db()->__iterator_copy(this, &__i);
541 }
542
Howard Hinnant99acc502010-09-21 17:32:39 +0000543 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58 +0000544 ~__hash_local_iterator()
545 {
546 __get_db()->__erase_i(this);
547 }
548
549 _LIBCPP_INLINE_VISIBILITY
550 __hash_local_iterator& operator=(const __hash_local_iterator& __i)
551 {
552 if (this != &__i)
553 {
554 __get_db()->__iterator_copy(this, &__i);
555 __node_ = __i.__node_;
556 __bucket_ = __i.__bucket_;
557 __bucket_count_ = __i.__bucket_count_;
558 }
559 return *this;
560 }
561
562#endif // _LIBCPP_DEBUG_LEVEL >= 2
563
564 _LIBCPP_INLINE_VISIBILITY
565 reference operator*() const
566 {
567#if _LIBCPP_DEBUG_LEVEL >= 2
568 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
569 "Attempted to dereference a non-dereferenceable unordered container local_iterator");
570#endif
571 return __node_->__value_;
572 }
573 _LIBCPP_INLINE_VISIBILITY
574 pointer operator->() const
575 {
576#if _LIBCPP_DEBUG_LEVEL >= 2
577 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
578 "Attempted to dereference a non-dereferenceable unordered container local_iterator");
579#endif
580 return pointer_traits<pointer>::pointer_to(__node_->__value_);
581 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000582
Howard Hinnant99acc502010-09-21 17:32:39 +0000583 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000584 __hash_local_iterator& operator++()
585 {
Howard Hinnant39213642013-07-23 22:01:58 +0000586#if _LIBCPP_DEBUG_LEVEL >= 2
587 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
588 "Attempted to increment non-incrementable unordered container local_iterator");
589#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000590 __node_ = __node_->__next_;
Howard Hinnant7a445152012-07-06 17:31:14 +0000591 if (__node_ != nullptr && __constrain_hash(__node_->__hash_, __bucket_count_) != __bucket_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000592 __node_ = nullptr;
593 return *this;
594 }
595
Howard Hinnant99acc502010-09-21 17:32:39 +0000596 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000597 __hash_local_iterator operator++(int)
598 {
599 __hash_local_iterator __t(*this);
600 ++(*this);
601 return __t;
602 }
603
Howard Hinnant99acc502010-09-21 17:32:39 +0000604 friend _LIBCPP_INLINE_VISIBILITY
605 bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58 +0000606 {
Howard Hinnant39213642013-07-23 22:01:58 +0000607 return __x.__node_ == __y.__node_;
608 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000609 friend _LIBCPP_INLINE_VISIBILITY
610 bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58 +0000611 {return !(__x == __y);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000612
613private:
Howard Hinnant39213642013-07-23 22:01:58 +0000614#if _LIBCPP_DEBUG_LEVEL >= 2
615 _LIBCPP_INLINE_VISIBILITY
616 __hash_local_iterator(__node_pointer __node, size_t __bucket,
617 size_t __bucket_count, const void* __c) _NOEXCEPT
618 : __node_(__node),
619 __bucket_(__bucket),
620 __bucket_count_(__bucket_count)
621 {
622 __get_db()->__insert_ic(this, __c);
623 if (__node_ != nullptr)
624 __node_ = __node_->__next_;
625 }
626#else
Howard Hinnant99acc502010-09-21 17:32:39 +0000627 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000628 __hash_local_iterator(__node_pointer __node, size_t __bucket,
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000629 size_t __bucket_count) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000630 : __node_(__node),
631 __bucket_(__bucket),
632 __bucket_count_(__bucket_count)
633 {
634 if (__node_ != nullptr)
635 __node_ = __node_->__next_;
636 }
Howard Hinnant39213642013-07-23 22:01:58 +0000637#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000638 template <class, class, class, class> friend class __hash_table;
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000639 template <class> friend class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator;
640 template <class> friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000641};
642
643template <class _ConstNodePtr>
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000644class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000645{
Eric Fiselier774c7c52016-02-10 20:46:23 +0000646 typedef __hash_node_types<_ConstNodePtr> _NodeTypes;
647 typedef _ConstNodePtr __node_pointer;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000648
649 __node_pointer __node_;
650 size_t __bucket_;
651 size_t __bucket_count_;
652
653 typedef pointer_traits<__node_pointer> __pointer_traits;
654 typedef typename __pointer_traits::element_type __node;
655 typedef typename remove_const<__node>::type __non_const_node;
Eric Fiselier5cf84e02015-12-30 21:52:00 +0000656 typedef typename __rebind_pointer<__node_pointer, __non_const_node>::type
657 __non_const_node_pointer;
658
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000659 typedef __hash_local_iterator<__non_const_node_pointer>
660 __non_const_iterator;
661public:
Eric Fiselier774c7c52016-02-10 20:46:23 +0000662 typedef forward_iterator_tag iterator_category;
663 typedef typename _NodeTypes::__node_value_type value_type;
664 typedef typename _NodeTypes::difference_type difference_type;
665 typedef const value_type& reference;
666 typedef typename _NodeTypes::__const_node_value_type_pointer pointer;
Eric Fiselier5cf84e02015-12-30 21:52:00 +0000667
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000668
Howard Hinnant39213642013-07-23 22:01:58 +0000669 _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT
670 {
671#if _LIBCPP_DEBUG_LEVEL >= 2
672 __get_db()->__insert_i(this);
673#endif
674 }
675
Howard Hinnant99acc502010-09-21 17:32:39 +0000676 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000677 __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000678 : __node_(__x.__node_),
679 __bucket_(__x.__bucket_),
680 __bucket_count_(__x.__bucket_count_)
Howard Hinnant39213642013-07-23 22:01:58 +0000681 {
682#if _LIBCPP_DEBUG_LEVEL >= 2
683 __get_db()->__iterator_copy(this, &__x);
684#endif
685 }
686
687#if _LIBCPP_DEBUG_LEVEL >= 2
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000688
Howard Hinnant99acc502010-09-21 17:32:39 +0000689 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58 +0000690 __hash_const_local_iterator(const __hash_const_local_iterator& __i)
691 : __node_(__i.__node_),
692 __bucket_(__i.__bucket_),
693 __bucket_count_(__i.__bucket_count_)
694 {
695 __get_db()->__iterator_copy(this, &__i);
696 }
697
Howard Hinnant99acc502010-09-21 17:32:39 +0000698 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58 +0000699 ~__hash_const_local_iterator()
700 {
701 __get_db()->__erase_i(this);
702 }
703
704 _LIBCPP_INLINE_VISIBILITY
705 __hash_const_local_iterator& operator=(const __hash_const_local_iterator& __i)
706 {
707 if (this != &__i)
708 {
709 __get_db()->__iterator_copy(this, &__i);
710 __node_ = __i.__node_;
711 __bucket_ = __i.__bucket_;
712 __bucket_count_ = __i.__bucket_count_;
713 }
714 return *this;
715 }
716
717#endif // _LIBCPP_DEBUG_LEVEL >= 2
718
719 _LIBCPP_INLINE_VISIBILITY
720 reference operator*() const
721 {
722#if _LIBCPP_DEBUG_LEVEL >= 2
723 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
724 "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
725#endif
726 return __node_->__value_;
727 }
728 _LIBCPP_INLINE_VISIBILITY
729 pointer operator->() const
730 {
731#if _LIBCPP_DEBUG_LEVEL >= 2
732 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
733 "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
734#endif
735 return pointer_traits<pointer>::pointer_to(__node_->__value_);
736 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000737
Howard Hinnant99acc502010-09-21 17:32:39 +0000738 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000739 __hash_const_local_iterator& operator++()
740 {
Howard Hinnant39213642013-07-23 22:01:58 +0000741#if _LIBCPP_DEBUG_LEVEL >= 2
742 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
743 "Attempted to increment non-incrementable unordered container const_local_iterator");
744#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000745 __node_ = __node_->__next_;
Howard Hinnant7a445152012-07-06 17:31:14 +0000746 if (__node_ != nullptr && __constrain_hash(__node_->__hash_, __bucket_count_) != __bucket_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000747 __node_ = nullptr;
748 return *this;
749 }
750
Howard Hinnant99acc502010-09-21 17:32:39 +0000751 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000752 __hash_const_local_iterator operator++(int)
753 {
754 __hash_const_local_iterator __t(*this);
755 ++(*this);
756 return __t;
757 }
758
Howard Hinnant99acc502010-09-21 17:32:39 +0000759 friend _LIBCPP_INLINE_VISIBILITY
760 bool operator==(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58 +0000761 {
Howard Hinnant39213642013-07-23 22:01:58 +0000762 return __x.__node_ == __y.__node_;
763 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000764 friend _LIBCPP_INLINE_VISIBILITY
765 bool operator!=(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58 +0000766 {return !(__x == __y);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000767
768private:
Howard Hinnant39213642013-07-23 22:01:58 +0000769#if _LIBCPP_DEBUG_LEVEL >= 2
770 _LIBCPP_INLINE_VISIBILITY
771 __hash_const_local_iterator(__node_pointer __node, size_t __bucket,
772 size_t __bucket_count, const void* __c) _NOEXCEPT
773 : __node_(__node),
774 __bucket_(__bucket),
775 __bucket_count_(__bucket_count)
776 {
777 __get_db()->__insert_ic(this, __c);
778 if (__node_ != nullptr)
779 __node_ = __node_->__next_;
780 }
781#else
Howard Hinnant99acc502010-09-21 17:32:39 +0000782 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000783 __hash_const_local_iterator(__node_pointer __node, size_t __bucket,
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000784 size_t __bucket_count) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000785 : __node_(__node),
786 __bucket_(__bucket),
787 __bucket_count_(__bucket_count)
788 {
789 if (__node_ != nullptr)
790 __node_ = __node_->__next_;
791 }
Howard Hinnant39213642013-07-23 22:01:58 +0000792#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000793 template <class, class, class, class> friend class __hash_table;
Howard Hinnant0f678bd2013-08-12 18:38:34 +0000794 template <class> friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000795};
796
797template <class _Alloc>
798class __bucket_list_deallocator
799{
800 typedef _Alloc allocator_type;
801 typedef allocator_traits<allocator_type> __alloc_traits;
802 typedef typename __alloc_traits::size_type size_type;
803
804 __compressed_pair<size_type, allocator_type> __data_;
805public:
806 typedef typename __alloc_traits::pointer pointer;
807
Howard Hinnant99acc502010-09-21 17:32:39 +0000808 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000809 __bucket_list_deallocator()
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000810 _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000811 : __data_(0) {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000812
813 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000814 __bucket_list_deallocator(const allocator_type& __a, size_type __size)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000815 _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000816 : __data_(__size, __a) {}
817
Howard Hinnant73d21a42010-09-04 23:28:19 +0000818#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000819
Howard Hinnant99acc502010-09-21 17:32:39 +0000820 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000821 __bucket_list_deallocator(__bucket_list_deallocator&& __x)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000822 _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000823 : __data_(_VSTD::move(__x.__data_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000824 {
825 __x.size() = 0;
826 }
827
Howard Hinnant73d21a42010-09-04 23:28:19 +0000828#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000829
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000830 _LIBCPP_INLINE_VISIBILITY
831 size_type& size() _NOEXCEPT {return __data_.first();}
832 _LIBCPP_INLINE_VISIBILITY
833 size_type size() const _NOEXCEPT {return __data_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000834
Howard Hinnant99acc502010-09-21 17:32:39 +0000835 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000836 allocator_type& __alloc() _NOEXCEPT {return __data_.second();}
837 _LIBCPP_INLINE_VISIBILITY
838 const allocator_type& __alloc() const _NOEXCEPT {return __data_.second();}
839
840 _LIBCPP_INLINE_VISIBILITY
841 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000842 {
843 __alloc_traits::deallocate(__alloc(), __p, size());
844 }
845};
846
Howard Hinnant2b1b2d42011-06-14 19:58:17 +0000847template <class _Alloc> class __hash_map_node_destructor;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000848
849template <class _Alloc>
850class __hash_node_destructor
851{
852 typedef _Alloc allocator_type;
853 typedef allocator_traits<allocator_type> __alloc_traits;
Eric Fiselier774c7c52016-02-10 20:46:23 +0000854
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000855public:
856 typedef typename __alloc_traits::pointer pointer;
857private:
Eric Fiselier2960ae22016-02-11 11:59:44 +0000858 typedef __hash_node_types<pointer> _NodeTypes;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000859
860 allocator_type& __na_;
861
862 __hash_node_destructor& operator=(const __hash_node_destructor&);
863
864public:
865 bool __value_constructed;
866
Howard Hinnant99acc502010-09-21 17:32:39 +0000867 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant199d0ae2011-07-31 17:04:30 +0000868 explicit __hash_node_destructor(allocator_type& __na,
869 bool __constructed = false) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000870 : __na_(__na),
Howard Hinnant199d0ae2011-07-31 17:04:30 +0000871 __value_constructed(__constructed)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000872 {}
873
Howard Hinnant99acc502010-09-21 17:32:39 +0000874 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000875 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000876 {
877 if (__value_constructed)
Eric Fiselier2960ae22016-02-11 11:59:44 +0000878 __alloc_traits::destroy(__na_, _NodeTypes::__get_ptr(__p->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000879 if (__p)
880 __alloc_traits::deallocate(__na_, __p, 1);
881 }
882
883 template <class> friend class __hash_map_node_destructor;
884};
885
886template <class _Tp, class _Hash, class _Equal, class _Alloc>
887class __hash_table
888{
889public:
890 typedef _Tp value_type;
891 typedef _Hash hasher;
892 typedef _Equal key_equal;
893 typedef _Alloc allocator_type;
894
895private:
896 typedef allocator_traits<allocator_type> __alloc_traits;
Eric Fiselier774c7c52016-02-10 20:46:23 +0000897 typedef typename
898 __make_hash_node_types<value_type, typename __alloc_traits::void_pointer>::type
899 _NodeTypes;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000900public:
Eric Fiselier2960ae22016-02-11 11:59:44 +0000901
902 typedef typename _NodeTypes::__node_value_type __node_value_type;
903 typedef typename _NodeTypes::__container_value_type __container_value_type;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000904 typedef value_type& reference;
905 typedef const value_type& const_reference;
906 typedef typename __alloc_traits::pointer pointer;
907 typedef typename __alloc_traits::const_pointer const_pointer;
Eric Fiselier774c7c52016-02-10 20:46:23 +0000908#ifndef _LIBCPP_ABI_FIX_UNORDERED_CONTAINER_SIZE_TYPE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000909 typedef typename __alloc_traits::size_type size_type;
Eric Fiselier774c7c52016-02-10 20:46:23 +0000910#else
911 typedef typename _NodeTypes::size_type size_type;
912#endif
913 typedef typename _NodeTypes::difference_type difference_type;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000914public:
915 // Create __node
Eric Fiselier774c7c52016-02-10 20:46:23 +0000916
917 typedef typename _NodeTypes::__node_type __node;
Marshall Clow66302c62015-04-07 05:21:38 +0000918 typedef typename __rebind_alloc_helper<__alloc_traits, __node>::type __node_allocator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000919 typedef allocator_traits<__node_allocator> __node_traits;
Eric Fiselier9e9f42e2016-02-11 15:22:37 +0000920 typedef typename _NodeTypes::__void_pointer __void_pointer;
Eric Fiselier774c7c52016-02-10 20:46:23 +0000921 typedef typename _NodeTypes::__node_pointer __node_pointer;
922 typedef typename _NodeTypes::__node_pointer __node_const_pointer;
923 typedef typename _NodeTypes::__node_base_type __first_node;
924 typedef typename _NodeTypes::__node_base_pointer __node_base_pointer;
925
926private:
927 // check for sane allocator pointer rebinding semantics. Rebinding the
928 // allocator for a new pointer type should be exactly the same as rebinding
929 // the pointer using 'pointer_traits'.
930 static_assert((is_same<__node_pointer, typename __node_traits::pointer>::value),
931 "Allocator does not rebind pointers in a sane manner.");
932 typedef typename __rebind_alloc_helper<__node_traits, __first_node>::type
933 __node_base_allocator;
934 typedef allocator_traits<__node_base_allocator> __node_base_traits;
935 static_assert((is_same<__node_base_pointer, typename __node_base_traits::pointer>::value),
936 "Allocator does not rebind pointers in a sane manner.");
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000937
938private:
939
Marshall Clow66302c62015-04-07 05:21:38 +0000940 typedef typename __rebind_alloc_helper<__node_traits, __node_pointer>::type __pointer_allocator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000941 typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter;
942 typedef unique_ptr<__node_pointer[], __bucket_list_deleter> __bucket_list;
943 typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits;
944 typedef typename __bucket_list_deleter::pointer __node_pointer_pointer;
945
946 // --- Member data begin ---
Eric Fiselier774c7c52016-02-10 20:46:23 +0000947 __bucket_list __bucket_list_;
948 __compressed_pair<__first_node, __node_allocator> __p1_;
949 __compressed_pair<size_type, hasher> __p2_;
950 __compressed_pair<float, key_equal> __p3_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000951 // --- Member data end ---
952
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000953 _LIBCPP_INLINE_VISIBILITY
954 size_type& size() _NOEXCEPT {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000955public:
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000956 _LIBCPP_INLINE_VISIBILITY
957 size_type size() const _NOEXCEPT {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000958
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000959 _LIBCPP_INLINE_VISIBILITY
960 hasher& hash_function() _NOEXCEPT {return __p2_.second();}
961 _LIBCPP_INLINE_VISIBILITY
962 const hasher& hash_function() const _NOEXCEPT {return __p2_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000963
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000964 _LIBCPP_INLINE_VISIBILITY
965 float& max_load_factor() _NOEXCEPT {return __p3_.first();}
966 _LIBCPP_INLINE_VISIBILITY
967 float max_load_factor() const _NOEXCEPT {return __p3_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000968
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000969 _LIBCPP_INLINE_VISIBILITY
970 key_equal& key_eq() _NOEXCEPT {return __p3_.second();}
971 _LIBCPP_INLINE_VISIBILITY
972 const key_equal& key_eq() const _NOEXCEPT {return __p3_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000973
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000974 _LIBCPP_INLINE_VISIBILITY
975 __node_allocator& __node_alloc() _NOEXCEPT {return __p1_.second();}
976 _LIBCPP_INLINE_VISIBILITY
977 const __node_allocator& __node_alloc() const _NOEXCEPT
978 {return __p1_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000979
980public:
981 typedef __hash_iterator<__node_pointer> iterator;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000982 typedef __hash_const_iterator<__node_pointer> const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000983 typedef __hash_local_iterator<__node_pointer> local_iterator;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000984 typedef __hash_const_local_iterator<__node_pointer> const_local_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000985
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +0000986 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000987 __hash_table()
988 _NOEXCEPT_(
989 is_nothrow_default_constructible<__bucket_list>::value &&
990 is_nothrow_default_constructible<__first_node>::value &&
991 is_nothrow_default_constructible<__node_allocator>::value &&
992 is_nothrow_default_constructible<hasher>::value &&
993 is_nothrow_default_constructible<key_equal>::value);
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +0000994 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000995 __hash_table(const hasher& __hf, const key_equal& __eql);
996 __hash_table(const hasher& __hf, const key_equal& __eql,
997 const allocator_type& __a);
998 explicit __hash_table(const allocator_type& __a);
999 __hash_table(const __hash_table& __u);
1000 __hash_table(const __hash_table& __u, const allocator_type& __a);
Eric Fiselier2960ae22016-02-11 11:59:44 +00001001#ifndef _LIBCPP_CXX03_LANG
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001002 __hash_table(__hash_table&& __u)
1003 _NOEXCEPT_(
1004 is_nothrow_move_constructible<__bucket_list>::value &&
1005 is_nothrow_move_constructible<__first_node>::value &&
1006 is_nothrow_move_constructible<__node_allocator>::value &&
1007 is_nothrow_move_constructible<hasher>::value &&
1008 is_nothrow_move_constructible<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001009 __hash_table(__hash_table&& __u, const allocator_type& __a);
Eric Fiselier2960ae22016-02-11 11:59:44 +00001010#endif // _LIBCPP_CXX03_LANG
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001011 ~__hash_table();
1012
1013 __hash_table& operator=(const __hash_table& __u);
Eric Fiselier2960ae22016-02-11 11:59:44 +00001014#ifndef _LIBCPP_CXX03_LANG
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00001015 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001016 __hash_table& operator=(__hash_table&& __u)
1017 _NOEXCEPT_(
1018 __node_traits::propagate_on_container_move_assignment::value &&
1019 is_nothrow_move_assignable<__node_allocator>::value &&
1020 is_nothrow_move_assignable<hasher>::value &&
1021 is_nothrow_move_assignable<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001022#endif
1023 template <class _InputIterator>
1024 void __assign_unique(_InputIterator __first, _InputIterator __last);
1025 template <class _InputIterator>
1026 void __assign_multi(_InputIterator __first, _InputIterator __last);
1027
Howard Hinnant99acc502010-09-21 17:32:39 +00001028 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001029 size_type max_size() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001030 {
1031 return allocator_traits<__pointer_allocator>::max_size(
1032 __bucket_list_.get_deleter().__alloc());
1033 }
1034
1035 pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
1036 iterator __node_insert_multi(__node_pointer __nd);
1037 iterator __node_insert_multi(const_iterator __p,
1038 __node_pointer __nd);
1039
Eric Fiselier2960ae22016-02-11 11:59:44 +00001040#ifndef _LIBCPP_CXX03_LANG
1041 template <class _Key, class ..._Args>
1042 pair<iterator, bool> __emplace_unique_key_args(_Key const& __k, _Args&&... __args);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001043
Eric Fiselier2960ae22016-02-11 11:59:44 +00001044 template <class... _Args>
1045 pair<iterator, bool> __emplace_unique(_Args&&... __args);
1046 template <class... _Args>
1047 iterator __emplace_multi(_Args&&... __args);
1048 template <class... _Args>
1049 iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args);
1050
1051
Eric Fiselierfdae69a2015-06-13 07:18:32 +00001052 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier2960ae22016-02-11 11:59:44 +00001053 pair<iterator, bool>
1054 __insert_unique(__container_value_type&& __x) {
1055 return __emplace_unique_key_args(_NodeTypes::__get_key(__x), _VSTD::move(__x));
1056 }
1057
1058 template <class _Pp, class = typename enable_if<
1059 !__is_same_uncvref<_Pp, __container_value_type>::value
1060 >::type>
Eric Fiselierfdae69a2015-06-13 07:18:32 +00001061 _LIBCPP_INLINE_VISIBILITY
Eric Fiselier2960ae22016-02-11 11:59:44 +00001062 pair<iterator, bool> __insert_unique(_Pp&& __x) {
1063 return __emplace_unique(_VSTD::forward<_Pp>(__x));
1064 }
1065
1066 template <class _Pp>
1067 _LIBCPP_INLINE_VISIBILITY
1068 iterator __insert_multi(_Pp&& __x) {
1069 return __emplace_multi(_VSTD::forward<_Pp>(__x));
1070 }
1071
1072 template <class _Pp>
1073 _LIBCPP_INLINE_VISIBILITY
1074 iterator __insert_multi(const_iterator __p, _Pp&& __x) {
1075 return __emplace_hint_multi(__p, _VSTD::forward<_Pp>(__x));
1076 }
1077
1078#else // !defined(_LIBCPP_CXX03_LANG)
1079 template <class _Key, class _Args>
1080 pair<iterator, bool> __emplace_unique_key_args(_Key const&, _Args& __args);
1081
1082 iterator __insert_multi(const __container_value_type& __x);
1083 iterator __insert_multi(const_iterator __p, const __container_value_type& __x);
Eric Fiselierfdae69a2015-06-13 07:18:32 +00001084#endif
1085
Eric Fiselier2960ae22016-02-11 11:59:44 +00001086 _LIBCPP_INLINE_VISIBILITY
1087 pair<iterator, bool> __insert_unique(const __container_value_type& __x) {
1088 return __emplace_unique_key_args(_NodeTypes::__get_key(__x), __x);
1089 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001090
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001091 void clear() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001092 void rehash(size_type __n);
Howard Hinnant99acc502010-09-21 17:32:39 +00001093 _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001094 {rehash(static_cast<size_type>(ceil(__n / max_load_factor())));}
Howard Hinnant99acc502010-09-21 17:32:39 +00001095
1096 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001097 size_type bucket_count() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001098 {
1099 return __bucket_list_.get_deleter().size();
1100 }
1101
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00001102 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001103 iterator begin() _NOEXCEPT;
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00001104 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001105 iterator end() _NOEXCEPT;
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00001106 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001107 const_iterator begin() const _NOEXCEPT;
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00001108 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001109 const_iterator end() const _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001110
1111 template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39 +00001112 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001113 size_type bucket(const _Key& __k) const
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00001114 {
1115 _LIBCPP_ASSERT(bucket_count() > 0,
1116 "unordered container::bucket(key) called when bucket_count() == 0");
1117 return __constrain_hash(hash_function()(__k), bucket_count());
1118 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001119
1120 template <class _Key>
1121 iterator find(const _Key& __x);
1122 template <class _Key>
1123 const_iterator find(const _Key& __x) const;
1124
Howard Hinnant99968442011-11-29 18:15:50 +00001125 typedef __hash_node_destructor<__node_allocator> _Dp;
1126 typedef unique_ptr<__node, _Dp> __node_holder;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001127
1128 iterator erase(const_iterator __p);
1129 iterator erase(const_iterator __first, const_iterator __last);
1130 template <class _Key>
1131 size_type __erase_unique(const _Key& __k);
1132 template <class _Key>
1133 size_type __erase_multi(const _Key& __k);
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001134 __node_holder remove(const_iterator __p) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001135
1136 template <class _Key>
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00001137 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001138 size_type __count_unique(const _Key& __k) const;
1139 template <class _Key>
1140 size_type __count_multi(const _Key& __k) const;
1141
1142 template <class _Key>
1143 pair<iterator, iterator>
1144 __equal_range_unique(const _Key& __k);
1145 template <class _Key>
1146 pair<const_iterator, const_iterator>
1147 __equal_range_unique(const _Key& __k) const;
1148
1149 template <class _Key>
1150 pair<iterator, iterator>
1151 __equal_range_multi(const _Key& __k);
1152 template <class _Key>
1153 pair<const_iterator, const_iterator>
1154 __equal_range_multi(const _Key& __k) const;
1155
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001156 void swap(__hash_table& __u)
Eric Fiselier692177d2015-07-18 20:40:46 +00001157#if _LIBCPP_STD_VER <= 11
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001158 _NOEXCEPT_(
Marshall Clow7d914d12015-07-13 20:04:56 +00001159 __is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value
Marshall Clow7d914d12015-07-13 20:04:56 +00001160 && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value
1161 || __is_nothrow_swappable<__pointer_allocator>::value)
1162 && (!__node_traits::propagate_on_container_swap::value
1163 || __is_nothrow_swappable<__node_allocator>::value)
Marshall Clow7d914d12015-07-13 20:04:56 +00001164 );
Eric Fiselier692177d2015-07-18 20:40:46 +00001165#else
1166 _NOEXCEPT_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value);
1167#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001168
Howard Hinnant99acc502010-09-21 17:32:39 +00001169 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001170 size_type max_bucket_count() const _NOEXCEPT
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001171 {return __pointer_alloc_traits::max_size(__bucket_list_.get_deleter().__alloc());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001172 size_type bucket_size(size_type __n) const;
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001173 _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001174 {
1175 size_type __bc = bucket_count();
1176 return __bc != 0 ? (float)size() / __bc : 0.f;
1177 }
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001178 _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00001179 {
1180 _LIBCPP_ASSERT(__mlf > 0,
1181 "unordered container::max_load_factor(lf) called with lf <= 0");
1182 max_load_factor() = _VSTD::max(__mlf, load_factor());
1183 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001184
Howard Hinnant39213642013-07-23 22:01:58 +00001185 _LIBCPP_INLINE_VISIBILITY
1186 local_iterator
1187 begin(size_type __n)
1188 {
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00001189 _LIBCPP_ASSERT(__n < bucket_count(),
1190 "unordered container::begin(n) called with n >= bucket_count()");
Howard Hinnant39213642013-07-23 22:01:58 +00001191#if _LIBCPP_DEBUG_LEVEL >= 2
1192 return local_iterator(__bucket_list_[__n], __n, bucket_count(), this);
1193#else
1194 return local_iterator(__bucket_list_[__n], __n, bucket_count());
1195#endif
1196 }
1197
1198 _LIBCPP_INLINE_VISIBILITY
1199 local_iterator
1200 end(size_type __n)
1201 {
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00001202 _LIBCPP_ASSERT(__n < bucket_count(),
1203 "unordered container::end(n) called with n >= bucket_count()");
Howard Hinnant39213642013-07-23 22:01:58 +00001204#if _LIBCPP_DEBUG_LEVEL >= 2
1205 return local_iterator(nullptr, __n, bucket_count(), this);
1206#else
1207 return local_iterator(nullptr, __n, bucket_count());
1208#endif
1209 }
1210
1211 _LIBCPP_INLINE_VISIBILITY
1212 const_local_iterator
1213 cbegin(size_type __n) const
1214 {
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00001215 _LIBCPP_ASSERT(__n < bucket_count(),
1216 "unordered container::cbegin(n) called with n >= bucket_count()");
Howard Hinnant39213642013-07-23 22:01:58 +00001217#if _LIBCPP_DEBUG_LEVEL >= 2
1218 return const_local_iterator(__bucket_list_[__n], __n, bucket_count(), this);
1219#else
1220 return const_local_iterator(__bucket_list_[__n], __n, bucket_count());
1221#endif
1222 }
1223
1224 _LIBCPP_INLINE_VISIBILITY
1225 const_local_iterator
1226 cend(size_type __n) const
1227 {
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00001228 _LIBCPP_ASSERT(__n < bucket_count(),
1229 "unordered container::cend(n) called with n >= bucket_count()");
Howard Hinnant39213642013-07-23 22:01:58 +00001230#if _LIBCPP_DEBUG_LEVEL >= 2
1231 return const_local_iterator(nullptr, __n, bucket_count(), this);
1232#else
1233 return const_local_iterator(nullptr, __n, bucket_count());
1234#endif
1235 }
1236
1237#if _LIBCPP_DEBUG_LEVEL >= 2
1238
1239 bool __dereferenceable(const const_iterator* __i) const;
1240 bool __decrementable(const const_iterator* __i) const;
1241 bool __addable(const const_iterator* __i, ptrdiff_t __n) const;
1242 bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const;
1243
1244#endif // _LIBCPP_DEBUG_LEVEL >= 2
1245
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001246private:
1247 void __rehash(size_type __n);
1248
Eric Fiselier2960ae22016-02-11 11:59:44 +00001249#ifndef _LIBCPP_CXX03_LANG
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001250 template <class ..._Args>
Eric Fiselier2960ae22016-02-11 11:59:44 +00001251 __node_holder __construct_node(_Args&& ...__args);
1252
1253 template <class _First, class ..._Rest>
1254 __node_holder __construct_node_hash(size_t __hash, _First&& __f, _Rest&&... __rest);
1255#else // _LIBCPP_CXX03_LANG
1256 __node_holder __construct_node(const __container_value_type& __v);
1257 __node_holder __construct_node_hash(size_t __hash, const __container_value_type& __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001258#endif
Eric Fiselier2960ae22016-02-11 11:59:44 +00001259
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001260
Howard Hinnant99acc502010-09-21 17:32:39 +00001261 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001262 void __copy_assign_alloc(const __hash_table& __u)
1263 {__copy_assign_alloc(__u, integral_constant<bool,
1264 __node_traits::propagate_on_container_copy_assignment::value>());}
1265 void __copy_assign_alloc(const __hash_table& __u, true_type);
Howard Hinnant99acc502010-09-21 17:32:39 +00001266 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantec3773c2011-12-01 20:21:04 +00001267 void __copy_assign_alloc(const __hash_table&, false_type) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001268
Eric Fiselier2960ae22016-02-11 11:59:44 +00001269#ifndef _LIBCPP_CXX03_LANG
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001270 void __move_assign(__hash_table& __u, false_type);
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001271 void __move_assign(__hash_table& __u, true_type)
1272 _NOEXCEPT_(
1273 is_nothrow_move_assignable<__node_allocator>::value &&
1274 is_nothrow_move_assignable<hasher>::value &&
1275 is_nothrow_move_assignable<key_equal>::value);
1276 _LIBCPP_INLINE_VISIBILITY
1277 void __move_assign_alloc(__hash_table& __u)
1278 _NOEXCEPT_(
1279 !__node_traits::propagate_on_container_move_assignment::value ||
1280 (is_nothrow_move_assignable<__pointer_allocator>::value &&
1281 is_nothrow_move_assignable<__node_allocator>::value))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001282 {__move_assign_alloc(__u, integral_constant<bool,
1283 __node_traits::propagate_on_container_move_assignment::value>());}
Howard Hinnant99acc502010-09-21 17:32:39 +00001284 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001285 void __move_assign_alloc(__hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001286 _NOEXCEPT_(
1287 is_nothrow_move_assignable<__pointer_allocator>::value &&
1288 is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001289 {
1290 __bucket_list_.get_deleter().__alloc() =
Howard Hinnant0949eed2011-06-30 21:18:19 +00001291 _VSTD::move(__u.__bucket_list_.get_deleter().__alloc());
1292 __node_alloc() = _VSTD::move(__u.__node_alloc());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001293 }
Howard Hinnant99acc502010-09-21 17:32:39 +00001294 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001295 void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {}
Eric Fiselier2960ae22016-02-11 11:59:44 +00001296#endif // _LIBCPP_CXX03_LANG
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001297
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001298 void __deallocate(__node_pointer __np) _NOEXCEPT;
1299 __node_pointer __detach() _NOEXCEPT;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001300
Howard Hinnant0f678bd2013-08-12 18:38:34 +00001301 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY unordered_map;
1302 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001303};
1304
1305template <class _Tp, class _Hash, class _Equal, class _Alloc>
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00001306inline
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001307__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table()
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001308 _NOEXCEPT_(
1309 is_nothrow_default_constructible<__bucket_list>::value &&
1310 is_nothrow_default_constructible<__first_node>::value &&
Eric Fiselierc8f54c22015-12-16 00:53:04 +00001311 is_nothrow_default_constructible<__node_allocator>::value &&
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001312 is_nothrow_default_constructible<hasher>::value &&
1313 is_nothrow_default_constructible<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001314 : __p2_(0),
1315 __p3_(1.0f)
1316{
1317}
1318
1319template <class _Tp, class _Hash, class _Equal, class _Alloc>
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00001320inline
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001321__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
1322 const key_equal& __eql)
1323 : __bucket_list_(nullptr, __bucket_list_deleter()),
1324 __p1_(),
1325 __p2_(0, __hf),
1326 __p3_(1.0f, __eql)
1327{
1328}
1329
1330template <class _Tp, class _Hash, class _Equal, class _Alloc>
1331__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
1332 const key_equal& __eql,
1333 const allocator_type& __a)
1334 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1335 __p1_(__node_allocator(__a)),
1336 __p2_(0, __hf),
1337 __p3_(1.0f, __eql)
1338{
1339}
1340
1341template <class _Tp, class _Hash, class _Equal, class _Alloc>
1342__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
1343 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1344 __p1_(__node_allocator(__a)),
1345 __p2_(0),
1346 __p3_(1.0f)
1347{
1348}
1349
1350template <class _Tp, class _Hash, class _Equal, class _Alloc>
1351__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
1352 : __bucket_list_(nullptr,
1353 __bucket_list_deleter(allocator_traits<__pointer_allocator>::
1354 select_on_container_copy_construction(
1355 __u.__bucket_list_.get_deleter().__alloc()), 0)),
1356 __p1_(allocator_traits<__node_allocator>::
1357 select_on_container_copy_construction(__u.__node_alloc())),
1358 __p2_(0, __u.hash_function()),
1359 __p3_(__u.__p3_)
1360{
1361}
1362
1363template <class _Tp, class _Hash, class _Equal, class _Alloc>
1364__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u,
1365 const allocator_type& __a)
1366 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1367 __p1_(__node_allocator(__a)),
1368 __p2_(0, __u.hash_function()),
1369 __p3_(__u.__p3_)
1370{
1371}
1372
Eric Fiselier2960ae22016-02-11 11:59:44 +00001373#ifndef _LIBCPP_CXX03_LANG
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001374
1375template <class _Tp, class _Hash, class _Equal, class _Alloc>
1376__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001377 _NOEXCEPT_(
1378 is_nothrow_move_constructible<__bucket_list>::value &&
1379 is_nothrow_move_constructible<__first_node>::value &&
Eric Fiselierc8f54c22015-12-16 00:53:04 +00001380 is_nothrow_move_constructible<__node_allocator>::value &&
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001381 is_nothrow_move_constructible<hasher>::value &&
1382 is_nothrow_move_constructible<key_equal>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +00001383 : __bucket_list_(_VSTD::move(__u.__bucket_list_)),
1384 __p1_(_VSTD::move(__u.__p1_)),
1385 __p2_(_VSTD::move(__u.__p2_)),
1386 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001387{
1388 if (size() > 0)
1389 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001390 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001391 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001392 __u.__p1_.first().__next_ = nullptr;
1393 __u.size() = 0;
1394 }
1395}
1396
1397template <class _Tp, class _Hash, class _Equal, class _Alloc>
1398__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u,
1399 const allocator_type& __a)
1400 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1401 __p1_(__node_allocator(__a)),
Howard Hinnant0949eed2011-06-30 21:18:19 +00001402 __p2_(0, _VSTD::move(__u.hash_function())),
1403 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001404{
1405 if (__a == allocator_type(__u.__node_alloc()))
1406 {
1407 __bucket_list_.reset(__u.__bucket_list_.release());
1408 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
1409 __u.__bucket_list_.get_deleter().size() = 0;
1410 if (__u.size() > 0)
1411 {
1412 __p1_.first().__next_ = __u.__p1_.first().__next_;
1413 __u.__p1_.first().__next_ = nullptr;
Howard Hinnant7a445152012-07-06 17:31:14 +00001414 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001415 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001416 size() = __u.size();
1417 __u.size() = 0;
1418 }
1419 }
1420}
1421
Eric Fiselier2960ae22016-02-11 11:59:44 +00001422#endif // _LIBCPP_CXX03_LANG
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001423
1424template <class _Tp, class _Hash, class _Equal, class _Alloc>
1425__hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table()
1426{
1427 __deallocate(__p1_.first().__next_);
Howard Hinnant39213642013-07-23 22:01:58 +00001428#if _LIBCPP_DEBUG_LEVEL >= 2
1429 __get_db()->__erase_c(this);
1430#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001431}
1432
1433template <class _Tp, class _Hash, class _Equal, class _Alloc>
1434void
1435__hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc(
1436 const __hash_table& __u, true_type)
1437{
1438 if (__node_alloc() != __u.__node_alloc())
1439 {
1440 clear();
1441 __bucket_list_.reset();
1442 __bucket_list_.get_deleter().size() = 0;
1443 }
1444 __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc();
1445 __node_alloc() = __u.__node_alloc();
1446}
1447
1448template <class _Tp, class _Hash, class _Equal, class _Alloc>
1449__hash_table<_Tp, _Hash, _Equal, _Alloc>&
1450__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u)
1451{
1452 if (this != &__u)
1453 {
1454 __copy_assign_alloc(__u);
1455 hash_function() = __u.hash_function();
1456 key_eq() = __u.key_eq();
1457 max_load_factor() = __u.max_load_factor();
1458 __assign_multi(__u.begin(), __u.end());
1459 }
1460 return *this;
1461}
1462
1463template <class _Tp, class _Hash, class _Equal, class _Alloc>
1464void
1465__hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate(__node_pointer __np)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001466 _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001467{
1468 __node_allocator& __na = __node_alloc();
1469 while (__np != nullptr)
1470 {
1471 __node_pointer __next = __np->__next_;
Howard Hinnant39213642013-07-23 22:01:58 +00001472#if _LIBCPP_DEBUG_LEVEL >= 2
1473 __c_node* __c = __get_db()->__find_c_and_lock(this);
1474 for (__i_node** __p = __c->end_; __p != __c->beg_; )
1475 {
1476 --__p;
1477 iterator* __i = static_cast<iterator*>((*__p)->__i_);
1478 if (__i->__node_ == __np)
1479 {
1480 (*__p)->__c_ = nullptr;
1481 if (--__c->end_ != __p)
1482 memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*));
1483 }
1484 }
1485 __get_db()->unlock();
1486#endif
Eric Fiselier2960ae22016-02-11 11:59:44 +00001487 __node_traits::destroy(__na, _NodeTypes::__get_ptr(__np->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001488 __node_traits::deallocate(__na, __np, 1);
1489 __np = __next;
1490 }
1491}
1492
1493template <class _Tp, class _Hash, class _Equal, class _Alloc>
1494typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_pointer
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001495__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001496{
1497 size_type __bc = bucket_count();
1498 for (size_type __i = 0; __i < __bc; ++__i)
1499 __bucket_list_[__i] = nullptr;
1500 size() = 0;
1501 __node_pointer __cache = __p1_.first().__next_;
1502 __p1_.first().__next_ = nullptr;
1503 return __cache;
1504}
1505
Eric Fiselier2960ae22016-02-11 11:59:44 +00001506#ifndef _LIBCPP_CXX03_LANG
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001507
1508template <class _Tp, class _Hash, class _Equal, class _Alloc>
1509void
1510__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
1511 __hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001512 _NOEXCEPT_(
1513 is_nothrow_move_assignable<__node_allocator>::value &&
1514 is_nothrow_move_assignable<hasher>::value &&
1515 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001516{
1517 clear();
1518 __bucket_list_.reset(__u.__bucket_list_.release());
1519 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
1520 __u.__bucket_list_.get_deleter().size() = 0;
1521 __move_assign_alloc(__u);
1522 size() = __u.size();
Howard Hinnant0949eed2011-06-30 21:18:19 +00001523 hash_function() = _VSTD::move(__u.hash_function());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001524 max_load_factor() = __u.max_load_factor();
Howard Hinnant0949eed2011-06-30 21:18:19 +00001525 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001526 __p1_.first().__next_ = __u.__p1_.first().__next_;
1527 if (size() > 0)
1528 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001529 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001530 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001531 __u.__p1_.first().__next_ = nullptr;
1532 __u.size() = 0;
1533 }
Howard Hinnant39213642013-07-23 22:01:58 +00001534#if _LIBCPP_DEBUG_LEVEL >= 2
1535 __get_db()->swap(this, &__u);
1536#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001537}
1538
1539template <class _Tp, class _Hash, class _Equal, class _Alloc>
1540void
1541__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
1542 __hash_table& __u, false_type)
1543{
1544 if (__node_alloc() == __u.__node_alloc())
1545 __move_assign(__u, true_type());
1546 else
1547 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001548 hash_function() = _VSTD::move(__u.hash_function());
1549 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001550 max_load_factor() = __u.max_load_factor();
1551 if (bucket_count() != 0)
1552 {
1553 __node_pointer __cache = __detach();
1554#ifndef _LIBCPP_NO_EXCEPTIONS
1555 try
1556 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001557#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001558 const_iterator __i = __u.begin();
1559 while (__cache != nullptr && __u.size() != 0)
1560 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001561 __cache->__value_ = _VSTD::move(__u.remove(__i++)->__value_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001562 __node_pointer __next = __cache->__next_;
1563 __node_insert_multi(__cache);
1564 __cache = __next;
1565 }
1566#ifndef _LIBCPP_NO_EXCEPTIONS
1567 }
1568 catch (...)
1569 {
1570 __deallocate(__cache);
1571 throw;
1572 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001573#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001574 __deallocate(__cache);
1575 }
1576 const_iterator __i = __u.begin();
1577 while (__u.size() != 0)
1578 {
Eric Fiselier2960ae22016-02-11 11:59:44 +00001579 __node_holder __h = __construct_node(_NodeTypes::__move(__u.remove(__i++)->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001580 __node_insert_multi(__h.get());
1581 __h.release();
1582 }
1583 }
1584}
1585
1586template <class _Tp, class _Hash, class _Equal, class _Alloc>
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00001587inline
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001588__hash_table<_Tp, _Hash, _Equal, _Alloc>&
1589__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001590 _NOEXCEPT_(
1591 __node_traits::propagate_on_container_move_assignment::value &&
1592 is_nothrow_move_assignable<__node_allocator>::value &&
1593 is_nothrow_move_assignable<hasher>::value &&
1594 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001595{
1596 __move_assign(__u, integral_constant<bool,
1597 __node_traits::propagate_on_container_move_assignment::value>());
1598 return *this;
1599}
1600
Eric Fiselier2960ae22016-02-11 11:59:44 +00001601#endif // _LIBCPP_CXX03_LANG
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001602
1603template <class _Tp, class _Hash, class _Equal, class _Alloc>
1604template <class _InputIterator>
1605void
1606__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first,
1607 _InputIterator __last)
1608{
Eric Fiselier2960ae22016-02-11 11:59:44 +00001609 typedef iterator_traits<_InputIterator> _ITraits;
1610 typedef typename _ITraits::value_type _ItValueType;
1611 static_assert((is_same<_ItValueType, __container_value_type>::value),
1612 "__assign_unique may only be called with the containers value type");
1613
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001614 if (bucket_count() != 0)
1615 {
1616 __node_pointer __cache = __detach();
1617#ifndef _LIBCPP_NO_EXCEPTIONS
1618 try
1619 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001620#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001621 for (; __cache != nullptr && __first != __last; ++__first)
1622 {
1623 __cache->__value_ = *__first;
1624 __node_pointer __next = __cache->__next_;
1625 __node_insert_unique(__cache);
1626 __cache = __next;
1627 }
1628#ifndef _LIBCPP_NO_EXCEPTIONS
1629 }
1630 catch (...)
1631 {
1632 __deallocate(__cache);
1633 throw;
1634 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001635#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001636 __deallocate(__cache);
1637 }
1638 for (; __first != __last; ++__first)
1639 __insert_unique(*__first);
1640}
1641
1642template <class _Tp, class _Hash, class _Equal, class _Alloc>
1643template <class _InputIterator>
1644void
1645__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first,
1646 _InputIterator __last)
1647{
Eric Fiselier2960ae22016-02-11 11:59:44 +00001648 typedef iterator_traits<_InputIterator> _ITraits;
1649 typedef typename _ITraits::value_type _ItValueType;
1650 static_assert((is_same<_ItValueType, __container_value_type>::value ||
1651 is_same<_ItValueType, __node_value_type>::value),
1652 "__assign_multi may only be called with the containers value type"
1653 " or the nodes value type");
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001654 if (bucket_count() != 0)
1655 {
1656 __node_pointer __cache = __detach();
1657#ifndef _LIBCPP_NO_EXCEPTIONS
1658 try
1659 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001660#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001661 for (; __cache != nullptr && __first != __last; ++__first)
1662 {
1663 __cache->__value_ = *__first;
1664 __node_pointer __next = __cache->__next_;
1665 __node_insert_multi(__cache);
1666 __cache = __next;
1667 }
1668#ifndef _LIBCPP_NO_EXCEPTIONS
1669 }
1670 catch (...)
1671 {
1672 __deallocate(__cache);
1673 throw;
1674 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001675#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001676 __deallocate(__cache);
1677 }
1678 for (; __first != __last; ++__first)
Eric Fiselier2960ae22016-02-11 11:59:44 +00001679 __insert_multi(_NodeTypes::__get_value(*__first));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001680}
1681
1682template <class _Tp, class _Hash, class _Equal, class _Alloc>
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00001683inline
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001684typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001685__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001686{
Howard Hinnant39213642013-07-23 22:01:58 +00001687#if _LIBCPP_DEBUG_LEVEL >= 2
1688 return iterator(__p1_.first().__next_, this);
1689#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001690 return iterator(__p1_.first().__next_);
Howard Hinnant39213642013-07-23 22:01:58 +00001691#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001692}
1693
1694template <class _Tp, class _Hash, class _Equal, class _Alloc>
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00001695inline
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001696typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001697__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001698{
Howard Hinnant39213642013-07-23 22:01:58 +00001699#if _LIBCPP_DEBUG_LEVEL >= 2
1700 return iterator(nullptr, this);
1701#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001702 return iterator(nullptr);
Howard Hinnant39213642013-07-23 22:01:58 +00001703#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001704}
1705
1706template <class _Tp, class _Hash, class _Equal, class _Alloc>
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00001707inline
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001708typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001709__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001710{
Howard Hinnant39213642013-07-23 22:01:58 +00001711#if _LIBCPP_DEBUG_LEVEL >= 2
1712 return const_iterator(__p1_.first().__next_, this);
1713#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001714 return const_iterator(__p1_.first().__next_);
Howard Hinnant39213642013-07-23 22:01:58 +00001715#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001716}
1717
1718template <class _Tp, class _Hash, class _Equal, class _Alloc>
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00001719inline
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001720typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001721__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001722{
Howard Hinnant39213642013-07-23 22:01:58 +00001723#if _LIBCPP_DEBUG_LEVEL >= 2
1724 return const_iterator(nullptr, this);
1725#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001726 return const_iterator(nullptr);
Howard Hinnant39213642013-07-23 22:01:58 +00001727#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001728}
1729
1730template <class _Tp, class _Hash, class _Equal, class _Alloc>
1731void
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001732__hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001733{
1734 if (size() > 0)
1735 {
1736 __deallocate(__p1_.first().__next_);
1737 __p1_.first().__next_ = nullptr;
1738 size_type __bc = bucket_count();
Howard Hinnant9f66bff2011-07-05 14:14:17 +00001739 for (size_type __i = 0; __i < __bc; ++__i)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001740 __bucket_list_[__i] = nullptr;
1741 size() = 0;
1742 }
1743}
1744
1745template <class _Tp, class _Hash, class _Equal, class _Alloc>
1746pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1747__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd)
1748{
1749 __nd->__hash_ = hash_function()(__nd->__value_);
1750 size_type __bc = bucket_count();
1751 bool __inserted = false;
1752 __node_pointer __ndptr;
1753 size_t __chash;
1754 if (__bc != 0)
1755 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001756 __chash = __constrain_hash(__nd->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001757 __ndptr = __bucket_list_[__chash];
1758 if (__ndptr != nullptr)
1759 {
1760 for (__ndptr = __ndptr->__next_; __ndptr != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001761 __constrain_hash(__ndptr->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001762 __ndptr = __ndptr->__next_)
1763 {
1764 if (key_eq()(__ndptr->__value_, __nd->__value_))
1765 goto __done;
1766 }
1767 }
1768 }
1769 {
1770 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1771 {
Eric Fiselier57947ca2015-02-02 21:31:48 +00001772 rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001773 size_type(ceil(float(size() + 1) / max_load_factor()))));
1774 __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:14 +00001775 __chash = __constrain_hash(__nd->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001776 }
1777 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1778 __node_pointer __pn = __bucket_list_[__chash];
1779 if (__pn == nullptr)
1780 {
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001781 __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001782 __nd->__next_ = __pn->__next_;
1783 __pn->__next_ = __nd;
1784 // fix up __bucket_list_
1785 __bucket_list_[__chash] = __pn;
1786 if (__nd->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:14 +00001787 __bucket_list_[__constrain_hash(__nd->__next_->__hash_, __bc)] = __nd;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001788 }
1789 else
1790 {
1791 __nd->__next_ = __pn->__next_;
1792 __pn->__next_ = __nd;
1793 }
1794 __ndptr = __nd;
1795 // increment size
1796 ++size();
1797 __inserted = true;
1798 }
1799__done:
Howard Hinnant39213642013-07-23 22:01:58 +00001800#if _LIBCPP_DEBUG_LEVEL >= 2
1801 return pair<iterator, bool>(iterator(__ndptr, this), __inserted);
1802#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001803 return pair<iterator, bool>(iterator(__ndptr), __inserted);
Howard Hinnant39213642013-07-23 22:01:58 +00001804#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001805}
1806
1807template <class _Tp, class _Hash, class _Equal, class _Alloc>
1808typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1809__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp)
1810{
1811 __cp->__hash_ = hash_function()(__cp->__value_);
1812 size_type __bc = bucket_count();
1813 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1814 {
Eric Fiselier57947ca2015-02-02 21:31:48 +00001815 rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001816 size_type(ceil(float(size() + 1) / max_load_factor()))));
1817 __bc = bucket_count();
1818 }
Howard Hinnant7a445152012-07-06 17:31:14 +00001819 size_t __chash = __constrain_hash(__cp->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001820 __node_pointer __pn = __bucket_list_[__chash];
1821 if (__pn == nullptr)
1822 {
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001823 __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001824 __cp->__next_ = __pn->__next_;
1825 __pn->__next_ = __cp;
1826 // fix up __bucket_list_
1827 __bucket_list_[__chash] = __pn;
1828 if (__cp->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:14 +00001829 __bucket_list_[__constrain_hash(__cp->__next_->__hash_, __bc)] = __cp;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001830 }
1831 else
1832 {
1833 for (bool __found = false; __pn->__next_ != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001834 __constrain_hash(__pn->__next_->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001835 __pn = __pn->__next_)
Howard Hinnant324bb032010-08-22 00:02:43 +00001836 {
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001837 // __found key_eq() action
1838 // false false loop
1839 // true true loop
1840 // false true set __found to true
1841 // true false break
1842 if (__found != (__pn->__next_->__hash_ == __cp->__hash_ &&
1843 key_eq()(__pn->__next_->__value_, __cp->__value_)))
1844 {
1845 if (!__found)
1846 __found = true;
1847 else
1848 break;
1849 }
1850 }
1851 __cp->__next_ = __pn->__next_;
1852 __pn->__next_ = __cp;
1853 if (__cp->__next_ != nullptr)
1854 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001855 size_t __nhash = __constrain_hash(__cp->__next_->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001856 if (__nhash != __chash)
1857 __bucket_list_[__nhash] = __cp;
1858 }
1859 }
1860 ++size();
Howard Hinnant39213642013-07-23 22:01:58 +00001861#if _LIBCPP_DEBUG_LEVEL >= 2
1862 return iterator(__cp, this);
1863#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001864 return iterator(__cp);
Howard Hinnant39213642013-07-23 22:01:58 +00001865#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001866}
1867
1868template <class _Tp, class _Hash, class _Equal, class _Alloc>
1869typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1870__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(
1871 const_iterator __p, __node_pointer __cp)
1872{
Howard Hinnant824c1992013-08-02 17:50:49 +00001873#if _LIBCPP_DEBUG_LEVEL >= 2
1874 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
1875 "unordered container::emplace_hint(const_iterator, args...) called with an iterator not"
1876 " referring to this unordered container");
1877#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001878 if (__p != end() && key_eq()(*__p, __cp->__value_))
1879 {
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001880 __node_pointer __np = __p.__node_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001881 __cp->__hash_ = __np->__hash_;
1882 size_type __bc = bucket_count();
1883 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1884 {
Eric Fiselier57947ca2015-02-02 21:31:48 +00001885 rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001886 size_type(ceil(float(size() + 1) / max_load_factor()))));
1887 __bc = bucket_count();
1888 }
Howard Hinnant7a445152012-07-06 17:31:14 +00001889 size_t __chash = __constrain_hash(__cp->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001890 __node_pointer __pp = __bucket_list_[__chash];
1891 while (__pp->__next_ != __np)
1892 __pp = __pp->__next_;
1893 __cp->__next_ = __np;
1894 __pp->__next_ = __cp;
1895 ++size();
Howard Hinnant39213642013-07-23 22:01:58 +00001896#if _LIBCPP_DEBUG_LEVEL >= 2
1897 return iterator(__cp, this);
1898#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001899 return iterator(__cp);
Howard Hinnant39213642013-07-23 22:01:58 +00001900#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001901 }
1902 return __node_insert_multi(__cp);
1903}
1904
Eric Fiselierfdae69a2015-06-13 07:18:32 +00001905
1906
Eric Fiselier2960ae22016-02-11 11:59:44 +00001907#ifndef _LIBCPP_CXX03_LANG
Eric Fiselierfdae69a2015-06-13 07:18:32 +00001908template <class _Tp, class _Hash, class _Equal, class _Alloc>
Eric Fiselier2960ae22016-02-11 11:59:44 +00001909template <class _Key, class ..._Args>
Eric Fiselierfdae69a2015-06-13 07:18:32 +00001910_LIBCPP_INLINE_VISIBILITY
1911pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
Eric Fiselier2960ae22016-02-11 11:59:44 +00001912__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __k, _Args&&... __args)
Eric Fiselierfdae69a2015-06-13 07:18:32 +00001913#else
1914template <class _Tp, class _Hash, class _Equal, class _Alloc>
Eric Fiselier2960ae22016-02-11 11:59:44 +00001915template <class _Key, class _Args>
Eric Fiselierfdae69a2015-06-13 07:18:32 +00001916_LIBCPP_INLINE_VISIBILITY
1917pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
Eric Fiselier2960ae22016-02-11 11:59:44 +00001918__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique_key_args(_Key const& __k, _Args& __args)
Eric Fiselierfdae69a2015-06-13 07:18:32 +00001919#endif
1920{
Eric Fiselier2960ae22016-02-11 11:59:44 +00001921
1922 size_t __hash = hash_function()(__k);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001923 size_type __bc = bucket_count();
1924 bool __inserted = false;
1925 __node_pointer __nd;
1926 size_t __chash;
1927 if (__bc != 0)
1928 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001929 __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001930 __nd = __bucket_list_[__chash];
1931 if (__nd != nullptr)
1932 {
1933 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001934 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001935 __nd = __nd->__next_)
1936 {
Eric Fiselier2960ae22016-02-11 11:59:44 +00001937 if (key_eq()(__nd->__value_, __k))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001938 goto __done;
1939 }
1940 }
1941 }
1942 {
Eric Fiselier2960ae22016-02-11 11:59:44 +00001943#ifndef _LIBCPP_CXX03_LANG
1944 __node_holder __h = __construct_node_hash(__hash, _VSTD::forward<_Args>(__args)...);
1945#else
1946 __node_holder __h = __construct_node_hash(__hash, __args);
1947#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001948 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1949 {
Eric Fiselier57947ca2015-02-02 21:31:48 +00001950 rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001951 size_type(ceil(float(size() + 1) / max_load_factor()))));
1952 __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:14 +00001953 __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001954 }
1955 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1956 __node_pointer __pn = __bucket_list_[__chash];
1957 if (__pn == nullptr)
1958 {
Eric Fiselier9e9f42e2016-02-11 15:22:37 +00001959 __pn = static_cast<__node_pointer>(static_cast<__void_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001960 __h->__next_ = __pn->__next_;
1961 __pn->__next_ = __h.get();
1962 // fix up __bucket_list_
1963 __bucket_list_[__chash] = __pn;
1964 if (__h->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:14 +00001965 __bucket_list_[__constrain_hash(__h->__next_->__hash_, __bc)] = __h.get();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001966 }
1967 else
1968 {
1969 __h->__next_ = __pn->__next_;
1970 __pn->__next_ = __h.get();
1971 }
1972 __nd = __h.release();
1973 // increment size
1974 ++size();
1975 __inserted = true;
1976 }
1977__done:
Howard Hinnant39213642013-07-23 22:01:58 +00001978#if _LIBCPP_DEBUG_LEVEL >= 2
1979 return pair<iterator, bool>(iterator(__nd, this), __inserted);
1980#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001981 return pair<iterator, bool>(iterator(__nd), __inserted);
Howard Hinnant39213642013-07-23 22:01:58 +00001982#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001983}
1984
Eric Fiselier2960ae22016-02-11 11:59:44 +00001985#ifndef _LIBCPP_CXX03_LANG
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001986
1987template <class _Tp, class _Hash, class _Equal, class _Alloc>
1988template <class... _Args>
1989pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1990__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique(_Args&&... __args)
1991{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001992 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001993 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1994 if (__r.second)
1995 __h.release();
1996 return __r;
1997}
1998
1999template <class _Tp, class _Hash, class _Equal, class _Alloc>
2000template <class... _Args>
2001typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2002__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args)
2003{
Howard Hinnant0949eed2011-06-30 21:18:19 +00002004 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002005 iterator __r = __node_insert_multi(__h.get());
2006 __h.release();
2007 return __r;
2008}
2009
2010template <class _Tp, class _Hash, class _Equal, class _Alloc>
2011template <class... _Args>
2012typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2013__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi(
2014 const_iterator __p, _Args&&... __args)
2015{
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00002016#if _LIBCPP_DEBUG_LEVEL >= 2
2017 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
2018 "unordered container::emplace_hint(const_iterator, args...) called with an iterator not"
2019 " referring to this unordered container");
2020#endif
Howard Hinnant0949eed2011-06-30 21:18:19 +00002021 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002022 iterator __r = __node_insert_multi(__p, __h.get());
2023 __h.release();
2024 return __r;
2025}
2026
Eric Fiselier2960ae22016-02-11 11:59:44 +00002027#else // _LIBCPP_CXX03_LANG
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002028
2029template <class _Tp, class _Hash, class _Equal, class _Alloc>
2030typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Eric Fiselier2960ae22016-02-11 11:59:44 +00002031__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const __container_value_type& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002032{
2033 __node_holder __h = __construct_node(__x);
2034 iterator __r = __node_insert_multi(__h.get());
2035 __h.release();
2036 return __r;
2037}
2038
2039template <class _Tp, class _Hash, class _Equal, class _Alloc>
2040typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2041__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
Eric Fiselier2960ae22016-02-11 11:59:44 +00002042 const __container_value_type& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002043{
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00002044#if _LIBCPP_DEBUG_LEVEL >= 2
2045 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
2046 "unordered container::insert(const_iterator, lvalue) called with an iterator not"
2047 " referring to this unordered container");
2048#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002049 __node_holder __h = __construct_node(__x);
2050 iterator __r = __node_insert_multi(__p, __h.get());
2051 __h.release();
2052 return __r;
2053}
2054
Eric Fiselier2960ae22016-02-11 11:59:44 +00002055#endif // _LIBCPP_CXX03_LANG
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002056
2057template <class _Tp, class _Hash, class _Equal, class _Alloc>
2058void
2059__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n)
2060{
Howard Hinnant7a445152012-07-06 17:31:14 +00002061 if (__n == 1)
2062 __n = 2;
2063 else if (__n & (__n - 1))
2064 __n = __next_prime(__n);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002065 size_type __bc = bucket_count();
2066 if (__n > __bc)
2067 __rehash(__n);
Howard Hinnant7a445152012-07-06 17:31:14 +00002068 else if (__n < __bc)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002069 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00002070 __n = _VSTD::max<size_type>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002071 (
2072 __n,
Eric Fiselier57947ca2015-02-02 21:31:48 +00002073 __is_hash_power2(__bc) ? __next_hash_pow2(size_t(ceil(float(size()) / max_load_factor()))) :
2074 __next_prime(size_t(ceil(float(size()) / max_load_factor())))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002075 );
2076 if (__n < __bc)
2077 __rehash(__n);
2078 }
2079}
2080
2081template <class _Tp, class _Hash, class _Equal, class _Alloc>
2082void
2083__hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc)
2084{
Howard Hinnant39213642013-07-23 22:01:58 +00002085#if _LIBCPP_DEBUG_LEVEL >= 2
2086 __get_db()->__invalidate_all(this);
2087#endif // _LIBCPP_DEBUG_LEVEL >= 2
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002088 __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc();
2089 __bucket_list_.reset(__nbc > 0 ?
2090 __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr);
2091 __bucket_list_.get_deleter().size() = __nbc;
2092 if (__nbc > 0)
2093 {
2094 for (size_type __i = 0; __i < __nbc; ++__i)
2095 __bucket_list_[__i] = nullptr;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002096 __node_pointer __pp(static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002097 __node_pointer __cp = __pp->__next_;
2098 if (__cp != nullptr)
2099 {
Howard Hinnant7a445152012-07-06 17:31:14 +00002100 size_type __chash = __constrain_hash(__cp->__hash_, __nbc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002101 __bucket_list_[__chash] = __pp;
2102 size_type __phash = __chash;
2103 for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr;
2104 __cp = __pp->__next_)
2105 {
Howard Hinnant7a445152012-07-06 17:31:14 +00002106 __chash = __constrain_hash(__cp->__hash_, __nbc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002107 if (__chash == __phash)
2108 __pp = __cp;
2109 else
2110 {
2111 if (__bucket_list_[__chash] == nullptr)
2112 {
2113 __bucket_list_[__chash] = __pp;
2114 __pp = __cp;
2115 __phash = __chash;
2116 }
2117 else
2118 {
2119 __node_pointer __np = __cp;
2120 for (; __np->__next_ != nullptr &&
2121 key_eq()(__cp->__value_, __np->__next_->__value_);
2122 __np = __np->__next_)
2123 ;
2124 __pp->__next_ = __np->__next_;
2125 __np->__next_ = __bucket_list_[__chash]->__next_;
2126 __bucket_list_[__chash]->__next_ = __cp;
Howard Hinnant324bb032010-08-22 00:02:43 +00002127
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002128 }
2129 }
2130 }
2131 }
2132 }
2133}
2134
2135template <class _Tp, class _Hash, class _Equal, class _Alloc>
2136template <class _Key>
2137typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2138__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k)
2139{
2140 size_t __hash = hash_function()(__k);
2141 size_type __bc = bucket_count();
2142 if (__bc != 0)
2143 {
Howard Hinnant7a445152012-07-06 17:31:14 +00002144 size_t __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002145 __node_pointer __nd = __bucket_list_[__chash];
2146 if (__nd != nullptr)
2147 {
2148 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00002149 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002150 __nd = __nd->__next_)
2151 {
2152 if (key_eq()(__nd->__value_, __k))
Howard Hinnant39213642013-07-23 22:01:58 +00002153#if _LIBCPP_DEBUG_LEVEL >= 2
2154 return iterator(__nd, this);
2155#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002156 return iterator(__nd);
Howard Hinnant39213642013-07-23 22:01:58 +00002157#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002158 }
2159 }
2160 }
2161 return end();
2162}
2163
2164template <class _Tp, class _Hash, class _Equal, class _Alloc>
2165template <class _Key>
2166typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
2167__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const
2168{
2169 size_t __hash = hash_function()(__k);
2170 size_type __bc = bucket_count();
2171 if (__bc != 0)
2172 {
Howard Hinnant7a445152012-07-06 17:31:14 +00002173 size_t __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002174 __node_const_pointer __nd = __bucket_list_[__chash];
2175 if (__nd != nullptr)
2176 {
2177 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00002178 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002179 __nd = __nd->__next_)
2180 {
2181 if (key_eq()(__nd->__value_, __k))
Howard Hinnant39213642013-07-23 22:01:58 +00002182#if _LIBCPP_DEBUG_LEVEL >= 2
2183 return const_iterator(__nd, this);
2184#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002185 return const_iterator(__nd);
Howard Hinnant39213642013-07-23 22:01:58 +00002186#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002187 }
2188 }
Howard Hinnant324bb032010-08-22 00:02:43 +00002189
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002190 }
2191 return end();
2192}
2193
Eric Fiselier2960ae22016-02-11 11:59:44 +00002194#ifndef _LIBCPP_CXX03_LANG
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002195
2196template <class _Tp, class _Hash, class _Equal, class _Alloc>
2197template <class ..._Args>
2198typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
2199__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args)
2200{
Eric Fiselier2960ae22016-02-11 11:59:44 +00002201 static_assert(!__is_hash_value_type<_Args...>::value,
2202 "Construct cannot be called with a hash value type");
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002203 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00002204 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Eric Fiselier2960ae22016-02-11 11:59:44 +00002205 __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), _VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002206 __h.get_deleter().__value_constructed = true;
2207 __h->__hash_ = hash_function()(__h->__value_);
2208 __h->__next_ = nullptr;
2209 return __h;
2210}
2211
2212template <class _Tp, class _Hash, class _Equal, class _Alloc>
Eric Fiselier2960ae22016-02-11 11:59:44 +00002213template <class _First, class ..._Rest>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002214typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
Eric Fiselier2960ae22016-02-11 11:59:44 +00002215__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(
2216 size_t __hash, _First&& __f, _Rest&& ...__rest)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002217{
Eric Fiselier2960ae22016-02-11 11:59:44 +00002218 static_assert(!__is_hash_value_type<_First, _Rest...>::value,
2219 "Construct cannot be called with a hash value type");
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002220 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00002221 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Eric Fiselier2960ae22016-02-11 11:59:44 +00002222 __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_),
2223 _VSTD::forward<_First>(__f),
2224 _VSTD::forward<_Rest>(__rest)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002225 __h.get_deleter().__value_constructed = true;
2226 __h->__hash_ = __hash;
2227 __h->__next_ = nullptr;
Howard Hinnant9a894d92013-08-22 18:29:50 +00002228 return __h;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002229}
2230
Eric Fiselier2960ae22016-02-11 11:59:44 +00002231#else // _LIBCPP_CXX03_LANG
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002232
2233template <class _Tp, class _Hash, class _Equal, class _Alloc>
2234typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
Eric Fiselier2960ae22016-02-11 11:59:44 +00002235__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const __container_value_type& __v)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002236{
2237 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00002238 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Eric Fiselier2960ae22016-02-11 11:59:44 +00002239 __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002240 __h.get_deleter().__value_constructed = true;
2241 __h->__hash_ = hash_function()(__h->__value_);
2242 __h->__next_ = nullptr;
Dimitry Andric89663502015-08-19 06:43:33 +00002243 return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002244}
2245
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002246template <class _Tp, class _Hash, class _Equal, class _Alloc>
2247typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
Eric Fiselier2960ae22016-02-11 11:59:44 +00002248__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node_hash(size_t __hash,
2249 const __container_value_type& __v)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002250{
2251 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00002252 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Eric Fiselier2960ae22016-02-11 11:59:44 +00002253 __node_traits::construct(__na, _NodeTypes::__get_ptr(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002254 __h.get_deleter().__value_constructed = true;
2255 __h->__hash_ = __hash;
2256 __h->__next_ = nullptr;
Dimitry Andric89663502015-08-19 06:43:33 +00002257 return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002258}
2259
Eric Fiselier2960ae22016-02-11 11:59:44 +00002260#endif // _LIBCPP_CXX03_LANG
2261
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002262template <class _Tp, class _Hash, class _Equal, class _Alloc>
2263typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2264__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p)
2265{
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002266 __node_pointer __np = __p.__node_;
Howard Hinnant39213642013-07-23 22:01:58 +00002267#if _LIBCPP_DEBUG_LEVEL >= 2
2268 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
2269 "unordered container erase(iterator) called with an iterator not"
2270 " referring to this container");
2271 _LIBCPP_ASSERT(__p != end(),
2272 "unordered container erase(iterator) called with a non-dereferenceable iterator");
2273 iterator __r(__np, this);
2274#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002275 iterator __r(__np);
Howard Hinnant39213642013-07-23 22:01:58 +00002276#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002277 ++__r;
2278 remove(__p);
2279 return __r;
2280}
2281
2282template <class _Tp, class _Hash, class _Equal, class _Alloc>
2283typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2284__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first,
2285 const_iterator __last)
2286{
Howard Hinnant39213642013-07-23 22:01:58 +00002287#if _LIBCPP_DEBUG_LEVEL >= 2
2288 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this,
2289 "unodered container::erase(iterator, iterator) called with an iterator not"
2290 " referring to this unodered container");
2291 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__last) == this,
2292 "unodered container::erase(iterator, iterator) called with an iterator not"
2293 " referring to this unodered container");
2294#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002295 for (const_iterator __p = __first; __first != __last; __p = __first)
2296 {
2297 ++__first;
2298 erase(__p);
2299 }
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002300 __node_pointer __np = __last.__node_;
Howard Hinnant39213642013-07-23 22:01:58 +00002301#if _LIBCPP_DEBUG_LEVEL >= 2
2302 return iterator (__np, this);
2303#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002304 return iterator (__np);
Howard Hinnant39213642013-07-23 22:01:58 +00002305#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002306}
2307
2308template <class _Tp, class _Hash, class _Equal, class _Alloc>
2309template <class _Key>
2310typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2311__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k)
2312{
2313 iterator __i = find(__k);
2314 if (__i == end())
2315 return 0;
2316 erase(__i);
2317 return 1;
2318}
2319
2320template <class _Tp, class _Hash, class _Equal, class _Alloc>
2321template <class _Key>
2322typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2323__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k)
2324{
2325 size_type __r = 0;
2326 iterator __i = find(__k);
2327 if (__i != end())
2328 {
2329 iterator __e = end();
2330 do
2331 {
2332 erase(__i++);
2333 ++__r;
2334 } while (__i != __e && key_eq()(*__i, __k));
2335 }
2336 return __r;
2337}
2338
2339template <class _Tp, class _Hash, class _Equal, class _Alloc>
2340typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00002341__hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002342{
2343 // current node
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002344 __node_pointer __cn = __p.__node_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002345 size_type __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:14 +00002346 size_t __chash = __constrain_hash(__cn->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002347 // find previous node
2348 __node_pointer __pn = __bucket_list_[__chash];
2349 for (; __pn->__next_ != __cn; __pn = __pn->__next_)
2350 ;
2351 // Fix up __bucket_list_
2352 // if __pn is not in same bucket (before begin is not in same bucket) &&
2353 // if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002354 if (__pn == static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()))
2355 || __constrain_hash(__pn->__hash_, __bc) != __chash)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002356 {
Howard Hinnant7a445152012-07-06 17:31:14 +00002357 if (__cn->__next_ == nullptr || __constrain_hash(__cn->__next_->__hash_, __bc) != __chash)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002358 __bucket_list_[__chash] = nullptr;
2359 }
2360 // if __cn->__next_ is not in same bucket (nullptr is in same bucket)
2361 if (__cn->__next_ != nullptr)
2362 {
Howard Hinnant7a445152012-07-06 17:31:14 +00002363 size_t __nhash = __constrain_hash(__cn->__next_->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002364 if (__nhash != __chash)
2365 __bucket_list_[__nhash] = __pn;
2366 }
2367 // remove __cn
2368 __pn->__next_ = __cn->__next_;
2369 __cn->__next_ = nullptr;
2370 --size();
Howard Hinnant39213642013-07-23 22:01:58 +00002371#if _LIBCPP_DEBUG_LEVEL >= 2
2372 __c_node* __c = __get_db()->__find_c_and_lock(this);
2373 for (__i_node** __p = __c->end_; __p != __c->beg_; )
2374 {
2375 --__p;
2376 iterator* __i = static_cast<iterator*>((*__p)->__i_);
2377 if (__i->__node_ == __cn)
2378 {
2379 (*__p)->__c_ = nullptr;
2380 if (--__c->end_ != __p)
2381 memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*));
2382 }
2383 }
2384 __get_db()->unlock();
2385#endif
Howard Hinnant99968442011-11-29 18:15:50 +00002386 return __node_holder(__cn, _Dp(__node_alloc(), true));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002387}
2388
2389template <class _Tp, class _Hash, class _Equal, class _Alloc>
2390template <class _Key>
Evgeniy Stepanova3b25f82015-11-07 01:22:13 +00002391inline
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002392typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2393__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const
2394{
2395 return static_cast<size_type>(find(__k) != end());
2396}
2397
2398template <class _Tp, class _Hash, class _Equal, class _Alloc>
2399template <class _Key>
2400typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2401__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const
2402{
2403 size_type __r = 0;
2404 const_iterator __i = find(__k);
2405 if (__i != end())
2406 {
2407 const_iterator __e = end();
2408 do
2409 {
2410 ++__i;
2411 ++__r;
2412 } while (__i != __e && key_eq()(*__i, __k));
2413 }
2414 return __r;
2415}
2416
2417template <class _Tp, class _Hash, class _Equal, class _Alloc>
2418template <class _Key>
2419pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
2420 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
2421__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
2422 const _Key& __k)
2423{
2424 iterator __i = find(__k);
2425 iterator __j = __i;
2426 if (__i != end())
2427 ++__j;
2428 return pair<iterator, iterator>(__i, __j);
2429}
2430
2431template <class _Tp, class _Hash, class _Equal, class _Alloc>
2432template <class _Key>
2433pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
2434 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
2435__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
2436 const _Key& __k) const
2437{
2438 const_iterator __i = find(__k);
2439 const_iterator __j = __i;
2440 if (__i != end())
2441 ++__j;
2442 return pair<const_iterator, const_iterator>(__i, __j);
2443}
2444
2445template <class _Tp, class _Hash, class _Equal, class _Alloc>
2446template <class _Key>
2447pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
2448 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
2449__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
2450 const _Key& __k)
2451{
2452 iterator __i = find(__k);
2453 iterator __j = __i;
2454 if (__i != end())
2455 {
2456 iterator __e = end();
2457 do
2458 {
2459 ++__j;
2460 } while (__j != __e && key_eq()(*__j, __k));
2461 }
2462 return pair<iterator, iterator>(__i, __j);
2463}
2464
2465template <class _Tp, class _Hash, class _Equal, class _Alloc>
2466template <class _Key>
2467pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
2468 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
2469__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
2470 const _Key& __k) const
2471{
2472 const_iterator __i = find(__k);
2473 const_iterator __j = __i;
2474 if (__i != end())
2475 {
2476 const_iterator __e = end();
2477 do
2478 {
2479 ++__j;
2480 } while (__j != __e && key_eq()(*__j, __k));
2481 }
2482 return pair<const_iterator, const_iterator>(__i, __j);
2483}
2484
2485template <class _Tp, class _Hash, class _Equal, class _Alloc>
2486void
2487__hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
Eric Fiselier692177d2015-07-18 20:40:46 +00002488#if _LIBCPP_STD_VER <= 11
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00002489 _NOEXCEPT_(
Marshall Clow7d914d12015-07-13 20:04:56 +00002490 __is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value
Marshall Clow7d914d12015-07-13 20:04:56 +00002491 && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value
2492 || __is_nothrow_swappable<__pointer_allocator>::value)
2493 && (!__node_traits::propagate_on_container_swap::value
2494 || __is_nothrow_swappable<__node_allocator>::value)
Marshall Clow7d914d12015-07-13 20:04:56 +00002495 )
Eric Fiselier692177d2015-07-18 20:40:46 +00002496#else
2497 _NOEXCEPT_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value)
2498#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002499{
2500 {
2501 __node_pointer_pointer __npp = __bucket_list_.release();
2502 __bucket_list_.reset(__u.__bucket_list_.release());
2503 __u.__bucket_list_.reset(__npp);
2504 }
Howard Hinnant0949eed2011-06-30 21:18:19 +00002505 _VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
Marshall Clow7d914d12015-07-13 20:04:56 +00002506 __swap_allocator(__bucket_list_.get_deleter().__alloc(),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002507 __u.__bucket_list_.get_deleter().__alloc());
Marshall Clow7d914d12015-07-13 20:04:56 +00002508 __swap_allocator(__node_alloc(), __u.__node_alloc());
Howard Hinnant0949eed2011-06-30 21:18:19 +00002509 _VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002510 __p2_.swap(__u.__p2_);
2511 __p3_.swap(__u.__p3_);
2512 if (size() > 0)
Howard Hinnant7a445152012-07-06 17:31:14 +00002513 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002514 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002515 if (__u.size() > 0)
Howard Hinnant7a445152012-07-06 17:31:14 +00002516 __u.__bucket_list_[__constrain_hash(__u.__p1_.first().__next_->__hash_, __u.bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002517 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__u.__p1_.first()));
Howard Hinnant39213642013-07-23 22:01:58 +00002518#if _LIBCPP_DEBUG_LEVEL >= 2
2519 __get_db()->swap(this, &__u);
2520#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002521}
2522
2523template <class _Tp, class _Hash, class _Equal, class _Alloc>
2524typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2525__hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const
2526{
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00002527 _LIBCPP_ASSERT(__n < bucket_count(),
2528 "unordered container::bucket_size(n) called with n >= bucket_count()");
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002529 __node_const_pointer __np = __bucket_list_[__n];
2530 size_type __bc = bucket_count();
2531 size_type __r = 0;
2532 if (__np != nullptr)
2533 {
2534 for (__np = __np->__next_; __np != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00002535 __constrain_hash(__np->__hash_, __bc) == __n;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002536 __np = __np->__next_, ++__r)
2537 ;
2538 }
2539 return __r;
2540}
2541
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00002542template <class _Tp, class _Hash, class _Equal, class _Alloc>
2543inline _LIBCPP_INLINE_VISIBILITY
2544void
2545swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x,
2546 __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y)
2547 _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
2548{
2549 __x.swap(__y);
2550}
2551
Howard Hinnant39213642013-07-23 22:01:58 +00002552#if _LIBCPP_DEBUG_LEVEL >= 2
2553
2554template <class _Tp, class _Hash, class _Equal, class _Alloc>
2555bool
2556__hash_table<_Tp, _Hash, _Equal, _Alloc>::__dereferenceable(const const_iterator* __i) const
2557{
2558 return __i->__node_ != nullptr;
2559}
2560
2561template <class _Tp, class _Hash, class _Equal, class _Alloc>
2562bool
2563__hash_table<_Tp, _Hash, _Equal, _Alloc>::__decrementable(const const_iterator*) const
2564{
2565 return false;
2566}
2567
2568template <class _Tp, class _Hash, class _Equal, class _Alloc>
2569bool
2570__hash_table<_Tp, _Hash, _Equal, _Alloc>::__addable(const const_iterator*, ptrdiff_t) const
2571{
2572 return false;
2573}
2574
2575template <class _Tp, class _Hash, class _Equal, class _Alloc>
2576bool
2577__hash_table<_Tp, _Hash, _Equal, _Alloc>::__subscriptable(const const_iterator*, ptrdiff_t) const
2578{
2579 return false;
2580}
2581
2582#endif // _LIBCPP_DEBUG_LEVEL >= 2
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002583_LIBCPP_END_NAMESPACE_STD
2584
2585#endif // _LIBCPP__HASH_TABLE