blob: 0f722948f5492a91420f9c9583de9676dc812b90 [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>
20
Howard Hinnant66c6f972011-11-29 16:45:27 +000021#include <__undef_min_max>
22
Howard Hinnant08e17472011-10-17 20:05:10 +000023#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000024#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:10 +000025#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000026
27_LIBCPP_BEGIN_NAMESPACE_STD
28
Howard Hinnant83eade62013-03-06 23:30:19 +000029_LIBCPP_FUNC_VIS
Howard Hinnant2b1b2d42011-06-14 19:58:17 +000030size_t __next_prime(size_t __n);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000031
32template <class _NodePtr>
33struct __hash_node_base
34{
35 typedef __hash_node_base __first_node;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000036
Howard Hinnantdf85e572011-02-27 18:02:02 +000037 _NodePtr __next_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000038
Howard Hinnant5f2f14c2011-06-04 18:54:24 +000039 _LIBCPP_INLINE_VISIBILITY __hash_node_base() _NOEXCEPT : __next_(nullptr) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000040};
41
42template <class _Tp, class _VoidPtr>
43struct __hash_node
44 : public __hash_node_base
45 <
46 typename pointer_traits<_VoidPtr>::template
47#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
48 rebind<__hash_node<_Tp, _VoidPtr> >
49#else
50 rebind<__hash_node<_Tp, _VoidPtr> >::other
51#endif
52 >
53{
54 typedef _Tp value_type;
55
56 size_t __hash_;
57 value_type __value_;
58};
59
Howard Hinnant7a445152012-07-06 17:31:14 +000060inline _LIBCPP_INLINE_VISIBILITY
61bool
62__is_power2(size_t __bc)
63{
64 return __bc > 2 && !(__bc & (__bc - 1));
65}
66
67inline _LIBCPP_INLINE_VISIBILITY
68size_t
69__constrain_hash(size_t __h, size_t __bc)
70{
71 return !(__bc & (__bc - 1)) ? __h & (__bc - 1) : __h % __bc;
72}
73
74inline _LIBCPP_INLINE_VISIBILITY
75size_t
76__next_pow2(size_t __n)
77{
78 return size_t(1) << (std::numeric_limits<size_t>::digits - __clz(__n-1));
79}
80
Howard Hinnant2b1b2d42011-06-14 19:58:17 +000081template <class _Tp, class _Hash, class _Equal, class _Alloc> class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19 +000082template <class _ConstNodePtr> class _LIBCPP_TYPE_VIS __hash_const_iterator;
83template <class _HashIterator> class _LIBCPP_TYPE_VIS __hash_map_iterator;
84template <class _HashIterator> class _LIBCPP_TYPE_VIS __hash_map_const_iterator;
Howard Hinnant2b1b2d42011-06-14 19:58:17 +000085template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
Howard Hinnant83eade62013-03-06 23:30:19 +000086 class _LIBCPP_TYPE_VIS unordered_map;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000087
88template <class _NodePtr>
Howard Hinnant83eade62013-03-06 23:30:19 +000089class _LIBCPP_TYPE_VIS __hash_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000090{
91 typedef _NodePtr __node_pointer;
92
93 __node_pointer __node_;
94
95public:
96 typedef forward_iterator_tag iterator_category;
97 typedef typename pointer_traits<__node_pointer>::element_type::value_type value_type;
98 typedef typename pointer_traits<__node_pointer>::difference_type difference_type;
99 typedef value_type& reference;
100 typedef typename pointer_traits<__node_pointer>::template
101#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
102 rebind<value_type>
103#else
104 rebind<value_type>::other
105#endif
106 pointer;
107
Howard Hinnant39213642013-07-23 22:01:58 +0000108 _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT
109 {
110#if _LIBCPP_DEBUG_LEVEL >= 2
111 __get_db()->__insert_i(this);
112#endif
113 }
114
115#if _LIBCPP_DEBUG_LEVEL >= 2
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000116
Howard Hinnant99acc502010-09-21 17:32:39 +0000117 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58 +0000118 __hash_iterator(const __hash_iterator& __i)
119 : __node_(__i.__node_)
120 {
121 __get_db()->__iterator_copy(this, &__i);
122 }
123
Howard Hinnant99acc502010-09-21 17:32:39 +0000124 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58 +0000125 ~__hash_iterator()
126 {
127 __get_db()->__erase_i(this);
128 }
129
130 _LIBCPP_INLINE_VISIBILITY
131 __hash_iterator& operator=(const __hash_iterator& __i)
132 {
133 if (this != &__i)
134 {
135 __get_db()->__iterator_copy(this, &__i);
136 __node_ = __i.__node_;
137 }
138 return *this;
139 }
140
141#endif // _LIBCPP_DEBUG_LEVEL >= 2
142
143 _LIBCPP_INLINE_VISIBILITY
144 reference operator*() const
145 {
146#if _LIBCPP_DEBUG_LEVEL >= 2
147 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
148 "Attempted to dereference a non-dereferenceable unordered container iterator");
149#endif
150 return __node_->__value_;
151 }
152 _LIBCPP_INLINE_VISIBILITY
153 pointer operator->() const
154 {
155#if _LIBCPP_DEBUG_LEVEL >= 2
156 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
157 "Attempted to dereference a non-dereferenceable unordered container iterator");
158#endif
159 return pointer_traits<pointer>::pointer_to(__node_->__value_);
160 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000161
Howard Hinnant99acc502010-09-21 17:32:39 +0000162 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000163 __hash_iterator& operator++()
164 {
Howard Hinnant39213642013-07-23 22:01:58 +0000165#if _LIBCPP_DEBUG_LEVEL >= 2
166 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
167 "Attempted to increment non-incrementable unordered container iterator");
168#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000169 __node_ = __node_->__next_;
170 return *this;
171 }
172
Howard Hinnant99acc502010-09-21 17:32:39 +0000173 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000174 __hash_iterator operator++(int)
175 {
176 __hash_iterator __t(*this);
177 ++(*this);
178 return __t;
179 }
180
Howard Hinnant99acc502010-09-21 17:32:39 +0000181 friend _LIBCPP_INLINE_VISIBILITY
182 bool operator==(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58 +0000183 {
184#if _LIBCPP_DEBUG_LEVEL >= 2
185 _LIBCPP_ASSERT(__get_const_db()->__comparable(&__x, &__y),
186 "Attempted to compare non-comparable unordered container iterator");
187#endif
188 return __x.__node_ == __y.__node_;
189 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000190 friend _LIBCPP_INLINE_VISIBILITY
191 bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58 +0000192 {return !(__x == __y);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000193
194private:
Howard Hinnant39213642013-07-23 22:01:58 +0000195#if _LIBCPP_DEBUG_LEVEL >= 2
196 _LIBCPP_INLINE_VISIBILITY
197 __hash_iterator(__node_pointer __node, const void* __c) _NOEXCEPT
198 : __node_(__node)
199 {
200 __get_db()->__insert_ic(this, __c);
201 }
202#else
Howard Hinnant99acc502010-09-21 17:32:39 +0000203 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000204 __hash_iterator(__node_pointer __node) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000205 : __node_(__node)
206 {}
Howard Hinnant39213642013-07-23 22:01:58 +0000207#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000208
209 template <class, class, class, class> friend class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19 +0000210 template <class> friend class _LIBCPP_TYPE_VIS __hash_const_iterator;
211 template <class> friend class _LIBCPP_TYPE_VIS __hash_map_iterator;
212 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_map;
213 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000214};
215
216template <class _ConstNodePtr>
Howard Hinnant83eade62013-03-06 23:30:19 +0000217class _LIBCPP_TYPE_VIS __hash_const_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000218{
219 typedef _ConstNodePtr __node_pointer;
220
221 __node_pointer __node_;
222
223 typedef typename remove_const<
224 typename pointer_traits<__node_pointer>::element_type
225 >::type __node;
226
227public:
228 typedef forward_iterator_tag iterator_category;
229 typedef typename __node::value_type value_type;
230 typedef typename pointer_traits<__node_pointer>::difference_type difference_type;
231 typedef const value_type& reference;
232 typedef typename pointer_traits<__node_pointer>::template
233#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
234 rebind<const value_type>
235#else
236 rebind<const value_type>::other
237#endif
238 pointer;
239 typedef typename pointer_traits<__node_pointer>::template
240#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
241 rebind<__node>
242#else
243 rebind<__node>::other
244#endif
245 __non_const_node_pointer;
246 typedef __hash_iterator<__non_const_node_pointer> __non_const_iterator;
247
Howard Hinnant39213642013-07-23 22:01:58 +0000248 _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT
249 {
250#if _LIBCPP_DEBUG_LEVEL >= 2
251 __get_db()->__insert_i(this);
252#endif
253 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000254 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000255 __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000256 : __node_(__x.__node_)
Howard Hinnant39213642013-07-23 22:01:58 +0000257 {
258#if _LIBCPP_DEBUG_LEVEL >= 2
259 __get_db()->__iterator_copy(this, &__x);
260#endif
261 }
262
263#if _LIBCPP_DEBUG_LEVEL >= 2
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000264
Howard Hinnant99acc502010-09-21 17:32:39 +0000265 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58 +0000266 __hash_const_iterator(const __hash_const_iterator& __i)
267 : __node_(__i.__node_)
268 {
269 __get_db()->__iterator_copy(this, &__i);
270 }
271
Howard Hinnant99acc502010-09-21 17:32:39 +0000272 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58 +0000273 ~__hash_const_iterator()
274 {
275 __get_db()->__erase_i(this);
276 }
277
278 _LIBCPP_INLINE_VISIBILITY
279 __hash_const_iterator& operator=(const __hash_const_iterator& __i)
280 {
281 if (this != &__i)
282 {
283 __get_db()->__iterator_copy(this, &__i);
284 __node_ = __i.__node_;
285 }
286 return *this;
287 }
288
289#endif // _LIBCPP_DEBUG_LEVEL >= 2
290
291 _LIBCPP_INLINE_VISIBILITY
292 reference operator*() const
293 {
294#if _LIBCPP_DEBUG_LEVEL >= 2
295 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
296 "Attempted to dereference a non-dereferenceable unordered container const_iterator");
297#endif
298 return __node_->__value_;
299 }
300 _LIBCPP_INLINE_VISIBILITY
301 pointer operator->() const
302 {
303#if _LIBCPP_DEBUG_LEVEL >= 2
304 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
305 "Attempted to dereference a non-dereferenceable unordered container const_iterator");
306#endif
307 return pointer_traits<pointer>::pointer_to(__node_->__value_);
308 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000309
Howard Hinnant99acc502010-09-21 17:32:39 +0000310 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000311 __hash_const_iterator& operator++()
312 {
Howard Hinnant39213642013-07-23 22:01:58 +0000313#if _LIBCPP_DEBUG_LEVEL >= 2
314 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
315 "Attempted to increment non-incrementable unordered container const_iterator");
316#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000317 __node_ = __node_->__next_;
318 return *this;
319 }
320
Howard Hinnant99acc502010-09-21 17:32:39 +0000321 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000322 __hash_const_iterator operator++(int)
323 {
324 __hash_const_iterator __t(*this);
325 ++(*this);
326 return __t;
327 }
328
Howard Hinnant99acc502010-09-21 17:32:39 +0000329 friend _LIBCPP_INLINE_VISIBILITY
330 bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58 +0000331 {
332#if _LIBCPP_DEBUG_LEVEL >= 2
333 _LIBCPP_ASSERT(__get_const_db()->__comparable(&__x, &__y),
334 "Attempted to compare non-comparable unordered container const_iterator");
335#endif
336 return __x.__node_ == __y.__node_;
337 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000338 friend _LIBCPP_INLINE_VISIBILITY
339 bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58 +0000340 {return !(__x == __y);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000341
342private:
Howard Hinnant39213642013-07-23 22:01:58 +0000343#if _LIBCPP_DEBUG_LEVEL >= 2
344 _LIBCPP_INLINE_VISIBILITY
345 __hash_const_iterator(__node_pointer __node, const void* __c) _NOEXCEPT
346 : __node_(__node)
347 {
348 __get_db()->__insert_ic(this, __c);
349 }
350#else
Howard Hinnant99acc502010-09-21 17:32:39 +0000351 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000352 __hash_const_iterator(__node_pointer __node) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000353 : __node_(__node)
354 {}
Howard Hinnant39213642013-07-23 22:01:58 +0000355#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000356
357 template <class, class, class, class> friend class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19 +0000358 template <class> friend class _LIBCPP_TYPE_VIS __hash_map_const_iterator;
359 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_map;
360 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000361};
362
Howard Hinnant83eade62013-03-06 23:30:19 +0000363template <class _ConstNodePtr> class _LIBCPP_TYPE_VIS __hash_const_local_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000364
365template <class _NodePtr>
Howard Hinnant83eade62013-03-06 23:30:19 +0000366class _LIBCPP_TYPE_VIS __hash_local_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000367{
368 typedef _NodePtr __node_pointer;
369
370 __node_pointer __node_;
371 size_t __bucket_;
372 size_t __bucket_count_;
373
374 typedef pointer_traits<__node_pointer> __pointer_traits;
375public:
376 typedef forward_iterator_tag iterator_category;
377 typedef typename __pointer_traits::element_type::value_type value_type;
378 typedef typename __pointer_traits::difference_type difference_type;
379 typedef value_type& reference;
380 typedef typename __pointer_traits::template
381#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
382 rebind<value_type>
383#else
384 rebind<value_type>::other
385#endif
386 pointer;
387
Howard Hinnant39213642013-07-23 22:01:58 +0000388 _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT
389 {
390#if _LIBCPP_DEBUG_LEVEL >= 2
391 __get_db()->__insert_i(this);
392#endif
393 }
394
395#if _LIBCPP_DEBUG_LEVEL >= 2
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000396
Howard Hinnant99acc502010-09-21 17:32:39 +0000397 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58 +0000398 __hash_local_iterator(const __hash_local_iterator& __i)
399 : __node_(__i.__node_),
400 __bucket_(__i.__bucket_),
401 __bucket_count_(__i.__bucket_count_)
402 {
403 __get_db()->__iterator_copy(this, &__i);
404 }
405
Howard Hinnant99acc502010-09-21 17:32:39 +0000406 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58 +0000407 ~__hash_local_iterator()
408 {
409 __get_db()->__erase_i(this);
410 }
411
412 _LIBCPP_INLINE_VISIBILITY
413 __hash_local_iterator& operator=(const __hash_local_iterator& __i)
414 {
415 if (this != &__i)
416 {
417 __get_db()->__iterator_copy(this, &__i);
418 __node_ = __i.__node_;
419 __bucket_ = __i.__bucket_;
420 __bucket_count_ = __i.__bucket_count_;
421 }
422 return *this;
423 }
424
425#endif // _LIBCPP_DEBUG_LEVEL >= 2
426
427 _LIBCPP_INLINE_VISIBILITY
428 reference operator*() const
429 {
430#if _LIBCPP_DEBUG_LEVEL >= 2
431 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
432 "Attempted to dereference a non-dereferenceable unordered container local_iterator");
433#endif
434 return __node_->__value_;
435 }
436 _LIBCPP_INLINE_VISIBILITY
437 pointer operator->() const
438 {
439#if _LIBCPP_DEBUG_LEVEL >= 2
440 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
441 "Attempted to dereference a non-dereferenceable unordered container local_iterator");
442#endif
443 return pointer_traits<pointer>::pointer_to(__node_->__value_);
444 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000445
Howard Hinnant99acc502010-09-21 17:32:39 +0000446 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000447 __hash_local_iterator& operator++()
448 {
Howard Hinnant39213642013-07-23 22:01:58 +0000449#if _LIBCPP_DEBUG_LEVEL >= 2
450 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
451 "Attempted to increment non-incrementable unordered container local_iterator");
452#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000453 __node_ = __node_->__next_;
Howard Hinnant7a445152012-07-06 17:31:14 +0000454 if (__node_ != nullptr && __constrain_hash(__node_->__hash_, __bucket_count_) != __bucket_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000455 __node_ = nullptr;
456 return *this;
457 }
458
Howard Hinnant99acc502010-09-21 17:32:39 +0000459 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000460 __hash_local_iterator operator++(int)
461 {
462 __hash_local_iterator __t(*this);
463 ++(*this);
464 return __t;
465 }
466
Howard Hinnant99acc502010-09-21 17:32:39 +0000467 friend _LIBCPP_INLINE_VISIBILITY
468 bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58 +0000469 {
470#if _LIBCPP_DEBUG_LEVEL >= 2
471 _LIBCPP_ASSERT(__get_const_db()->__comparable(&__x, &__y),
472 "Attempted to compare non-comparable unordered container local_iterator");
473#endif
474 return __x.__node_ == __y.__node_;
475 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000476 friend _LIBCPP_INLINE_VISIBILITY
477 bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58 +0000478 {return !(__x == __y);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000479
480private:
Howard Hinnant39213642013-07-23 22:01:58 +0000481#if _LIBCPP_DEBUG_LEVEL >= 2
482 _LIBCPP_INLINE_VISIBILITY
483 __hash_local_iterator(__node_pointer __node, size_t __bucket,
484 size_t __bucket_count, const void* __c) _NOEXCEPT
485 : __node_(__node),
486 __bucket_(__bucket),
487 __bucket_count_(__bucket_count)
488 {
489 __get_db()->__insert_ic(this, __c);
490 if (__node_ != nullptr)
491 __node_ = __node_->__next_;
492 }
493#else
Howard Hinnant99acc502010-09-21 17:32:39 +0000494 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000495 __hash_local_iterator(__node_pointer __node, size_t __bucket,
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000496 size_t __bucket_count) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000497 : __node_(__node),
498 __bucket_(__bucket),
499 __bucket_count_(__bucket_count)
500 {
501 if (__node_ != nullptr)
502 __node_ = __node_->__next_;
503 }
Howard Hinnant39213642013-07-23 22:01:58 +0000504#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000505 template <class, class, class, class> friend class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19 +0000506 template <class> friend class _LIBCPP_TYPE_VIS __hash_const_local_iterator;
507 template <class> friend class _LIBCPP_TYPE_VIS __hash_map_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000508};
509
510template <class _ConstNodePtr>
Howard Hinnant83eade62013-03-06 23:30:19 +0000511class _LIBCPP_TYPE_VIS __hash_const_local_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000512{
513 typedef _ConstNodePtr __node_pointer;
514
515 __node_pointer __node_;
516 size_t __bucket_;
517 size_t __bucket_count_;
518
519 typedef pointer_traits<__node_pointer> __pointer_traits;
520 typedef typename __pointer_traits::element_type __node;
521 typedef typename remove_const<__node>::type __non_const_node;
522 typedef typename pointer_traits<__node_pointer>::template
523#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
524 rebind<__non_const_node>
525#else
526 rebind<__non_const_node>::other
527#endif
528 __non_const_node_pointer;
529 typedef __hash_local_iterator<__non_const_node_pointer>
530 __non_const_iterator;
531public:
532 typedef forward_iterator_tag iterator_category;
533 typedef typename remove_const<
534 typename __pointer_traits::element_type::value_type
535 >::type value_type;
536 typedef typename __pointer_traits::difference_type difference_type;
537 typedef const value_type& reference;
538 typedef typename __pointer_traits::template
539#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
540 rebind<const value_type>
541#else
542 rebind<const value_type>::other
543#endif
544 pointer;
545
Howard Hinnant39213642013-07-23 22:01:58 +0000546 _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT
547 {
548#if _LIBCPP_DEBUG_LEVEL >= 2
549 __get_db()->__insert_i(this);
550#endif
551 }
552
Howard Hinnant99acc502010-09-21 17:32:39 +0000553 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000554 __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000555 : __node_(__x.__node_),
556 __bucket_(__x.__bucket_),
557 __bucket_count_(__x.__bucket_count_)
Howard Hinnant39213642013-07-23 22:01:58 +0000558 {
559#if _LIBCPP_DEBUG_LEVEL >= 2
560 __get_db()->__iterator_copy(this, &__x);
561#endif
562 }
563
564#if _LIBCPP_DEBUG_LEVEL >= 2
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000565
Howard Hinnant99acc502010-09-21 17:32:39 +0000566 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58 +0000567 __hash_const_local_iterator(const __hash_const_local_iterator& __i)
568 : __node_(__i.__node_),
569 __bucket_(__i.__bucket_),
570 __bucket_count_(__i.__bucket_count_)
571 {
572 __get_db()->__iterator_copy(this, &__i);
573 }
574
Howard Hinnant99acc502010-09-21 17:32:39 +0000575 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58 +0000576 ~__hash_const_local_iterator()
577 {
578 __get_db()->__erase_i(this);
579 }
580
581 _LIBCPP_INLINE_VISIBILITY
582 __hash_const_local_iterator& operator=(const __hash_const_local_iterator& __i)
583 {
584 if (this != &__i)
585 {
586 __get_db()->__iterator_copy(this, &__i);
587 __node_ = __i.__node_;
588 __bucket_ = __i.__bucket_;
589 __bucket_count_ = __i.__bucket_count_;
590 }
591 return *this;
592 }
593
594#endif // _LIBCPP_DEBUG_LEVEL >= 2
595
596 _LIBCPP_INLINE_VISIBILITY
597 reference operator*() const
598 {
599#if _LIBCPP_DEBUG_LEVEL >= 2
600 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
601 "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
602#endif
603 return __node_->__value_;
604 }
605 _LIBCPP_INLINE_VISIBILITY
606 pointer operator->() const
607 {
608#if _LIBCPP_DEBUG_LEVEL >= 2
609 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
610 "Attempted to dereference a non-dereferenceable unordered container const_local_iterator");
611#endif
612 return pointer_traits<pointer>::pointer_to(__node_->__value_);
613 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000614
Howard Hinnant99acc502010-09-21 17:32:39 +0000615 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000616 __hash_const_local_iterator& operator++()
617 {
Howard Hinnant39213642013-07-23 22:01:58 +0000618#if _LIBCPP_DEBUG_LEVEL >= 2
619 _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this),
620 "Attempted to increment non-incrementable unordered container const_local_iterator");
621#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000622 __node_ = __node_->__next_;
Howard Hinnant7a445152012-07-06 17:31:14 +0000623 if (__node_ != nullptr && __constrain_hash(__node_->__hash_, __bucket_count_) != __bucket_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000624 __node_ = nullptr;
625 return *this;
626 }
627
Howard Hinnant99acc502010-09-21 17:32:39 +0000628 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000629 __hash_const_local_iterator operator++(int)
630 {
631 __hash_const_local_iterator __t(*this);
632 ++(*this);
633 return __t;
634 }
635
Howard Hinnant99acc502010-09-21 17:32:39 +0000636 friend _LIBCPP_INLINE_VISIBILITY
637 bool operator==(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58 +0000638 {
639#if _LIBCPP_DEBUG_LEVEL >= 2
640 _LIBCPP_ASSERT(__get_const_db()->__comparable(&__x, &__y),
641 "Attempted to compare non-comparable unordered container local_const_iterator");
642#endif
643 return __x.__node_ == __y.__node_;
644 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000645 friend _LIBCPP_INLINE_VISIBILITY
646 bool operator!=(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58 +0000647 {return !(__x == __y);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000648
649private:
Howard Hinnant39213642013-07-23 22:01:58 +0000650#if _LIBCPP_DEBUG_LEVEL >= 2
651 _LIBCPP_INLINE_VISIBILITY
652 __hash_const_local_iterator(__node_pointer __node, size_t __bucket,
653 size_t __bucket_count, const void* __c) _NOEXCEPT
654 : __node_(__node),
655 __bucket_(__bucket),
656 __bucket_count_(__bucket_count)
657 {
658 __get_db()->__insert_ic(this, __c);
659 if (__node_ != nullptr)
660 __node_ = __node_->__next_;
661 }
662#else
Howard Hinnant99acc502010-09-21 17:32:39 +0000663 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000664 __hash_const_local_iterator(__node_pointer __node, size_t __bucket,
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000665 size_t __bucket_count) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000666 : __node_(__node),
667 __bucket_(__bucket),
668 __bucket_count_(__bucket_count)
669 {
670 if (__node_ != nullptr)
671 __node_ = __node_->__next_;
672 }
Howard Hinnant39213642013-07-23 22:01:58 +0000673#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000674 template <class, class, class, class> friend class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19 +0000675 template <class> friend class _LIBCPP_TYPE_VIS __hash_map_const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000676};
677
678template <class _Alloc>
679class __bucket_list_deallocator
680{
681 typedef _Alloc allocator_type;
682 typedef allocator_traits<allocator_type> __alloc_traits;
683 typedef typename __alloc_traits::size_type size_type;
684
685 __compressed_pair<size_type, allocator_type> __data_;
686public:
687 typedef typename __alloc_traits::pointer pointer;
688
Howard Hinnant99acc502010-09-21 17:32:39 +0000689 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000690 __bucket_list_deallocator()
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000691 _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000692 : __data_(0) {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000693
694 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000695 __bucket_list_deallocator(const allocator_type& __a, size_type __size)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000696 _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000697 : __data_(__size, __a) {}
698
Howard Hinnant73d21a42010-09-04 23:28:19 +0000699#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000700
Howard Hinnant99acc502010-09-21 17:32:39 +0000701 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000702 __bucket_list_deallocator(__bucket_list_deallocator&& __x)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000703 _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000704 : __data_(_VSTD::move(__x.__data_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000705 {
706 __x.size() = 0;
707 }
708
Howard Hinnant73d21a42010-09-04 23:28:19 +0000709#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000710
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000711 _LIBCPP_INLINE_VISIBILITY
712 size_type& size() _NOEXCEPT {return __data_.first();}
713 _LIBCPP_INLINE_VISIBILITY
714 size_type size() const _NOEXCEPT {return __data_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000715
Howard Hinnant99acc502010-09-21 17:32:39 +0000716 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000717 allocator_type& __alloc() _NOEXCEPT {return __data_.second();}
718 _LIBCPP_INLINE_VISIBILITY
719 const allocator_type& __alloc() const _NOEXCEPT {return __data_.second();}
720
721 _LIBCPP_INLINE_VISIBILITY
722 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000723 {
724 __alloc_traits::deallocate(__alloc(), __p, size());
725 }
726};
727
Howard Hinnant2b1b2d42011-06-14 19:58:17 +0000728template <class _Alloc> class __hash_map_node_destructor;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000729
730template <class _Alloc>
731class __hash_node_destructor
732{
733 typedef _Alloc allocator_type;
734 typedef allocator_traits<allocator_type> __alloc_traits;
735 typedef typename __alloc_traits::value_type::value_type value_type;
736public:
737 typedef typename __alloc_traits::pointer pointer;
738private:
739
740 allocator_type& __na_;
741
742 __hash_node_destructor& operator=(const __hash_node_destructor&);
743
744public:
745 bool __value_constructed;
746
Howard Hinnant99acc502010-09-21 17:32:39 +0000747 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant199d0ae2011-07-31 17:04:30 +0000748 explicit __hash_node_destructor(allocator_type& __na,
749 bool __constructed = false) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000750 : __na_(__na),
Howard Hinnant199d0ae2011-07-31 17:04:30 +0000751 __value_constructed(__constructed)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000752 {}
753
Howard Hinnant99acc502010-09-21 17:32:39 +0000754 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000755 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000756 {
757 if (__value_constructed)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000758 __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000759 if (__p)
760 __alloc_traits::deallocate(__na_, __p, 1);
761 }
762
763 template <class> friend class __hash_map_node_destructor;
764};
765
766template <class _Tp, class _Hash, class _Equal, class _Alloc>
767class __hash_table
768{
769public:
770 typedef _Tp value_type;
771 typedef _Hash hasher;
772 typedef _Equal key_equal;
773 typedef _Alloc allocator_type;
774
775private:
776 typedef allocator_traits<allocator_type> __alloc_traits;
777public:
778 typedef value_type& reference;
779 typedef const value_type& const_reference;
780 typedef typename __alloc_traits::pointer pointer;
781 typedef typename __alloc_traits::const_pointer const_pointer;
782 typedef typename __alloc_traits::size_type size_type;
783 typedef typename __alloc_traits::difference_type difference_type;
784public:
785 // Create __node
786 typedef __hash_node<value_type, typename __alloc_traits::void_pointer> __node;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000787 typedef typename __alloc_traits::template
788#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
789 rebind_alloc<__node>
790#else
791 rebind_alloc<__node>::other
792#endif
793 __node_allocator;
794 typedef allocator_traits<__node_allocator> __node_traits;
795 typedef typename __node_traits::pointer __node_pointer;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000796 typedef typename __node_traits::pointer __node_const_pointer;
Howard Hinnantf8880d02011-12-12 17:26:24 +0000797 typedef __hash_node_base<__node_pointer> __first_node;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000798 typedef typename pointer_traits<__node_pointer>::template
799#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
800 rebind<__first_node>
801#else
802 rebind<__first_node>::other
803#endif
804 __node_base_pointer;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000805
806private:
807
808 typedef typename __node_traits::template
809#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
810 rebind_alloc<__node_pointer>
811#else
812 rebind_alloc<__node_pointer>::other
813#endif
814 __pointer_allocator;
815 typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter;
816 typedef unique_ptr<__node_pointer[], __bucket_list_deleter> __bucket_list;
817 typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits;
818 typedef typename __bucket_list_deleter::pointer __node_pointer_pointer;
819
820 // --- Member data begin ---
821 __bucket_list __bucket_list_;
822 __compressed_pair<__first_node, __node_allocator> __p1_;
823 __compressed_pair<size_type, hasher> __p2_;
824 __compressed_pair<float, key_equal> __p3_;
825 // --- Member data end ---
826
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000827 _LIBCPP_INLINE_VISIBILITY
828 size_type& size() _NOEXCEPT {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000829public:
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000830 _LIBCPP_INLINE_VISIBILITY
831 size_type size() const _NOEXCEPT {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000832
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000833 _LIBCPP_INLINE_VISIBILITY
834 hasher& hash_function() _NOEXCEPT {return __p2_.second();}
835 _LIBCPP_INLINE_VISIBILITY
836 const hasher& hash_function() const _NOEXCEPT {return __p2_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000837
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000838 _LIBCPP_INLINE_VISIBILITY
839 float& max_load_factor() _NOEXCEPT {return __p3_.first();}
840 _LIBCPP_INLINE_VISIBILITY
841 float max_load_factor() const _NOEXCEPT {return __p3_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000842
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000843 _LIBCPP_INLINE_VISIBILITY
844 key_equal& key_eq() _NOEXCEPT {return __p3_.second();}
845 _LIBCPP_INLINE_VISIBILITY
846 const key_equal& key_eq() const _NOEXCEPT {return __p3_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000847
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000848 _LIBCPP_INLINE_VISIBILITY
849 __node_allocator& __node_alloc() _NOEXCEPT {return __p1_.second();}
850 _LIBCPP_INLINE_VISIBILITY
851 const __node_allocator& __node_alloc() const _NOEXCEPT
852 {return __p1_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000853
854public:
855 typedef __hash_iterator<__node_pointer> iterator;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000856 typedef __hash_const_iterator<__node_pointer> const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000857 typedef __hash_local_iterator<__node_pointer> local_iterator;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000858 typedef __hash_const_local_iterator<__node_pointer> const_local_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000859
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000860 __hash_table()
861 _NOEXCEPT_(
862 is_nothrow_default_constructible<__bucket_list>::value &&
863 is_nothrow_default_constructible<__first_node>::value &&
864 is_nothrow_default_constructible<__node_allocator>::value &&
865 is_nothrow_default_constructible<hasher>::value &&
866 is_nothrow_default_constructible<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000867 __hash_table(const hasher& __hf, const key_equal& __eql);
868 __hash_table(const hasher& __hf, const key_equal& __eql,
869 const allocator_type& __a);
870 explicit __hash_table(const allocator_type& __a);
871 __hash_table(const __hash_table& __u);
872 __hash_table(const __hash_table& __u, const allocator_type& __a);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000873#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000874 __hash_table(__hash_table&& __u)
875 _NOEXCEPT_(
876 is_nothrow_move_constructible<__bucket_list>::value &&
877 is_nothrow_move_constructible<__first_node>::value &&
878 is_nothrow_move_constructible<__node_allocator>::value &&
879 is_nothrow_move_constructible<hasher>::value &&
880 is_nothrow_move_constructible<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000881 __hash_table(__hash_table&& __u, const allocator_type& __a);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000882#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000883 ~__hash_table();
884
885 __hash_table& operator=(const __hash_table& __u);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000886#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000887 __hash_table& operator=(__hash_table&& __u)
888 _NOEXCEPT_(
889 __node_traits::propagate_on_container_move_assignment::value &&
890 is_nothrow_move_assignable<__node_allocator>::value &&
891 is_nothrow_move_assignable<hasher>::value &&
892 is_nothrow_move_assignable<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000893#endif
894 template <class _InputIterator>
895 void __assign_unique(_InputIterator __first, _InputIterator __last);
896 template <class _InputIterator>
897 void __assign_multi(_InputIterator __first, _InputIterator __last);
898
Howard Hinnant99acc502010-09-21 17:32:39 +0000899 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000900 size_type max_size() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000901 {
902 return allocator_traits<__pointer_allocator>::max_size(
903 __bucket_list_.get_deleter().__alloc());
904 }
905
906 pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
907 iterator __node_insert_multi(__node_pointer __nd);
908 iterator __node_insert_multi(const_iterator __p,
909 __node_pointer __nd);
910
Howard Hinnant73d21a42010-09-04 23:28:19 +0000911#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000912 template <class... _Args>
913 pair<iterator, bool> __emplace_unique(_Args&&... __args);
914 template <class... _Args>
915 iterator __emplace_multi(_Args&&... __args);
916 template <class... _Args>
917 iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000918#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000919
920 pair<iterator, bool> __insert_unique(const value_type& __x);
921
Howard Hinnant73d21a42010-09-04 23:28:19 +0000922#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant99968442011-11-29 18:15:50 +0000923 template <class _Pp>
924 pair<iterator, bool> __insert_unique(_Pp&& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000925#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000926
Howard Hinnant73d21a42010-09-04 23:28:19 +0000927#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant99968442011-11-29 18:15:50 +0000928 template <class _Pp>
929 iterator __insert_multi(_Pp&& __x);
930 template <class _Pp>
931 iterator __insert_multi(const_iterator __p, _Pp&& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000932#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000933 iterator __insert_multi(const value_type& __x);
934 iterator __insert_multi(const_iterator __p, const value_type& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000935#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000936
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000937 void clear() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000938 void rehash(size_type __n);
Howard Hinnant99acc502010-09-21 17:32:39 +0000939 _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000940 {rehash(static_cast<size_type>(ceil(__n / max_load_factor())));}
Howard Hinnant99acc502010-09-21 17:32:39 +0000941
942 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000943 size_type bucket_count() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000944 {
945 return __bucket_list_.get_deleter().size();
946 }
947
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000948 iterator begin() _NOEXCEPT;
949 iterator end() _NOEXCEPT;
950 const_iterator begin() const _NOEXCEPT;
951 const_iterator end() const _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000952
953 template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39 +0000954 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000955 size_type bucket(const _Key& __k) const
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +0000956 {
957 _LIBCPP_ASSERT(bucket_count() > 0,
958 "unordered container::bucket(key) called when bucket_count() == 0");
959 return __constrain_hash(hash_function()(__k), bucket_count());
960 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000961
962 template <class _Key>
963 iterator find(const _Key& __x);
964 template <class _Key>
965 const_iterator find(const _Key& __x) const;
966
Howard Hinnant99968442011-11-29 18:15:50 +0000967 typedef __hash_node_destructor<__node_allocator> _Dp;
968 typedef unique_ptr<__node, _Dp> __node_holder;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000969
970 iterator erase(const_iterator __p);
971 iterator erase(const_iterator __first, const_iterator __last);
972 template <class _Key>
973 size_type __erase_unique(const _Key& __k);
974 template <class _Key>
975 size_type __erase_multi(const _Key& __k);
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000976 __node_holder remove(const_iterator __p) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000977
978 template <class _Key>
979 size_type __count_unique(const _Key& __k) const;
980 template <class _Key>
981 size_type __count_multi(const _Key& __k) const;
982
983 template <class _Key>
984 pair<iterator, iterator>
985 __equal_range_unique(const _Key& __k);
986 template <class _Key>
987 pair<const_iterator, const_iterator>
988 __equal_range_unique(const _Key& __k) const;
989
990 template <class _Key>
991 pair<iterator, iterator>
992 __equal_range_multi(const _Key& __k);
993 template <class _Key>
994 pair<const_iterator, const_iterator>
995 __equal_range_multi(const _Key& __k) const;
996
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000997 void swap(__hash_table& __u)
998 _NOEXCEPT_(
999 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
1000 __is_nothrow_swappable<__pointer_allocator>::value) &&
1001 (!__node_traits::propagate_on_container_swap::value ||
1002 __is_nothrow_swappable<__node_allocator>::value) &&
1003 __is_nothrow_swappable<hasher>::value &&
1004 __is_nothrow_swappable<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001005
Howard Hinnant99acc502010-09-21 17:32:39 +00001006 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001007 size_type max_bucket_count() const _NOEXCEPT
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001008 {return __pointer_alloc_traits::max_size(__bucket_list_.get_deleter().__alloc());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001009 size_type bucket_size(size_type __n) const;
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001010 _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001011 {
1012 size_type __bc = bucket_count();
1013 return __bc != 0 ? (float)size() / __bc : 0.f;
1014 }
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001015 _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00001016 {
1017 _LIBCPP_ASSERT(__mlf > 0,
1018 "unordered container::max_load_factor(lf) called with lf <= 0");
1019 max_load_factor() = _VSTD::max(__mlf, load_factor());
1020 }
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001021
Howard Hinnant39213642013-07-23 22:01:58 +00001022 _LIBCPP_INLINE_VISIBILITY
1023 local_iterator
1024 begin(size_type __n)
1025 {
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00001026 _LIBCPP_ASSERT(__n < bucket_count(),
1027 "unordered container::begin(n) called with n >= bucket_count()");
Howard Hinnant39213642013-07-23 22:01:58 +00001028#if _LIBCPP_DEBUG_LEVEL >= 2
1029 return local_iterator(__bucket_list_[__n], __n, bucket_count(), this);
1030#else
1031 return local_iterator(__bucket_list_[__n], __n, bucket_count());
1032#endif
1033 }
1034
1035 _LIBCPP_INLINE_VISIBILITY
1036 local_iterator
1037 end(size_type __n)
1038 {
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00001039 _LIBCPP_ASSERT(__n < bucket_count(),
1040 "unordered container::end(n) called with n >= bucket_count()");
Howard Hinnant39213642013-07-23 22:01:58 +00001041#if _LIBCPP_DEBUG_LEVEL >= 2
1042 return local_iterator(nullptr, __n, bucket_count(), this);
1043#else
1044 return local_iterator(nullptr, __n, bucket_count());
1045#endif
1046 }
1047
1048 _LIBCPP_INLINE_VISIBILITY
1049 const_local_iterator
1050 cbegin(size_type __n) const
1051 {
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00001052 _LIBCPP_ASSERT(__n < bucket_count(),
1053 "unordered container::cbegin(n) called with n >= bucket_count()");
Howard Hinnant39213642013-07-23 22:01:58 +00001054#if _LIBCPP_DEBUG_LEVEL >= 2
1055 return const_local_iterator(__bucket_list_[__n], __n, bucket_count(), this);
1056#else
1057 return const_local_iterator(__bucket_list_[__n], __n, bucket_count());
1058#endif
1059 }
1060
1061 _LIBCPP_INLINE_VISIBILITY
1062 const_local_iterator
1063 cend(size_type __n) const
1064 {
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00001065 _LIBCPP_ASSERT(__n < bucket_count(),
1066 "unordered container::cend(n) called with n >= bucket_count()");
Howard Hinnant39213642013-07-23 22:01:58 +00001067#if _LIBCPP_DEBUG_LEVEL >= 2
1068 return const_local_iterator(nullptr, __n, bucket_count(), this);
1069#else
1070 return const_local_iterator(nullptr, __n, bucket_count());
1071#endif
1072 }
1073
1074#if _LIBCPP_DEBUG_LEVEL >= 2
1075
1076 bool __dereferenceable(const const_iterator* __i) const;
1077 bool __decrementable(const const_iterator* __i) const;
1078 bool __addable(const const_iterator* __i, ptrdiff_t __n) const;
1079 bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const;
1080
1081#endif // _LIBCPP_DEBUG_LEVEL >= 2
1082
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001083private:
1084 void __rehash(size_type __n);
1085
Howard Hinnant73d21a42010-09-04 23:28:19 +00001086#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1087#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001088 template <class ..._Args>
1089 __node_holder __construct_node(_Args&& ...__args);
Howard Hinnantbfd55302010-09-04 23:46:48 +00001090#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001091 __node_holder __construct_node(value_type&& __v, size_t __hash);
Howard Hinnant73d21a42010-09-04 23:28:19 +00001092#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001093 __node_holder __construct_node(const value_type& __v);
1094#endif
1095 __node_holder __construct_node(const value_type& __v, size_t __hash);
1096
Howard Hinnant99acc502010-09-21 17:32:39 +00001097 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001098 void __copy_assign_alloc(const __hash_table& __u)
1099 {__copy_assign_alloc(__u, integral_constant<bool,
1100 __node_traits::propagate_on_container_copy_assignment::value>());}
1101 void __copy_assign_alloc(const __hash_table& __u, true_type);
Howard Hinnant99acc502010-09-21 17:32:39 +00001102 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantec3773c2011-12-01 20:21:04 +00001103 void __copy_assign_alloc(const __hash_table&, false_type) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001104
1105 void __move_assign(__hash_table& __u, false_type);
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001106 void __move_assign(__hash_table& __u, true_type)
1107 _NOEXCEPT_(
1108 is_nothrow_move_assignable<__node_allocator>::value &&
1109 is_nothrow_move_assignable<hasher>::value &&
1110 is_nothrow_move_assignable<key_equal>::value);
1111 _LIBCPP_INLINE_VISIBILITY
1112 void __move_assign_alloc(__hash_table& __u)
1113 _NOEXCEPT_(
1114 !__node_traits::propagate_on_container_move_assignment::value ||
1115 (is_nothrow_move_assignable<__pointer_allocator>::value &&
1116 is_nothrow_move_assignable<__node_allocator>::value))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001117 {__move_assign_alloc(__u, integral_constant<bool,
1118 __node_traits::propagate_on_container_move_assignment::value>());}
Howard Hinnant99acc502010-09-21 17:32:39 +00001119 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001120 void __move_assign_alloc(__hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001121 _NOEXCEPT_(
1122 is_nothrow_move_assignable<__pointer_allocator>::value &&
1123 is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001124 {
1125 __bucket_list_.get_deleter().__alloc() =
Howard Hinnant0949eed2011-06-30 21:18:19 +00001126 _VSTD::move(__u.__bucket_list_.get_deleter().__alloc());
1127 __node_alloc() = _VSTD::move(__u.__node_alloc());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001128 }
Howard Hinnant99acc502010-09-21 17:32:39 +00001129 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001130 void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001131
Howard Hinnant99968442011-11-29 18:15:50 +00001132 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:39 +00001133 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001134 static
1135 void
Howard Hinnant99968442011-11-29 18:15:50 +00001136 __swap_alloc(_Ap& __x, _Ap& __y)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001137 _NOEXCEPT_(
Howard Hinnant99968442011-11-29 18:15:50 +00001138 !allocator_traits<_Ap>::propagate_on_container_swap::value ||
1139 __is_nothrow_swappable<_Ap>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001140 {
1141 __swap_alloc(__x, __y,
1142 integral_constant<bool,
Howard Hinnant99968442011-11-29 18:15:50 +00001143 allocator_traits<_Ap>::propagate_on_container_swap::value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001144 >());
1145 }
1146
Howard Hinnant99968442011-11-29 18:15:50 +00001147 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:39 +00001148 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001149 static
1150 void
Howard Hinnant99968442011-11-29 18:15:50 +00001151 __swap_alloc(_Ap& __x, _Ap& __y, true_type)
1152 _NOEXCEPT_(__is_nothrow_swappable<_Ap>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001153 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001154 using _VSTD::swap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001155 swap(__x, __y);
1156 }
1157
Howard Hinnant99968442011-11-29 18:15:50 +00001158 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:39 +00001159 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001160 static
1161 void
Howard Hinnantec3773c2011-12-01 20:21:04 +00001162 __swap_alloc(_Ap&, _Ap&, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001163
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001164 void __deallocate(__node_pointer __np) _NOEXCEPT;
1165 __node_pointer __detach() _NOEXCEPT;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001166
1167 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_map;
1168 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001169};
1170
1171template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001172inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001173__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table()
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001174 _NOEXCEPT_(
1175 is_nothrow_default_constructible<__bucket_list>::value &&
1176 is_nothrow_default_constructible<__first_node>::value &&
1177 is_nothrow_default_constructible<hasher>::value &&
1178 is_nothrow_default_constructible<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001179 : __p2_(0),
1180 __p3_(1.0f)
1181{
1182}
1183
1184template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001185inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001186__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
1187 const key_equal& __eql)
1188 : __bucket_list_(nullptr, __bucket_list_deleter()),
1189 __p1_(),
1190 __p2_(0, __hf),
1191 __p3_(1.0f, __eql)
1192{
1193}
1194
1195template <class _Tp, class _Hash, class _Equal, class _Alloc>
1196__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
1197 const key_equal& __eql,
1198 const allocator_type& __a)
1199 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1200 __p1_(__node_allocator(__a)),
1201 __p2_(0, __hf),
1202 __p3_(1.0f, __eql)
1203{
1204}
1205
1206template <class _Tp, class _Hash, class _Equal, class _Alloc>
1207__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
1208 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1209 __p1_(__node_allocator(__a)),
1210 __p2_(0),
1211 __p3_(1.0f)
1212{
1213}
1214
1215template <class _Tp, class _Hash, class _Equal, class _Alloc>
1216__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
1217 : __bucket_list_(nullptr,
1218 __bucket_list_deleter(allocator_traits<__pointer_allocator>::
1219 select_on_container_copy_construction(
1220 __u.__bucket_list_.get_deleter().__alloc()), 0)),
1221 __p1_(allocator_traits<__node_allocator>::
1222 select_on_container_copy_construction(__u.__node_alloc())),
1223 __p2_(0, __u.hash_function()),
1224 __p3_(__u.__p3_)
1225{
1226}
1227
1228template <class _Tp, class _Hash, class _Equal, class _Alloc>
1229__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u,
1230 const allocator_type& __a)
1231 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1232 __p1_(__node_allocator(__a)),
1233 __p2_(0, __u.hash_function()),
1234 __p3_(__u.__p3_)
1235{
1236}
1237
Howard Hinnant73d21a42010-09-04 23:28:19 +00001238#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001239
1240template <class _Tp, class _Hash, class _Equal, class _Alloc>
1241__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001242 _NOEXCEPT_(
1243 is_nothrow_move_constructible<__bucket_list>::value &&
1244 is_nothrow_move_constructible<__first_node>::value &&
1245 is_nothrow_move_constructible<hasher>::value &&
1246 is_nothrow_move_constructible<key_equal>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +00001247 : __bucket_list_(_VSTD::move(__u.__bucket_list_)),
1248 __p1_(_VSTD::move(__u.__p1_)),
1249 __p2_(_VSTD::move(__u.__p2_)),
1250 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001251{
1252 if (size() > 0)
1253 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001254 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001255 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001256 __u.__p1_.first().__next_ = nullptr;
1257 __u.size() = 0;
1258 }
1259}
1260
1261template <class _Tp, class _Hash, class _Equal, class _Alloc>
1262__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u,
1263 const allocator_type& __a)
1264 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1265 __p1_(__node_allocator(__a)),
Howard Hinnant0949eed2011-06-30 21:18:19 +00001266 __p2_(0, _VSTD::move(__u.hash_function())),
1267 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001268{
1269 if (__a == allocator_type(__u.__node_alloc()))
1270 {
1271 __bucket_list_.reset(__u.__bucket_list_.release());
1272 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
1273 __u.__bucket_list_.get_deleter().size() = 0;
1274 if (__u.size() > 0)
1275 {
1276 __p1_.first().__next_ = __u.__p1_.first().__next_;
1277 __u.__p1_.first().__next_ = nullptr;
Howard Hinnant7a445152012-07-06 17:31:14 +00001278 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001279 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001280 size() = __u.size();
1281 __u.size() = 0;
1282 }
1283 }
1284}
1285
Howard Hinnant73d21a42010-09-04 23:28:19 +00001286#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001287
1288template <class _Tp, class _Hash, class _Equal, class _Alloc>
1289__hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table()
1290{
1291 __deallocate(__p1_.first().__next_);
Howard Hinnant39213642013-07-23 22:01:58 +00001292#if _LIBCPP_DEBUG_LEVEL >= 2
1293 __get_db()->__erase_c(this);
1294#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001295}
1296
1297template <class _Tp, class _Hash, class _Equal, class _Alloc>
1298void
1299__hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc(
1300 const __hash_table& __u, true_type)
1301{
1302 if (__node_alloc() != __u.__node_alloc())
1303 {
1304 clear();
1305 __bucket_list_.reset();
1306 __bucket_list_.get_deleter().size() = 0;
1307 }
1308 __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc();
1309 __node_alloc() = __u.__node_alloc();
1310}
1311
1312template <class _Tp, class _Hash, class _Equal, class _Alloc>
1313__hash_table<_Tp, _Hash, _Equal, _Alloc>&
1314__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u)
1315{
1316 if (this != &__u)
1317 {
1318 __copy_assign_alloc(__u);
1319 hash_function() = __u.hash_function();
1320 key_eq() = __u.key_eq();
1321 max_load_factor() = __u.max_load_factor();
1322 __assign_multi(__u.begin(), __u.end());
1323 }
1324 return *this;
1325}
1326
1327template <class _Tp, class _Hash, class _Equal, class _Alloc>
1328void
1329__hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate(__node_pointer __np)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001330 _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001331{
1332 __node_allocator& __na = __node_alloc();
1333 while (__np != nullptr)
1334 {
1335 __node_pointer __next = __np->__next_;
Howard Hinnant39213642013-07-23 22:01:58 +00001336#if _LIBCPP_DEBUG_LEVEL >= 2
1337 __c_node* __c = __get_db()->__find_c_and_lock(this);
1338 for (__i_node** __p = __c->end_; __p != __c->beg_; )
1339 {
1340 --__p;
1341 iterator* __i = static_cast<iterator*>((*__p)->__i_);
1342 if (__i->__node_ == __np)
1343 {
1344 (*__p)->__c_ = nullptr;
1345 if (--__c->end_ != __p)
1346 memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*));
1347 }
1348 }
1349 __get_db()->unlock();
1350#endif
Howard Hinnant0949eed2011-06-30 21:18:19 +00001351 __node_traits::destroy(__na, _VSTD::addressof(__np->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001352 __node_traits::deallocate(__na, __np, 1);
1353 __np = __next;
1354 }
1355}
1356
1357template <class _Tp, class _Hash, class _Equal, class _Alloc>
1358typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_pointer
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001359__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001360{
1361 size_type __bc = bucket_count();
1362 for (size_type __i = 0; __i < __bc; ++__i)
1363 __bucket_list_[__i] = nullptr;
1364 size() = 0;
1365 __node_pointer __cache = __p1_.first().__next_;
1366 __p1_.first().__next_ = nullptr;
1367 return __cache;
1368}
1369
Howard Hinnant73d21a42010-09-04 23:28:19 +00001370#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001371
1372template <class _Tp, class _Hash, class _Equal, class _Alloc>
1373void
1374__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
1375 __hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001376 _NOEXCEPT_(
1377 is_nothrow_move_assignable<__node_allocator>::value &&
1378 is_nothrow_move_assignable<hasher>::value &&
1379 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001380{
1381 clear();
1382 __bucket_list_.reset(__u.__bucket_list_.release());
1383 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
1384 __u.__bucket_list_.get_deleter().size() = 0;
1385 __move_assign_alloc(__u);
1386 size() = __u.size();
Howard Hinnant0949eed2011-06-30 21:18:19 +00001387 hash_function() = _VSTD::move(__u.hash_function());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001388 max_load_factor() = __u.max_load_factor();
Howard Hinnant0949eed2011-06-30 21:18:19 +00001389 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001390 __p1_.first().__next_ = __u.__p1_.first().__next_;
1391 if (size() > 0)
1392 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001393 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001394 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001395 __u.__p1_.first().__next_ = nullptr;
1396 __u.size() = 0;
1397 }
Howard Hinnant39213642013-07-23 22:01:58 +00001398#if _LIBCPP_DEBUG_LEVEL >= 2
1399 __get_db()->swap(this, &__u);
1400#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001401}
1402
1403template <class _Tp, class _Hash, class _Equal, class _Alloc>
1404void
1405__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
1406 __hash_table& __u, false_type)
1407{
1408 if (__node_alloc() == __u.__node_alloc())
1409 __move_assign(__u, true_type());
1410 else
1411 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001412 hash_function() = _VSTD::move(__u.hash_function());
1413 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001414 max_load_factor() = __u.max_load_factor();
1415 if (bucket_count() != 0)
1416 {
1417 __node_pointer __cache = __detach();
1418#ifndef _LIBCPP_NO_EXCEPTIONS
1419 try
1420 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001421#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001422 const_iterator __i = __u.begin();
1423 while (__cache != nullptr && __u.size() != 0)
1424 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001425 __cache->__value_ = _VSTD::move(__u.remove(__i++)->__value_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001426 __node_pointer __next = __cache->__next_;
1427 __node_insert_multi(__cache);
1428 __cache = __next;
1429 }
1430#ifndef _LIBCPP_NO_EXCEPTIONS
1431 }
1432 catch (...)
1433 {
1434 __deallocate(__cache);
1435 throw;
1436 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001437#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001438 __deallocate(__cache);
1439 }
1440 const_iterator __i = __u.begin();
1441 while (__u.size() != 0)
1442 {
1443 __node_holder __h =
Howard Hinnant0949eed2011-06-30 21:18:19 +00001444 __construct_node(_VSTD::move(__u.remove(__i++)->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001445 __node_insert_multi(__h.get());
1446 __h.release();
1447 }
1448 }
1449}
1450
1451template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001452inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001453__hash_table<_Tp, _Hash, _Equal, _Alloc>&
1454__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001455 _NOEXCEPT_(
1456 __node_traits::propagate_on_container_move_assignment::value &&
1457 is_nothrow_move_assignable<__node_allocator>::value &&
1458 is_nothrow_move_assignable<hasher>::value &&
1459 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001460{
1461 __move_assign(__u, integral_constant<bool,
1462 __node_traits::propagate_on_container_move_assignment::value>());
1463 return *this;
1464}
1465
Howard Hinnant73d21a42010-09-04 23:28:19 +00001466#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001467
1468template <class _Tp, class _Hash, class _Equal, class _Alloc>
1469template <class _InputIterator>
1470void
1471__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first,
1472 _InputIterator __last)
1473{
1474 if (bucket_count() != 0)
1475 {
1476 __node_pointer __cache = __detach();
1477#ifndef _LIBCPP_NO_EXCEPTIONS
1478 try
1479 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001480#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001481 for (; __cache != nullptr && __first != __last; ++__first)
1482 {
1483 __cache->__value_ = *__first;
1484 __node_pointer __next = __cache->__next_;
1485 __node_insert_unique(__cache);
1486 __cache = __next;
1487 }
1488#ifndef _LIBCPP_NO_EXCEPTIONS
1489 }
1490 catch (...)
1491 {
1492 __deallocate(__cache);
1493 throw;
1494 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001495#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001496 __deallocate(__cache);
1497 }
1498 for (; __first != __last; ++__first)
1499 __insert_unique(*__first);
1500}
1501
1502template <class _Tp, class _Hash, class _Equal, class _Alloc>
1503template <class _InputIterator>
1504void
1505__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first,
1506 _InputIterator __last)
1507{
1508 if (bucket_count() != 0)
1509 {
1510 __node_pointer __cache = __detach();
1511#ifndef _LIBCPP_NO_EXCEPTIONS
1512 try
1513 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001514#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001515 for (; __cache != nullptr && __first != __last; ++__first)
1516 {
1517 __cache->__value_ = *__first;
1518 __node_pointer __next = __cache->__next_;
1519 __node_insert_multi(__cache);
1520 __cache = __next;
1521 }
1522#ifndef _LIBCPP_NO_EXCEPTIONS
1523 }
1524 catch (...)
1525 {
1526 __deallocate(__cache);
1527 throw;
1528 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001529#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001530 __deallocate(__cache);
1531 }
1532 for (; __first != __last; ++__first)
1533 __insert_multi(*__first);
1534}
1535
1536template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001537inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001538typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001539__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001540{
Howard Hinnant39213642013-07-23 22:01:58 +00001541#if _LIBCPP_DEBUG_LEVEL >= 2
1542 return iterator(__p1_.first().__next_, this);
1543#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001544 return iterator(__p1_.first().__next_);
Howard Hinnant39213642013-07-23 22:01:58 +00001545#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001546}
1547
1548template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001549inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001550typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001551__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001552{
Howard Hinnant39213642013-07-23 22:01:58 +00001553#if _LIBCPP_DEBUG_LEVEL >= 2
1554 return iterator(nullptr, this);
1555#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001556 return iterator(nullptr);
Howard Hinnant39213642013-07-23 22:01:58 +00001557#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001558}
1559
1560template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001561inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001562typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001563__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001564{
Howard Hinnant39213642013-07-23 22:01:58 +00001565#if _LIBCPP_DEBUG_LEVEL >= 2
1566 return const_iterator(__p1_.first().__next_, this);
1567#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001568 return const_iterator(__p1_.first().__next_);
Howard Hinnant39213642013-07-23 22:01:58 +00001569#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001570}
1571
1572template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001573inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001574typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001575__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001576{
Howard Hinnant39213642013-07-23 22:01:58 +00001577#if _LIBCPP_DEBUG_LEVEL >= 2
1578 return const_iterator(nullptr, this);
1579#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001580 return const_iterator(nullptr);
Howard Hinnant39213642013-07-23 22:01:58 +00001581#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001582}
1583
1584template <class _Tp, class _Hash, class _Equal, class _Alloc>
1585void
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001586__hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001587{
1588 if (size() > 0)
1589 {
1590 __deallocate(__p1_.first().__next_);
1591 __p1_.first().__next_ = nullptr;
1592 size_type __bc = bucket_count();
Howard Hinnant9f66bff2011-07-05 14:14:17 +00001593 for (size_type __i = 0; __i < __bc; ++__i)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001594 __bucket_list_[__i] = nullptr;
1595 size() = 0;
1596 }
1597}
1598
1599template <class _Tp, class _Hash, class _Equal, class _Alloc>
1600pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1601__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd)
1602{
1603 __nd->__hash_ = hash_function()(__nd->__value_);
1604 size_type __bc = bucket_count();
1605 bool __inserted = false;
1606 __node_pointer __ndptr;
1607 size_t __chash;
1608 if (__bc != 0)
1609 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001610 __chash = __constrain_hash(__nd->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001611 __ndptr = __bucket_list_[__chash];
1612 if (__ndptr != nullptr)
1613 {
1614 for (__ndptr = __ndptr->__next_; __ndptr != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001615 __constrain_hash(__ndptr->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001616 __ndptr = __ndptr->__next_)
1617 {
1618 if (key_eq()(__ndptr->__value_, __nd->__value_))
1619 goto __done;
1620 }
1621 }
1622 }
1623 {
1624 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1625 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001626 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001627 size_type(ceil(float(size() + 1) / max_load_factor()))));
1628 __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:14 +00001629 __chash = __constrain_hash(__nd->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001630 }
1631 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1632 __node_pointer __pn = __bucket_list_[__chash];
1633 if (__pn == nullptr)
1634 {
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001635 __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001636 __nd->__next_ = __pn->__next_;
1637 __pn->__next_ = __nd;
1638 // fix up __bucket_list_
1639 __bucket_list_[__chash] = __pn;
1640 if (__nd->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:14 +00001641 __bucket_list_[__constrain_hash(__nd->__next_->__hash_, __bc)] = __nd;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001642 }
1643 else
1644 {
1645 __nd->__next_ = __pn->__next_;
1646 __pn->__next_ = __nd;
1647 }
1648 __ndptr = __nd;
1649 // increment size
1650 ++size();
1651 __inserted = true;
1652 }
1653__done:
Howard Hinnant39213642013-07-23 22:01:58 +00001654#if _LIBCPP_DEBUG_LEVEL >= 2
1655 return pair<iterator, bool>(iterator(__ndptr, this), __inserted);
1656#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001657 return pair<iterator, bool>(iterator(__ndptr), __inserted);
Howard Hinnant39213642013-07-23 22:01:58 +00001658#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001659}
1660
1661template <class _Tp, class _Hash, class _Equal, class _Alloc>
1662typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1663__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp)
1664{
1665 __cp->__hash_ = hash_function()(__cp->__value_);
1666 size_type __bc = bucket_count();
1667 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1668 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001669 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001670 size_type(ceil(float(size() + 1) / max_load_factor()))));
1671 __bc = bucket_count();
1672 }
Howard Hinnant7a445152012-07-06 17:31:14 +00001673 size_t __chash = __constrain_hash(__cp->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001674 __node_pointer __pn = __bucket_list_[__chash];
1675 if (__pn == nullptr)
1676 {
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001677 __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001678 __cp->__next_ = __pn->__next_;
1679 __pn->__next_ = __cp;
1680 // fix up __bucket_list_
1681 __bucket_list_[__chash] = __pn;
1682 if (__cp->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:14 +00001683 __bucket_list_[__constrain_hash(__cp->__next_->__hash_, __bc)] = __cp;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001684 }
1685 else
1686 {
1687 for (bool __found = false; __pn->__next_ != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001688 __constrain_hash(__pn->__next_->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001689 __pn = __pn->__next_)
Howard Hinnant324bb032010-08-22 00:02:43 +00001690 {
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001691 // __found key_eq() action
1692 // false false loop
1693 // true true loop
1694 // false true set __found to true
1695 // true false break
1696 if (__found != (__pn->__next_->__hash_ == __cp->__hash_ &&
1697 key_eq()(__pn->__next_->__value_, __cp->__value_)))
1698 {
1699 if (!__found)
1700 __found = true;
1701 else
1702 break;
1703 }
1704 }
1705 __cp->__next_ = __pn->__next_;
1706 __pn->__next_ = __cp;
1707 if (__cp->__next_ != nullptr)
1708 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001709 size_t __nhash = __constrain_hash(__cp->__next_->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001710 if (__nhash != __chash)
1711 __bucket_list_[__nhash] = __cp;
1712 }
1713 }
1714 ++size();
Howard Hinnant39213642013-07-23 22:01:58 +00001715#if _LIBCPP_DEBUG_LEVEL >= 2
1716 return iterator(__cp, this);
1717#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001718 return iterator(__cp);
Howard Hinnant39213642013-07-23 22:01:58 +00001719#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001720}
1721
1722template <class _Tp, class _Hash, class _Equal, class _Alloc>
1723typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1724__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(
1725 const_iterator __p, __node_pointer __cp)
1726{
1727 if (__p != end() && key_eq()(*__p, __cp->__value_))
1728 {
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001729 __node_pointer __np = __p.__node_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001730 __cp->__hash_ = __np->__hash_;
1731 size_type __bc = bucket_count();
1732 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1733 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001734 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001735 size_type(ceil(float(size() + 1) / max_load_factor()))));
1736 __bc = bucket_count();
1737 }
Howard Hinnant7a445152012-07-06 17:31:14 +00001738 size_t __chash = __constrain_hash(__cp->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001739 __node_pointer __pp = __bucket_list_[__chash];
1740 while (__pp->__next_ != __np)
1741 __pp = __pp->__next_;
1742 __cp->__next_ = __np;
1743 __pp->__next_ = __cp;
1744 ++size();
Howard Hinnant39213642013-07-23 22:01:58 +00001745#if _LIBCPP_DEBUG_LEVEL >= 2
1746 return iterator(__cp, this);
1747#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001748 return iterator(__cp);
Howard Hinnant39213642013-07-23 22:01:58 +00001749#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001750 }
1751 return __node_insert_multi(__cp);
1752}
1753
1754template <class _Tp, class _Hash, class _Equal, class _Alloc>
1755pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1756__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(const value_type& __x)
1757{
1758 size_t __hash = hash_function()(__x);
1759 size_type __bc = bucket_count();
1760 bool __inserted = false;
1761 __node_pointer __nd;
1762 size_t __chash;
1763 if (__bc != 0)
1764 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001765 __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001766 __nd = __bucket_list_[__chash];
1767 if (__nd != nullptr)
1768 {
1769 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001770 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001771 __nd = __nd->__next_)
1772 {
1773 if (key_eq()(__nd->__value_, __x))
1774 goto __done;
1775 }
1776 }
1777 }
1778 {
1779 __node_holder __h = __construct_node(__x, __hash);
1780 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1781 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001782 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001783 size_type(ceil(float(size() + 1) / max_load_factor()))));
1784 __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:14 +00001785 __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001786 }
1787 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1788 __node_pointer __pn = __bucket_list_[__chash];
1789 if (__pn == nullptr)
1790 {
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001791 __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001792 __h->__next_ = __pn->__next_;
1793 __pn->__next_ = __h.get();
1794 // fix up __bucket_list_
1795 __bucket_list_[__chash] = __pn;
1796 if (__h->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:14 +00001797 __bucket_list_[__constrain_hash(__h->__next_->__hash_, __bc)] = __h.get();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001798 }
1799 else
1800 {
1801 __h->__next_ = __pn->__next_;
1802 __pn->__next_ = __h.get();
1803 }
1804 __nd = __h.release();
1805 // increment size
1806 ++size();
1807 __inserted = true;
1808 }
1809__done:
Howard Hinnant39213642013-07-23 22:01:58 +00001810#if _LIBCPP_DEBUG_LEVEL >= 2
1811 return pair<iterator, bool>(iterator(__nd, this), __inserted);
1812#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001813 return pair<iterator, bool>(iterator(__nd), __inserted);
Howard Hinnant39213642013-07-23 22:01:58 +00001814#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001815}
1816
Howard Hinnant73d21a42010-09-04 23:28:19 +00001817#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1818#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001819
1820template <class _Tp, class _Hash, class _Equal, class _Alloc>
1821template <class... _Args>
1822pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1823__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique(_Args&&... __args)
1824{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001825 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001826 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1827 if (__r.second)
1828 __h.release();
1829 return __r;
1830}
1831
1832template <class _Tp, class _Hash, class _Equal, class _Alloc>
1833template <class... _Args>
1834typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1835__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args)
1836{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001837 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001838 iterator __r = __node_insert_multi(__h.get());
1839 __h.release();
1840 return __r;
1841}
1842
1843template <class _Tp, class _Hash, class _Equal, class _Alloc>
1844template <class... _Args>
1845typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1846__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi(
1847 const_iterator __p, _Args&&... __args)
1848{
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00001849#if _LIBCPP_DEBUG_LEVEL >= 2
1850 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
1851 "unordered container::emplace_hint(const_iterator, args...) called with an iterator not"
1852 " referring to this unordered container");
1853#endif
Howard Hinnant0949eed2011-06-30 21:18:19 +00001854 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001855 iterator __r = __node_insert_multi(__p, __h.get());
1856 __h.release();
1857 return __r;
1858}
1859
Howard Hinnant73d21a42010-09-04 23:28:19 +00001860#endif // _LIBCPP_HAS_NO_VARIADICS
1861
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001862template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:50 +00001863template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001864pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
Howard Hinnant99968442011-11-29 18:15:50 +00001865__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(_Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001866{
Howard Hinnant99968442011-11-29 18:15:50 +00001867 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001868 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1869 if (__r.second)
1870 __h.release();
1871 return __r;
1872}
1873
Howard Hinnant73d21a42010-09-04 23:28:19 +00001874#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001875
Howard Hinnant73d21a42010-09-04 23:28:19 +00001876#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001877
1878template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:50 +00001879template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001880typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant99968442011-11-29 18:15:50 +00001881__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(_Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001882{
Howard Hinnant99968442011-11-29 18:15:50 +00001883 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001884 iterator __r = __node_insert_multi(__h.get());
1885 __h.release();
1886 return __r;
1887}
1888
1889template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:50 +00001890template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001891typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1892__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
Howard Hinnant99968442011-11-29 18:15:50 +00001893 _Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001894{
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00001895#if _LIBCPP_DEBUG_LEVEL >= 2
1896 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
1897 "unordered container::insert(const_iterator, rvalue) called with an iterator not"
1898 " referring to this unordered container");
1899#endif
Howard Hinnant99968442011-11-29 18:15:50 +00001900 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001901 iterator __r = __node_insert_multi(__p, __h.get());
1902 __h.release();
1903 return __r;
1904}
1905
Howard Hinnant73d21a42010-09-04 23:28:19 +00001906#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001907
1908template <class _Tp, class _Hash, class _Equal, class _Alloc>
1909typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1910__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const value_type& __x)
1911{
1912 __node_holder __h = __construct_node(__x);
1913 iterator __r = __node_insert_multi(__h.get());
1914 __h.release();
1915 return __r;
1916}
1917
1918template <class _Tp, class _Hash, class _Equal, class _Alloc>
1919typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1920__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
1921 const value_type& __x)
1922{
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00001923#if _LIBCPP_DEBUG_LEVEL >= 2
1924 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
1925 "unordered container::insert(const_iterator, lvalue) called with an iterator not"
1926 " referring to this unordered container");
1927#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001928 __node_holder __h = __construct_node(__x);
1929 iterator __r = __node_insert_multi(__p, __h.get());
1930 __h.release();
1931 return __r;
1932}
1933
Howard Hinnant73d21a42010-09-04 23:28:19 +00001934#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001935
1936template <class _Tp, class _Hash, class _Equal, class _Alloc>
1937void
1938__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n)
1939{
Howard Hinnant7a445152012-07-06 17:31:14 +00001940 if (__n == 1)
1941 __n = 2;
1942 else if (__n & (__n - 1))
1943 __n = __next_prime(__n);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001944 size_type __bc = bucket_count();
1945 if (__n > __bc)
1946 __rehash(__n);
Howard Hinnant7a445152012-07-06 17:31:14 +00001947 else if (__n < __bc)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001948 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001949 __n = _VSTD::max<size_type>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001950 (
1951 __n,
Howard Hinnant7a445152012-07-06 17:31:14 +00001952 __is_power2(__bc) ? __next_pow2(size_t(ceil(float(size()) / max_load_factor()))) :
1953 __next_prime(size_t(ceil(float(size()) / max_load_factor())))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001954 );
1955 if (__n < __bc)
1956 __rehash(__n);
1957 }
1958}
1959
1960template <class _Tp, class _Hash, class _Equal, class _Alloc>
1961void
1962__hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc)
1963{
Howard Hinnant39213642013-07-23 22:01:58 +00001964#if _LIBCPP_DEBUG_LEVEL >= 2
1965 __get_db()->__invalidate_all(this);
1966#endif // _LIBCPP_DEBUG_LEVEL >= 2
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001967 __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc();
1968 __bucket_list_.reset(__nbc > 0 ?
1969 __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr);
1970 __bucket_list_.get_deleter().size() = __nbc;
1971 if (__nbc > 0)
1972 {
1973 for (size_type __i = 0; __i < __nbc; ++__i)
1974 __bucket_list_[__i] = nullptr;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001975 __node_pointer __pp(static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001976 __node_pointer __cp = __pp->__next_;
1977 if (__cp != nullptr)
1978 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001979 size_type __chash = __constrain_hash(__cp->__hash_, __nbc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001980 __bucket_list_[__chash] = __pp;
1981 size_type __phash = __chash;
1982 for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr;
1983 __cp = __pp->__next_)
1984 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001985 __chash = __constrain_hash(__cp->__hash_, __nbc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001986 if (__chash == __phash)
1987 __pp = __cp;
1988 else
1989 {
1990 if (__bucket_list_[__chash] == nullptr)
1991 {
1992 __bucket_list_[__chash] = __pp;
1993 __pp = __cp;
1994 __phash = __chash;
1995 }
1996 else
1997 {
1998 __node_pointer __np = __cp;
1999 for (; __np->__next_ != nullptr &&
2000 key_eq()(__cp->__value_, __np->__next_->__value_);
2001 __np = __np->__next_)
2002 ;
2003 __pp->__next_ = __np->__next_;
2004 __np->__next_ = __bucket_list_[__chash]->__next_;
2005 __bucket_list_[__chash]->__next_ = __cp;
Howard Hinnant324bb032010-08-22 00:02:43 +00002006
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002007 }
2008 }
2009 }
2010 }
2011 }
2012}
2013
2014template <class _Tp, class _Hash, class _Equal, class _Alloc>
2015template <class _Key>
2016typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2017__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k)
2018{
2019 size_t __hash = hash_function()(__k);
2020 size_type __bc = bucket_count();
2021 if (__bc != 0)
2022 {
Howard Hinnant7a445152012-07-06 17:31:14 +00002023 size_t __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002024 __node_pointer __nd = __bucket_list_[__chash];
2025 if (__nd != nullptr)
2026 {
2027 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00002028 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002029 __nd = __nd->__next_)
2030 {
2031 if (key_eq()(__nd->__value_, __k))
Howard Hinnant39213642013-07-23 22:01:58 +00002032#if _LIBCPP_DEBUG_LEVEL >= 2
2033 return iterator(__nd, this);
2034#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002035 return iterator(__nd);
Howard Hinnant39213642013-07-23 22:01:58 +00002036#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002037 }
2038 }
2039 }
2040 return end();
2041}
2042
2043template <class _Tp, class _Hash, class _Equal, class _Alloc>
2044template <class _Key>
2045typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
2046__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const
2047{
2048 size_t __hash = hash_function()(__k);
2049 size_type __bc = bucket_count();
2050 if (__bc != 0)
2051 {
Howard Hinnant7a445152012-07-06 17:31:14 +00002052 size_t __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002053 __node_const_pointer __nd = __bucket_list_[__chash];
2054 if (__nd != nullptr)
2055 {
2056 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00002057 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002058 __nd = __nd->__next_)
2059 {
2060 if (key_eq()(__nd->__value_, __k))
Howard Hinnant39213642013-07-23 22:01:58 +00002061#if _LIBCPP_DEBUG_LEVEL >= 2
2062 return const_iterator(__nd, this);
2063#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002064 return const_iterator(__nd);
Howard Hinnant39213642013-07-23 22:01:58 +00002065#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002066 }
2067 }
Howard Hinnant324bb032010-08-22 00:02:43 +00002068
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002069 }
2070 return end();
2071}
2072
Howard Hinnant73d21a42010-09-04 23:28:19 +00002073#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
2074#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002075
2076template <class _Tp, class _Hash, class _Equal, class _Alloc>
2077template <class ..._Args>
2078typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
2079__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args)
2080{
2081 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00002082 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00002083 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002084 __h.get_deleter().__value_constructed = true;
2085 __h->__hash_ = hash_function()(__h->__value_);
2086 __h->__next_ = nullptr;
2087 return __h;
2088}
2089
Howard Hinnant73d21a42010-09-04 23:28:19 +00002090#endif // _LIBCPP_HAS_NO_VARIADICS
2091
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002092template <class _Tp, class _Hash, class _Equal, class _Alloc>
2093typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
2094__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(value_type&& __v,
2095 size_t __hash)
2096{
2097 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00002098 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00002099 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::move(__v));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002100 __h.get_deleter().__value_constructed = true;
2101 __h->__hash_ = __hash;
2102 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00002103 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002104}
2105
Howard Hinnant73d21a42010-09-04 23:28:19 +00002106#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002107
2108template <class _Tp, class _Hash, class _Equal, class _Alloc>
2109typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
2110__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v)
2111{
2112 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00002113 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00002114 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002115 __h.get_deleter().__value_constructed = true;
2116 __h->__hash_ = hash_function()(__h->__value_);
2117 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00002118 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002119}
2120
Howard Hinnant73d21a42010-09-04 23:28:19 +00002121#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002122
2123template <class _Tp, class _Hash, class _Equal, class _Alloc>
2124typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
2125__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v,
2126 size_t __hash)
2127{
2128 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00002129 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00002130 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002131 __h.get_deleter().__value_constructed = true;
2132 __h->__hash_ = __hash;
2133 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00002134 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002135}
2136
2137template <class _Tp, class _Hash, class _Equal, class _Alloc>
2138typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2139__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p)
2140{
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002141 __node_pointer __np = __p.__node_;
Howard Hinnant39213642013-07-23 22:01:58 +00002142#if _LIBCPP_DEBUG_LEVEL >= 2
2143 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
2144 "unordered container erase(iterator) called with an iterator not"
2145 " referring to this container");
2146 _LIBCPP_ASSERT(__p != end(),
2147 "unordered container erase(iterator) called with a non-dereferenceable iterator");
2148 iterator __r(__np, this);
2149#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002150 iterator __r(__np);
Howard Hinnant39213642013-07-23 22:01:58 +00002151#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002152 ++__r;
2153 remove(__p);
2154 return __r;
2155}
2156
2157template <class _Tp, class _Hash, class _Equal, class _Alloc>
2158typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2159__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first,
2160 const_iterator __last)
2161{
Howard Hinnant39213642013-07-23 22:01:58 +00002162#if _LIBCPP_DEBUG_LEVEL >= 2
2163 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this,
2164 "unodered container::erase(iterator, iterator) called with an iterator not"
2165 " referring to this unodered container");
2166 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__last) == this,
2167 "unodered container::erase(iterator, iterator) called with an iterator not"
2168 " referring to this unodered container");
2169#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002170 for (const_iterator __p = __first; __first != __last; __p = __first)
2171 {
2172 ++__first;
2173 erase(__p);
2174 }
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002175 __node_pointer __np = __last.__node_;
Howard Hinnant39213642013-07-23 22:01:58 +00002176#if _LIBCPP_DEBUG_LEVEL >= 2
2177 return iterator (__np, this);
2178#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002179 return iterator (__np);
Howard Hinnant39213642013-07-23 22:01:58 +00002180#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002181}
2182
2183template <class _Tp, class _Hash, class _Equal, class _Alloc>
2184template <class _Key>
2185typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2186__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k)
2187{
2188 iterator __i = find(__k);
2189 if (__i == end())
2190 return 0;
2191 erase(__i);
2192 return 1;
2193}
2194
2195template <class _Tp, class _Hash, class _Equal, class _Alloc>
2196template <class _Key>
2197typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2198__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k)
2199{
2200 size_type __r = 0;
2201 iterator __i = find(__k);
2202 if (__i != end())
2203 {
2204 iterator __e = end();
2205 do
2206 {
2207 erase(__i++);
2208 ++__r;
2209 } while (__i != __e && key_eq()(*__i, __k));
2210 }
2211 return __r;
2212}
2213
2214template <class _Tp, class _Hash, class _Equal, class _Alloc>
2215typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00002216__hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002217{
2218 // current node
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002219 __node_pointer __cn = __p.__node_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002220 size_type __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:14 +00002221 size_t __chash = __constrain_hash(__cn->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002222 // find previous node
2223 __node_pointer __pn = __bucket_list_[__chash];
2224 for (; __pn->__next_ != __cn; __pn = __pn->__next_)
2225 ;
2226 // Fix up __bucket_list_
2227 // if __pn is not in same bucket (before begin is not in same bucket) &&
2228 // if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002229 if (__pn == static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()))
2230 || __constrain_hash(__pn->__hash_, __bc) != __chash)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002231 {
Howard Hinnant7a445152012-07-06 17:31:14 +00002232 if (__cn->__next_ == nullptr || __constrain_hash(__cn->__next_->__hash_, __bc) != __chash)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002233 __bucket_list_[__chash] = nullptr;
2234 }
2235 // if __cn->__next_ is not in same bucket (nullptr is in same bucket)
2236 if (__cn->__next_ != nullptr)
2237 {
Howard Hinnant7a445152012-07-06 17:31:14 +00002238 size_t __nhash = __constrain_hash(__cn->__next_->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002239 if (__nhash != __chash)
2240 __bucket_list_[__nhash] = __pn;
2241 }
2242 // remove __cn
2243 __pn->__next_ = __cn->__next_;
2244 __cn->__next_ = nullptr;
2245 --size();
Howard Hinnant39213642013-07-23 22:01:58 +00002246#if _LIBCPP_DEBUG_LEVEL >= 2
2247 __c_node* __c = __get_db()->__find_c_and_lock(this);
2248 for (__i_node** __p = __c->end_; __p != __c->beg_; )
2249 {
2250 --__p;
2251 iterator* __i = static_cast<iterator*>((*__p)->__i_);
2252 if (__i->__node_ == __cn)
2253 {
2254 (*__p)->__c_ = nullptr;
2255 if (--__c->end_ != __p)
2256 memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*));
2257 }
2258 }
2259 __get_db()->unlock();
2260#endif
Howard Hinnant99968442011-11-29 18:15:50 +00002261 return __node_holder(__cn, _Dp(__node_alloc(), true));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002262}
2263
2264template <class _Tp, class _Hash, class _Equal, class _Alloc>
2265template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39 +00002266inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002267typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2268__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const
2269{
2270 return static_cast<size_type>(find(__k) != end());
2271}
2272
2273template <class _Tp, class _Hash, class _Equal, class _Alloc>
2274template <class _Key>
2275typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2276__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const
2277{
2278 size_type __r = 0;
2279 const_iterator __i = find(__k);
2280 if (__i != end())
2281 {
2282 const_iterator __e = end();
2283 do
2284 {
2285 ++__i;
2286 ++__r;
2287 } while (__i != __e && key_eq()(*__i, __k));
2288 }
2289 return __r;
2290}
2291
2292template <class _Tp, class _Hash, class _Equal, class _Alloc>
2293template <class _Key>
2294pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
2295 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
2296__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
2297 const _Key& __k)
2298{
2299 iterator __i = find(__k);
2300 iterator __j = __i;
2301 if (__i != end())
2302 ++__j;
2303 return pair<iterator, iterator>(__i, __j);
2304}
2305
2306template <class _Tp, class _Hash, class _Equal, class _Alloc>
2307template <class _Key>
2308pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
2309 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
2310__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
2311 const _Key& __k) const
2312{
2313 const_iterator __i = find(__k);
2314 const_iterator __j = __i;
2315 if (__i != end())
2316 ++__j;
2317 return pair<const_iterator, const_iterator>(__i, __j);
2318}
2319
2320template <class _Tp, class _Hash, class _Equal, class _Alloc>
2321template <class _Key>
2322pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
2323 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
2324__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
2325 const _Key& __k)
2326{
2327 iterator __i = find(__k);
2328 iterator __j = __i;
2329 if (__i != end())
2330 {
2331 iterator __e = end();
2332 do
2333 {
2334 ++__j;
2335 } while (__j != __e && key_eq()(*__j, __k));
2336 }
2337 return pair<iterator, iterator>(__i, __j);
2338}
2339
2340template <class _Tp, class _Hash, class _Equal, class _Alloc>
2341template <class _Key>
2342pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
2343 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
2344__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
2345 const _Key& __k) const
2346{
2347 const_iterator __i = find(__k);
2348 const_iterator __j = __i;
2349 if (__i != end())
2350 {
2351 const_iterator __e = end();
2352 do
2353 {
2354 ++__j;
2355 } while (__j != __e && key_eq()(*__j, __k));
2356 }
2357 return pair<const_iterator, const_iterator>(__i, __j);
2358}
2359
2360template <class _Tp, class _Hash, class _Equal, class _Alloc>
2361void
2362__hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00002363 _NOEXCEPT_(
2364 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
2365 __is_nothrow_swappable<__pointer_allocator>::value) &&
2366 (!__node_traits::propagate_on_container_swap::value ||
2367 __is_nothrow_swappable<__node_allocator>::value) &&
2368 __is_nothrow_swappable<hasher>::value &&
2369 __is_nothrow_swappable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002370{
2371 {
2372 __node_pointer_pointer __npp = __bucket_list_.release();
2373 __bucket_list_.reset(__u.__bucket_list_.release());
2374 __u.__bucket_list_.reset(__npp);
2375 }
Howard Hinnant0949eed2011-06-30 21:18:19 +00002376 _VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002377 __swap_alloc(__bucket_list_.get_deleter().__alloc(),
2378 __u.__bucket_list_.get_deleter().__alloc());
2379 __swap_alloc(__node_alloc(), __u.__node_alloc());
Howard Hinnant0949eed2011-06-30 21:18:19 +00002380 _VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002381 __p2_.swap(__u.__p2_);
2382 __p3_.swap(__u.__p3_);
2383 if (size() > 0)
Howard Hinnant7a445152012-07-06 17:31:14 +00002384 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002385 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002386 if (__u.size() > 0)
Howard Hinnant7a445152012-07-06 17:31:14 +00002387 __u.__bucket_list_[__constrain_hash(__u.__p1_.first().__next_->__hash_, __u.bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002388 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__u.__p1_.first()));
Howard Hinnant39213642013-07-23 22:01:58 +00002389#if _LIBCPP_DEBUG_LEVEL >= 2
2390 __get_db()->swap(this, &__u);
2391#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002392}
2393
2394template <class _Tp, class _Hash, class _Equal, class _Alloc>
2395typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2396__hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const
2397{
Howard Hinnant0bb0a7c2013-07-29 19:05:47 +00002398 _LIBCPP_ASSERT(__n < bucket_count(),
2399 "unordered container::bucket_size(n) called with n >= bucket_count()");
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002400 __node_const_pointer __np = __bucket_list_[__n];
2401 size_type __bc = bucket_count();
2402 size_type __r = 0;
2403 if (__np != nullptr)
2404 {
2405 for (__np = __np->__next_; __np != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00002406 __constrain_hash(__np->__hash_, __bc) == __n;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002407 __np = __np->__next_, ++__r)
2408 ;
2409 }
2410 return __r;
2411}
2412
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00002413template <class _Tp, class _Hash, class _Equal, class _Alloc>
2414inline _LIBCPP_INLINE_VISIBILITY
2415void
2416swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x,
2417 __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y)
2418 _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
2419{
2420 __x.swap(__y);
2421}
2422
Howard Hinnant39213642013-07-23 22:01:58 +00002423#if _LIBCPP_DEBUG_LEVEL >= 2
2424
2425template <class _Tp, class _Hash, class _Equal, class _Alloc>
2426bool
2427__hash_table<_Tp, _Hash, _Equal, _Alloc>::__dereferenceable(const const_iterator* __i) const
2428{
2429 return __i->__node_ != nullptr;
2430}
2431
2432template <class _Tp, class _Hash, class _Equal, class _Alloc>
2433bool
2434__hash_table<_Tp, _Hash, _Equal, _Alloc>::__decrementable(const const_iterator*) const
2435{
2436 return false;
2437}
2438
2439template <class _Tp, class _Hash, class _Equal, class _Alloc>
2440bool
2441__hash_table<_Tp, _Hash, _Equal, _Alloc>::__addable(const const_iterator*, ptrdiff_t) const
2442{
2443 return false;
2444}
2445
2446template <class _Tp, class _Hash, class _Equal, class _Alloc>
2447bool
2448__hash_table<_Tp, _Hash, _Equal, _Alloc>::__subscriptable(const const_iterator*, ptrdiff_t) const
2449{
2450 return false;
2451}
2452
2453#endif // _LIBCPP_DEBUG_LEVEL >= 2
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002454_LIBCPP_END_NAMESPACE_STD
2455
2456#endif // _LIBCPP__HASH_TABLE