blob: 55398e4d026e156105ad6cea2c0031dd5f685921 [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 Hinnant7a445152012-07-06 17:31:14 +0000956 {return __constrain_hash(hash_function()(__k), bucket_count());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000957
958 template <class _Key>
959 iterator find(const _Key& __x);
960 template <class _Key>
961 const_iterator find(const _Key& __x) const;
962
Howard Hinnant99968442011-11-29 18:15:50 +0000963 typedef __hash_node_destructor<__node_allocator> _Dp;
964 typedef unique_ptr<__node, _Dp> __node_holder;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000965
966 iterator erase(const_iterator __p);
967 iterator erase(const_iterator __first, const_iterator __last);
968 template <class _Key>
969 size_type __erase_unique(const _Key& __k);
970 template <class _Key>
971 size_type __erase_multi(const _Key& __k);
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000972 __node_holder remove(const_iterator __p) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000973
974 template <class _Key>
975 size_type __count_unique(const _Key& __k) const;
976 template <class _Key>
977 size_type __count_multi(const _Key& __k) const;
978
979 template <class _Key>
980 pair<iterator, iterator>
981 __equal_range_unique(const _Key& __k);
982 template <class _Key>
983 pair<const_iterator, const_iterator>
984 __equal_range_unique(const _Key& __k) const;
985
986 template <class _Key>
987 pair<iterator, iterator>
988 __equal_range_multi(const _Key& __k);
989 template <class _Key>
990 pair<const_iterator, const_iterator>
991 __equal_range_multi(const _Key& __k) const;
992
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000993 void swap(__hash_table& __u)
994 _NOEXCEPT_(
995 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
996 __is_nothrow_swappable<__pointer_allocator>::value) &&
997 (!__node_traits::propagate_on_container_swap::value ||
998 __is_nothrow_swappable<__node_allocator>::value) &&
999 __is_nothrow_swappable<hasher>::value &&
1000 __is_nothrow_swappable<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001001
Howard Hinnant99acc502010-09-21 17:32:39 +00001002 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001003 size_type max_bucket_count() const _NOEXCEPT
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001004 {return __pointer_alloc_traits::max_size(__bucket_list_.get_deleter().__alloc());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001005 size_type bucket_size(size_type __n) const;
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001006 _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001007 {
1008 size_type __bc = bucket_count();
1009 return __bc != 0 ? (float)size() / __bc : 0.f;
1010 }
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001011 _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT
Howard Hinnant0949eed2011-06-30 21:18:19 +00001012 {max_load_factor() = _VSTD::max(__mlf, load_factor());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001013
Howard Hinnant39213642013-07-23 22:01:58 +00001014 _LIBCPP_INLINE_VISIBILITY
1015 local_iterator
1016 begin(size_type __n)
1017 {
1018#if _LIBCPP_DEBUG_LEVEL >= 2
1019 return local_iterator(__bucket_list_[__n], __n, bucket_count(), this);
1020#else
1021 return local_iterator(__bucket_list_[__n], __n, bucket_count());
1022#endif
1023 }
1024
1025 _LIBCPP_INLINE_VISIBILITY
1026 local_iterator
1027 end(size_type __n)
1028 {
1029#if _LIBCPP_DEBUG_LEVEL >= 2
1030 return local_iterator(nullptr, __n, bucket_count(), this);
1031#else
1032 return local_iterator(nullptr, __n, bucket_count());
1033#endif
1034 }
1035
1036 _LIBCPP_INLINE_VISIBILITY
1037 const_local_iterator
1038 cbegin(size_type __n) const
1039 {
1040#if _LIBCPP_DEBUG_LEVEL >= 2
1041 return const_local_iterator(__bucket_list_[__n], __n, bucket_count(), this);
1042#else
1043 return const_local_iterator(__bucket_list_[__n], __n, bucket_count());
1044#endif
1045 }
1046
1047 _LIBCPP_INLINE_VISIBILITY
1048 const_local_iterator
1049 cend(size_type __n) const
1050 {
1051#if _LIBCPP_DEBUG_LEVEL >= 2
1052 return const_local_iterator(nullptr, __n, bucket_count(), this);
1053#else
1054 return const_local_iterator(nullptr, __n, bucket_count());
1055#endif
1056 }
1057
1058#if _LIBCPP_DEBUG_LEVEL >= 2
1059
1060 bool __dereferenceable(const const_iterator* __i) const;
1061 bool __decrementable(const const_iterator* __i) const;
1062 bool __addable(const const_iterator* __i, ptrdiff_t __n) const;
1063 bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const;
1064
1065#endif // _LIBCPP_DEBUG_LEVEL >= 2
1066
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001067private:
1068 void __rehash(size_type __n);
1069
Howard Hinnant73d21a42010-09-04 23:28:19 +00001070#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1071#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001072 template <class ..._Args>
1073 __node_holder __construct_node(_Args&& ...__args);
Howard Hinnantbfd55302010-09-04 23:46:48 +00001074#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001075 __node_holder __construct_node(value_type&& __v, size_t __hash);
Howard Hinnant73d21a42010-09-04 23:28:19 +00001076#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001077 __node_holder __construct_node(const value_type& __v);
1078#endif
1079 __node_holder __construct_node(const value_type& __v, size_t __hash);
1080
Howard Hinnant99acc502010-09-21 17:32:39 +00001081 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001082 void __copy_assign_alloc(const __hash_table& __u)
1083 {__copy_assign_alloc(__u, integral_constant<bool,
1084 __node_traits::propagate_on_container_copy_assignment::value>());}
1085 void __copy_assign_alloc(const __hash_table& __u, true_type);
Howard Hinnant99acc502010-09-21 17:32:39 +00001086 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantec3773c2011-12-01 20:21:04 +00001087 void __copy_assign_alloc(const __hash_table&, false_type) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001088
1089 void __move_assign(__hash_table& __u, false_type);
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001090 void __move_assign(__hash_table& __u, true_type)
1091 _NOEXCEPT_(
1092 is_nothrow_move_assignable<__node_allocator>::value &&
1093 is_nothrow_move_assignable<hasher>::value &&
1094 is_nothrow_move_assignable<key_equal>::value);
1095 _LIBCPP_INLINE_VISIBILITY
1096 void __move_assign_alloc(__hash_table& __u)
1097 _NOEXCEPT_(
1098 !__node_traits::propagate_on_container_move_assignment::value ||
1099 (is_nothrow_move_assignable<__pointer_allocator>::value &&
1100 is_nothrow_move_assignable<__node_allocator>::value))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001101 {__move_assign_alloc(__u, integral_constant<bool,
1102 __node_traits::propagate_on_container_move_assignment::value>());}
Howard Hinnant99acc502010-09-21 17:32:39 +00001103 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001104 void __move_assign_alloc(__hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001105 _NOEXCEPT_(
1106 is_nothrow_move_assignable<__pointer_allocator>::value &&
1107 is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001108 {
1109 __bucket_list_.get_deleter().__alloc() =
Howard Hinnant0949eed2011-06-30 21:18:19 +00001110 _VSTD::move(__u.__bucket_list_.get_deleter().__alloc());
1111 __node_alloc() = _VSTD::move(__u.__node_alloc());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001112 }
Howard Hinnant99acc502010-09-21 17:32:39 +00001113 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001114 void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001115
Howard Hinnant99968442011-11-29 18:15:50 +00001116 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:39 +00001117 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001118 static
1119 void
Howard Hinnant99968442011-11-29 18:15:50 +00001120 __swap_alloc(_Ap& __x, _Ap& __y)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001121 _NOEXCEPT_(
Howard Hinnant99968442011-11-29 18:15:50 +00001122 !allocator_traits<_Ap>::propagate_on_container_swap::value ||
1123 __is_nothrow_swappable<_Ap>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001124 {
1125 __swap_alloc(__x, __y,
1126 integral_constant<bool,
Howard Hinnant99968442011-11-29 18:15:50 +00001127 allocator_traits<_Ap>::propagate_on_container_swap::value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001128 >());
1129 }
1130
Howard Hinnant99968442011-11-29 18:15:50 +00001131 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:39 +00001132 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001133 static
1134 void
Howard Hinnant99968442011-11-29 18:15:50 +00001135 __swap_alloc(_Ap& __x, _Ap& __y, true_type)
1136 _NOEXCEPT_(__is_nothrow_swappable<_Ap>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001137 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001138 using _VSTD::swap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001139 swap(__x, __y);
1140 }
1141
Howard Hinnant99968442011-11-29 18:15:50 +00001142 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:39 +00001143 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001144 static
1145 void
Howard Hinnantec3773c2011-12-01 20:21:04 +00001146 __swap_alloc(_Ap&, _Ap&, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001147
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001148 void __deallocate(__node_pointer __np) _NOEXCEPT;
1149 __node_pointer __detach() _NOEXCEPT;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001150
1151 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_map;
1152 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001153};
1154
1155template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001156inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001157__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table()
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001158 _NOEXCEPT_(
1159 is_nothrow_default_constructible<__bucket_list>::value &&
1160 is_nothrow_default_constructible<__first_node>::value &&
1161 is_nothrow_default_constructible<hasher>::value &&
1162 is_nothrow_default_constructible<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001163 : __p2_(0),
1164 __p3_(1.0f)
1165{
1166}
1167
1168template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001169inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001170__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
1171 const key_equal& __eql)
1172 : __bucket_list_(nullptr, __bucket_list_deleter()),
1173 __p1_(),
1174 __p2_(0, __hf),
1175 __p3_(1.0f, __eql)
1176{
1177}
1178
1179template <class _Tp, class _Hash, class _Equal, class _Alloc>
1180__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
1181 const key_equal& __eql,
1182 const allocator_type& __a)
1183 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1184 __p1_(__node_allocator(__a)),
1185 __p2_(0, __hf),
1186 __p3_(1.0f, __eql)
1187{
1188}
1189
1190template <class _Tp, class _Hash, class _Equal, class _Alloc>
1191__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
1192 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1193 __p1_(__node_allocator(__a)),
1194 __p2_(0),
1195 __p3_(1.0f)
1196{
1197}
1198
1199template <class _Tp, class _Hash, class _Equal, class _Alloc>
1200__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
1201 : __bucket_list_(nullptr,
1202 __bucket_list_deleter(allocator_traits<__pointer_allocator>::
1203 select_on_container_copy_construction(
1204 __u.__bucket_list_.get_deleter().__alloc()), 0)),
1205 __p1_(allocator_traits<__node_allocator>::
1206 select_on_container_copy_construction(__u.__node_alloc())),
1207 __p2_(0, __u.hash_function()),
1208 __p3_(__u.__p3_)
1209{
1210}
1211
1212template <class _Tp, class _Hash, class _Equal, class _Alloc>
1213__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u,
1214 const allocator_type& __a)
1215 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1216 __p1_(__node_allocator(__a)),
1217 __p2_(0, __u.hash_function()),
1218 __p3_(__u.__p3_)
1219{
1220}
1221
Howard Hinnant73d21a42010-09-04 23:28:19 +00001222#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001223
1224template <class _Tp, class _Hash, class _Equal, class _Alloc>
1225__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001226 _NOEXCEPT_(
1227 is_nothrow_move_constructible<__bucket_list>::value &&
1228 is_nothrow_move_constructible<__first_node>::value &&
1229 is_nothrow_move_constructible<hasher>::value &&
1230 is_nothrow_move_constructible<key_equal>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +00001231 : __bucket_list_(_VSTD::move(__u.__bucket_list_)),
1232 __p1_(_VSTD::move(__u.__p1_)),
1233 __p2_(_VSTD::move(__u.__p2_)),
1234 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001235{
1236 if (size() > 0)
1237 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001238 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001239 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001240 __u.__p1_.first().__next_ = nullptr;
1241 __u.size() = 0;
1242 }
1243}
1244
1245template <class _Tp, class _Hash, class _Equal, class _Alloc>
1246__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u,
1247 const allocator_type& __a)
1248 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1249 __p1_(__node_allocator(__a)),
Howard Hinnant0949eed2011-06-30 21:18:19 +00001250 __p2_(0, _VSTD::move(__u.hash_function())),
1251 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001252{
1253 if (__a == allocator_type(__u.__node_alloc()))
1254 {
1255 __bucket_list_.reset(__u.__bucket_list_.release());
1256 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
1257 __u.__bucket_list_.get_deleter().size() = 0;
1258 if (__u.size() > 0)
1259 {
1260 __p1_.first().__next_ = __u.__p1_.first().__next_;
1261 __u.__p1_.first().__next_ = nullptr;
Howard Hinnant7a445152012-07-06 17:31:14 +00001262 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001263 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001264 size() = __u.size();
1265 __u.size() = 0;
1266 }
1267 }
1268}
1269
Howard Hinnant73d21a42010-09-04 23:28:19 +00001270#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001271
1272template <class _Tp, class _Hash, class _Equal, class _Alloc>
1273__hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table()
1274{
1275 __deallocate(__p1_.first().__next_);
Howard Hinnant39213642013-07-23 22:01:58 +00001276#if _LIBCPP_DEBUG_LEVEL >= 2
1277 __get_db()->__erase_c(this);
1278#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001279}
1280
1281template <class _Tp, class _Hash, class _Equal, class _Alloc>
1282void
1283__hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc(
1284 const __hash_table& __u, true_type)
1285{
1286 if (__node_alloc() != __u.__node_alloc())
1287 {
1288 clear();
1289 __bucket_list_.reset();
1290 __bucket_list_.get_deleter().size() = 0;
1291 }
1292 __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc();
1293 __node_alloc() = __u.__node_alloc();
1294}
1295
1296template <class _Tp, class _Hash, class _Equal, class _Alloc>
1297__hash_table<_Tp, _Hash, _Equal, _Alloc>&
1298__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u)
1299{
1300 if (this != &__u)
1301 {
1302 __copy_assign_alloc(__u);
1303 hash_function() = __u.hash_function();
1304 key_eq() = __u.key_eq();
1305 max_load_factor() = __u.max_load_factor();
1306 __assign_multi(__u.begin(), __u.end());
1307 }
1308 return *this;
1309}
1310
1311template <class _Tp, class _Hash, class _Equal, class _Alloc>
1312void
1313__hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate(__node_pointer __np)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001314 _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001315{
1316 __node_allocator& __na = __node_alloc();
1317 while (__np != nullptr)
1318 {
1319 __node_pointer __next = __np->__next_;
Howard Hinnant39213642013-07-23 22:01:58 +00001320#if _LIBCPP_DEBUG_LEVEL >= 2
1321 __c_node* __c = __get_db()->__find_c_and_lock(this);
1322 for (__i_node** __p = __c->end_; __p != __c->beg_; )
1323 {
1324 --__p;
1325 iterator* __i = static_cast<iterator*>((*__p)->__i_);
1326 if (__i->__node_ == __np)
1327 {
1328 (*__p)->__c_ = nullptr;
1329 if (--__c->end_ != __p)
1330 memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*));
1331 }
1332 }
1333 __get_db()->unlock();
1334#endif
Howard Hinnant0949eed2011-06-30 21:18:19 +00001335 __node_traits::destroy(__na, _VSTD::addressof(__np->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001336 __node_traits::deallocate(__na, __np, 1);
1337 __np = __next;
1338 }
1339}
1340
1341template <class _Tp, class _Hash, class _Equal, class _Alloc>
1342typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_pointer
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001343__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001344{
1345 size_type __bc = bucket_count();
1346 for (size_type __i = 0; __i < __bc; ++__i)
1347 __bucket_list_[__i] = nullptr;
1348 size() = 0;
1349 __node_pointer __cache = __p1_.first().__next_;
1350 __p1_.first().__next_ = nullptr;
1351 return __cache;
1352}
1353
Howard Hinnant73d21a42010-09-04 23:28:19 +00001354#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001355
1356template <class _Tp, class _Hash, class _Equal, class _Alloc>
1357void
1358__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
1359 __hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001360 _NOEXCEPT_(
1361 is_nothrow_move_assignable<__node_allocator>::value &&
1362 is_nothrow_move_assignable<hasher>::value &&
1363 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001364{
1365 clear();
1366 __bucket_list_.reset(__u.__bucket_list_.release());
1367 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
1368 __u.__bucket_list_.get_deleter().size() = 0;
1369 __move_assign_alloc(__u);
1370 size() = __u.size();
Howard Hinnant0949eed2011-06-30 21:18:19 +00001371 hash_function() = _VSTD::move(__u.hash_function());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001372 max_load_factor() = __u.max_load_factor();
Howard Hinnant0949eed2011-06-30 21:18:19 +00001373 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001374 __p1_.first().__next_ = __u.__p1_.first().__next_;
1375 if (size() > 0)
1376 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001377 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001378 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001379 __u.__p1_.first().__next_ = nullptr;
1380 __u.size() = 0;
1381 }
Howard Hinnant39213642013-07-23 22:01:58 +00001382#if _LIBCPP_DEBUG_LEVEL >= 2
1383 __get_db()->swap(this, &__u);
1384#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001385}
1386
1387template <class _Tp, class _Hash, class _Equal, class _Alloc>
1388void
1389__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
1390 __hash_table& __u, false_type)
1391{
1392 if (__node_alloc() == __u.__node_alloc())
1393 __move_assign(__u, true_type());
1394 else
1395 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001396 hash_function() = _VSTD::move(__u.hash_function());
1397 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001398 max_load_factor() = __u.max_load_factor();
1399 if (bucket_count() != 0)
1400 {
1401 __node_pointer __cache = __detach();
1402#ifndef _LIBCPP_NO_EXCEPTIONS
1403 try
1404 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001405#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001406 const_iterator __i = __u.begin();
1407 while (__cache != nullptr && __u.size() != 0)
1408 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001409 __cache->__value_ = _VSTD::move(__u.remove(__i++)->__value_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001410 __node_pointer __next = __cache->__next_;
1411 __node_insert_multi(__cache);
1412 __cache = __next;
1413 }
1414#ifndef _LIBCPP_NO_EXCEPTIONS
1415 }
1416 catch (...)
1417 {
1418 __deallocate(__cache);
1419 throw;
1420 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001421#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001422 __deallocate(__cache);
1423 }
1424 const_iterator __i = __u.begin();
1425 while (__u.size() != 0)
1426 {
1427 __node_holder __h =
Howard Hinnant0949eed2011-06-30 21:18:19 +00001428 __construct_node(_VSTD::move(__u.remove(__i++)->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001429 __node_insert_multi(__h.get());
1430 __h.release();
1431 }
1432 }
1433}
1434
1435template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001436inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001437__hash_table<_Tp, _Hash, _Equal, _Alloc>&
1438__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001439 _NOEXCEPT_(
1440 __node_traits::propagate_on_container_move_assignment::value &&
1441 is_nothrow_move_assignable<__node_allocator>::value &&
1442 is_nothrow_move_assignable<hasher>::value &&
1443 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001444{
1445 __move_assign(__u, integral_constant<bool,
1446 __node_traits::propagate_on_container_move_assignment::value>());
1447 return *this;
1448}
1449
Howard Hinnant73d21a42010-09-04 23:28:19 +00001450#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001451
1452template <class _Tp, class _Hash, class _Equal, class _Alloc>
1453template <class _InputIterator>
1454void
1455__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first,
1456 _InputIterator __last)
1457{
1458 if (bucket_count() != 0)
1459 {
1460 __node_pointer __cache = __detach();
1461#ifndef _LIBCPP_NO_EXCEPTIONS
1462 try
1463 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001464#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001465 for (; __cache != nullptr && __first != __last; ++__first)
1466 {
1467 __cache->__value_ = *__first;
1468 __node_pointer __next = __cache->__next_;
1469 __node_insert_unique(__cache);
1470 __cache = __next;
1471 }
1472#ifndef _LIBCPP_NO_EXCEPTIONS
1473 }
1474 catch (...)
1475 {
1476 __deallocate(__cache);
1477 throw;
1478 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001479#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001480 __deallocate(__cache);
1481 }
1482 for (; __first != __last; ++__first)
1483 __insert_unique(*__first);
1484}
1485
1486template <class _Tp, class _Hash, class _Equal, class _Alloc>
1487template <class _InputIterator>
1488void
1489__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first,
1490 _InputIterator __last)
1491{
1492 if (bucket_count() != 0)
1493 {
1494 __node_pointer __cache = __detach();
1495#ifndef _LIBCPP_NO_EXCEPTIONS
1496 try
1497 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001498#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001499 for (; __cache != nullptr && __first != __last; ++__first)
1500 {
1501 __cache->__value_ = *__first;
1502 __node_pointer __next = __cache->__next_;
1503 __node_insert_multi(__cache);
1504 __cache = __next;
1505 }
1506#ifndef _LIBCPP_NO_EXCEPTIONS
1507 }
1508 catch (...)
1509 {
1510 __deallocate(__cache);
1511 throw;
1512 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001513#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001514 __deallocate(__cache);
1515 }
1516 for (; __first != __last; ++__first)
1517 __insert_multi(*__first);
1518}
1519
1520template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001521inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001522typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001523__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001524{
Howard Hinnant39213642013-07-23 22:01:58 +00001525#if _LIBCPP_DEBUG_LEVEL >= 2
1526 return iterator(__p1_.first().__next_, this);
1527#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001528 return iterator(__p1_.first().__next_);
Howard Hinnant39213642013-07-23 22:01:58 +00001529#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001530}
1531
1532template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001533inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001534typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001535__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001536{
Howard Hinnant39213642013-07-23 22:01:58 +00001537#if _LIBCPP_DEBUG_LEVEL >= 2
1538 return iterator(nullptr, this);
1539#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001540 return iterator(nullptr);
Howard Hinnant39213642013-07-23 22:01:58 +00001541#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001542}
1543
1544template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001545inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001546typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001547__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001548{
Howard Hinnant39213642013-07-23 22:01:58 +00001549#if _LIBCPP_DEBUG_LEVEL >= 2
1550 return const_iterator(__p1_.first().__next_, this);
1551#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001552 return const_iterator(__p1_.first().__next_);
Howard Hinnant39213642013-07-23 22:01:58 +00001553#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001554}
1555
1556template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001557inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001558typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001559__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001560{
Howard Hinnant39213642013-07-23 22:01:58 +00001561#if _LIBCPP_DEBUG_LEVEL >= 2
1562 return const_iterator(nullptr, this);
1563#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001564 return const_iterator(nullptr);
Howard Hinnant39213642013-07-23 22:01:58 +00001565#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001566}
1567
1568template <class _Tp, class _Hash, class _Equal, class _Alloc>
1569void
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001570__hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001571{
1572 if (size() > 0)
1573 {
1574 __deallocate(__p1_.first().__next_);
1575 __p1_.first().__next_ = nullptr;
1576 size_type __bc = bucket_count();
Howard Hinnant9f66bff2011-07-05 14:14:17 +00001577 for (size_type __i = 0; __i < __bc; ++__i)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001578 __bucket_list_[__i] = nullptr;
1579 size() = 0;
1580 }
1581}
1582
1583template <class _Tp, class _Hash, class _Equal, class _Alloc>
1584pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1585__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd)
1586{
1587 __nd->__hash_ = hash_function()(__nd->__value_);
1588 size_type __bc = bucket_count();
1589 bool __inserted = false;
1590 __node_pointer __ndptr;
1591 size_t __chash;
1592 if (__bc != 0)
1593 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001594 __chash = __constrain_hash(__nd->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001595 __ndptr = __bucket_list_[__chash];
1596 if (__ndptr != nullptr)
1597 {
1598 for (__ndptr = __ndptr->__next_; __ndptr != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001599 __constrain_hash(__ndptr->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001600 __ndptr = __ndptr->__next_)
1601 {
1602 if (key_eq()(__ndptr->__value_, __nd->__value_))
1603 goto __done;
1604 }
1605 }
1606 }
1607 {
1608 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1609 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001610 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001611 size_type(ceil(float(size() + 1) / max_load_factor()))));
1612 __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:14 +00001613 __chash = __constrain_hash(__nd->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001614 }
1615 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1616 __node_pointer __pn = __bucket_list_[__chash];
1617 if (__pn == nullptr)
1618 {
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001619 __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001620 __nd->__next_ = __pn->__next_;
1621 __pn->__next_ = __nd;
1622 // fix up __bucket_list_
1623 __bucket_list_[__chash] = __pn;
1624 if (__nd->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:14 +00001625 __bucket_list_[__constrain_hash(__nd->__next_->__hash_, __bc)] = __nd;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001626 }
1627 else
1628 {
1629 __nd->__next_ = __pn->__next_;
1630 __pn->__next_ = __nd;
1631 }
1632 __ndptr = __nd;
1633 // increment size
1634 ++size();
1635 __inserted = true;
1636 }
1637__done:
Howard Hinnant39213642013-07-23 22:01:58 +00001638#if _LIBCPP_DEBUG_LEVEL >= 2
1639 return pair<iterator, bool>(iterator(__ndptr, this), __inserted);
1640#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001641 return pair<iterator, bool>(iterator(__ndptr), __inserted);
Howard Hinnant39213642013-07-23 22:01:58 +00001642#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001643}
1644
1645template <class _Tp, class _Hash, class _Equal, class _Alloc>
1646typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1647__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp)
1648{
1649 __cp->__hash_ = hash_function()(__cp->__value_);
1650 size_type __bc = bucket_count();
1651 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1652 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001653 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001654 size_type(ceil(float(size() + 1) / max_load_factor()))));
1655 __bc = bucket_count();
1656 }
Howard Hinnant7a445152012-07-06 17:31:14 +00001657 size_t __chash = __constrain_hash(__cp->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001658 __node_pointer __pn = __bucket_list_[__chash];
1659 if (__pn == nullptr)
1660 {
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001661 __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001662 __cp->__next_ = __pn->__next_;
1663 __pn->__next_ = __cp;
1664 // fix up __bucket_list_
1665 __bucket_list_[__chash] = __pn;
1666 if (__cp->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:14 +00001667 __bucket_list_[__constrain_hash(__cp->__next_->__hash_, __bc)] = __cp;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001668 }
1669 else
1670 {
1671 for (bool __found = false; __pn->__next_ != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001672 __constrain_hash(__pn->__next_->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001673 __pn = __pn->__next_)
Howard Hinnant324bb032010-08-22 00:02:43 +00001674 {
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001675 // __found key_eq() action
1676 // false false loop
1677 // true true loop
1678 // false true set __found to true
1679 // true false break
1680 if (__found != (__pn->__next_->__hash_ == __cp->__hash_ &&
1681 key_eq()(__pn->__next_->__value_, __cp->__value_)))
1682 {
1683 if (!__found)
1684 __found = true;
1685 else
1686 break;
1687 }
1688 }
1689 __cp->__next_ = __pn->__next_;
1690 __pn->__next_ = __cp;
1691 if (__cp->__next_ != nullptr)
1692 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001693 size_t __nhash = __constrain_hash(__cp->__next_->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001694 if (__nhash != __chash)
1695 __bucket_list_[__nhash] = __cp;
1696 }
1697 }
1698 ++size();
Howard Hinnant39213642013-07-23 22:01:58 +00001699#if _LIBCPP_DEBUG_LEVEL >= 2
1700 return iterator(__cp, this);
1701#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001702 return iterator(__cp);
Howard Hinnant39213642013-07-23 22:01:58 +00001703#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001704}
1705
1706template <class _Tp, class _Hash, class _Equal, class _Alloc>
1707typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1708__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(
1709 const_iterator __p, __node_pointer __cp)
1710{
1711 if (__p != end() && key_eq()(*__p, __cp->__value_))
1712 {
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001713 __node_pointer __np = __p.__node_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001714 __cp->__hash_ = __np->__hash_;
1715 size_type __bc = bucket_count();
1716 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1717 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001718 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001719 size_type(ceil(float(size() + 1) / max_load_factor()))));
1720 __bc = bucket_count();
1721 }
Howard Hinnant7a445152012-07-06 17:31:14 +00001722 size_t __chash = __constrain_hash(__cp->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001723 __node_pointer __pp = __bucket_list_[__chash];
1724 while (__pp->__next_ != __np)
1725 __pp = __pp->__next_;
1726 __cp->__next_ = __np;
1727 __pp->__next_ = __cp;
1728 ++size();
Howard Hinnant39213642013-07-23 22:01:58 +00001729#if _LIBCPP_DEBUG_LEVEL >= 2
1730 return iterator(__cp, this);
1731#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001732 return iterator(__cp);
Howard Hinnant39213642013-07-23 22:01:58 +00001733#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001734 }
1735 return __node_insert_multi(__cp);
1736}
1737
1738template <class _Tp, class _Hash, class _Equal, class _Alloc>
1739pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1740__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(const value_type& __x)
1741{
1742 size_t __hash = hash_function()(__x);
1743 size_type __bc = bucket_count();
1744 bool __inserted = false;
1745 __node_pointer __nd;
1746 size_t __chash;
1747 if (__bc != 0)
1748 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001749 __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001750 __nd = __bucket_list_[__chash];
1751 if (__nd != nullptr)
1752 {
1753 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001754 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001755 __nd = __nd->__next_)
1756 {
1757 if (key_eq()(__nd->__value_, __x))
1758 goto __done;
1759 }
1760 }
1761 }
1762 {
1763 __node_holder __h = __construct_node(__x, __hash);
1764 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1765 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001766 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001767 size_type(ceil(float(size() + 1) / max_load_factor()))));
1768 __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:14 +00001769 __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001770 }
1771 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1772 __node_pointer __pn = __bucket_list_[__chash];
1773 if (__pn == nullptr)
1774 {
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001775 __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001776 __h->__next_ = __pn->__next_;
1777 __pn->__next_ = __h.get();
1778 // fix up __bucket_list_
1779 __bucket_list_[__chash] = __pn;
1780 if (__h->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:14 +00001781 __bucket_list_[__constrain_hash(__h->__next_->__hash_, __bc)] = __h.get();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001782 }
1783 else
1784 {
1785 __h->__next_ = __pn->__next_;
1786 __pn->__next_ = __h.get();
1787 }
1788 __nd = __h.release();
1789 // increment size
1790 ++size();
1791 __inserted = true;
1792 }
1793__done:
Howard Hinnant39213642013-07-23 22:01:58 +00001794#if _LIBCPP_DEBUG_LEVEL >= 2
1795 return pair<iterator, bool>(iterator(__nd, this), __inserted);
1796#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001797 return pair<iterator, bool>(iterator(__nd), __inserted);
Howard Hinnant39213642013-07-23 22:01:58 +00001798#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001799}
1800
Howard Hinnant73d21a42010-09-04 23:28:19 +00001801#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1802#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001803
1804template <class _Tp, class _Hash, class _Equal, class _Alloc>
1805template <class... _Args>
1806pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1807__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique(_Args&&... __args)
1808{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001809 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001810 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1811 if (__r.second)
1812 __h.release();
1813 return __r;
1814}
1815
1816template <class _Tp, class _Hash, class _Equal, class _Alloc>
1817template <class... _Args>
1818typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1819__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args)
1820{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001821 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001822 iterator __r = __node_insert_multi(__h.get());
1823 __h.release();
1824 return __r;
1825}
1826
1827template <class _Tp, class _Hash, class _Equal, class _Alloc>
1828template <class... _Args>
1829typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1830__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi(
1831 const_iterator __p, _Args&&... __args)
1832{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001833 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001834 iterator __r = __node_insert_multi(__p, __h.get());
1835 __h.release();
1836 return __r;
1837}
1838
Howard Hinnant73d21a42010-09-04 23:28:19 +00001839#endif // _LIBCPP_HAS_NO_VARIADICS
1840
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001841template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:50 +00001842template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001843pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
Howard Hinnant99968442011-11-29 18:15:50 +00001844__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(_Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001845{
Howard Hinnant99968442011-11-29 18:15:50 +00001846 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001847 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1848 if (__r.second)
1849 __h.release();
1850 return __r;
1851}
1852
Howard Hinnant73d21a42010-09-04 23:28:19 +00001853#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001854
Howard Hinnant73d21a42010-09-04 23:28:19 +00001855#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001856
1857template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:50 +00001858template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001859typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant99968442011-11-29 18:15:50 +00001860__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(_Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001861{
Howard Hinnant99968442011-11-29 18:15:50 +00001862 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001863 iterator __r = __node_insert_multi(__h.get());
1864 __h.release();
1865 return __r;
1866}
1867
1868template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:50 +00001869template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001870typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1871__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
Howard Hinnant99968442011-11-29 18:15:50 +00001872 _Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001873{
Howard Hinnant99968442011-11-29 18:15:50 +00001874 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001875 iterator __r = __node_insert_multi(__p, __h.get());
1876 __h.release();
1877 return __r;
1878}
1879
Howard Hinnant73d21a42010-09-04 23:28:19 +00001880#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001881
1882template <class _Tp, class _Hash, class _Equal, class _Alloc>
1883typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1884__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const value_type& __x)
1885{
1886 __node_holder __h = __construct_node(__x);
1887 iterator __r = __node_insert_multi(__h.get());
1888 __h.release();
1889 return __r;
1890}
1891
1892template <class _Tp, class _Hash, class _Equal, class _Alloc>
1893typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1894__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
1895 const value_type& __x)
1896{
1897 __node_holder __h = __construct_node(__x);
1898 iterator __r = __node_insert_multi(__p, __h.get());
1899 __h.release();
1900 return __r;
1901}
1902
Howard Hinnant73d21a42010-09-04 23:28:19 +00001903#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001904
1905template <class _Tp, class _Hash, class _Equal, class _Alloc>
1906void
1907__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n)
1908{
Howard Hinnant7a445152012-07-06 17:31:14 +00001909 if (__n == 1)
1910 __n = 2;
1911 else if (__n & (__n - 1))
1912 __n = __next_prime(__n);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001913 size_type __bc = bucket_count();
1914 if (__n > __bc)
1915 __rehash(__n);
Howard Hinnant7a445152012-07-06 17:31:14 +00001916 else if (__n < __bc)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001917 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001918 __n = _VSTD::max<size_type>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001919 (
1920 __n,
Howard Hinnant7a445152012-07-06 17:31:14 +00001921 __is_power2(__bc) ? __next_pow2(size_t(ceil(float(size()) / max_load_factor()))) :
1922 __next_prime(size_t(ceil(float(size()) / max_load_factor())))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001923 );
1924 if (__n < __bc)
1925 __rehash(__n);
1926 }
1927}
1928
1929template <class _Tp, class _Hash, class _Equal, class _Alloc>
1930void
1931__hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc)
1932{
Howard Hinnant39213642013-07-23 22:01:58 +00001933#if _LIBCPP_DEBUG_LEVEL >= 2
1934 __get_db()->__invalidate_all(this);
1935#endif // _LIBCPP_DEBUG_LEVEL >= 2
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001936 __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc();
1937 __bucket_list_.reset(__nbc > 0 ?
1938 __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr);
1939 __bucket_list_.get_deleter().size() = __nbc;
1940 if (__nbc > 0)
1941 {
1942 for (size_type __i = 0; __i < __nbc; ++__i)
1943 __bucket_list_[__i] = nullptr;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001944 __node_pointer __pp(static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001945 __node_pointer __cp = __pp->__next_;
1946 if (__cp != nullptr)
1947 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001948 size_type __chash = __constrain_hash(__cp->__hash_, __nbc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001949 __bucket_list_[__chash] = __pp;
1950 size_type __phash = __chash;
1951 for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr;
1952 __cp = __pp->__next_)
1953 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001954 __chash = __constrain_hash(__cp->__hash_, __nbc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001955 if (__chash == __phash)
1956 __pp = __cp;
1957 else
1958 {
1959 if (__bucket_list_[__chash] == nullptr)
1960 {
1961 __bucket_list_[__chash] = __pp;
1962 __pp = __cp;
1963 __phash = __chash;
1964 }
1965 else
1966 {
1967 __node_pointer __np = __cp;
1968 for (; __np->__next_ != nullptr &&
1969 key_eq()(__cp->__value_, __np->__next_->__value_);
1970 __np = __np->__next_)
1971 ;
1972 __pp->__next_ = __np->__next_;
1973 __np->__next_ = __bucket_list_[__chash]->__next_;
1974 __bucket_list_[__chash]->__next_ = __cp;
Howard Hinnant324bb032010-08-22 00:02:43 +00001975
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001976 }
1977 }
1978 }
1979 }
1980 }
1981}
1982
1983template <class _Tp, class _Hash, class _Equal, class _Alloc>
1984template <class _Key>
1985typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1986__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k)
1987{
1988 size_t __hash = hash_function()(__k);
1989 size_type __bc = bucket_count();
1990 if (__bc != 0)
1991 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001992 size_t __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001993 __node_pointer __nd = __bucket_list_[__chash];
1994 if (__nd != nullptr)
1995 {
1996 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001997 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001998 __nd = __nd->__next_)
1999 {
2000 if (key_eq()(__nd->__value_, __k))
Howard Hinnant39213642013-07-23 22:01:58 +00002001#if _LIBCPP_DEBUG_LEVEL >= 2
2002 return iterator(__nd, this);
2003#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002004 return iterator(__nd);
Howard Hinnant39213642013-07-23 22:01:58 +00002005#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002006 }
2007 }
2008 }
2009 return end();
2010}
2011
2012template <class _Tp, class _Hash, class _Equal, class _Alloc>
2013template <class _Key>
2014typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
2015__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const
2016{
2017 size_t __hash = hash_function()(__k);
2018 size_type __bc = bucket_count();
2019 if (__bc != 0)
2020 {
Howard Hinnant7a445152012-07-06 17:31:14 +00002021 size_t __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002022 __node_const_pointer __nd = __bucket_list_[__chash];
2023 if (__nd != nullptr)
2024 {
2025 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00002026 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002027 __nd = __nd->__next_)
2028 {
2029 if (key_eq()(__nd->__value_, __k))
Howard Hinnant39213642013-07-23 22:01:58 +00002030#if _LIBCPP_DEBUG_LEVEL >= 2
2031 return const_iterator(__nd, this);
2032#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002033 return const_iterator(__nd);
Howard Hinnant39213642013-07-23 22:01:58 +00002034#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002035 }
2036 }
Howard Hinnant324bb032010-08-22 00:02:43 +00002037
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002038 }
2039 return end();
2040}
2041
Howard Hinnant73d21a42010-09-04 23:28:19 +00002042#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
2043#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002044
2045template <class _Tp, class _Hash, class _Equal, class _Alloc>
2046template <class ..._Args>
2047typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
2048__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args)
2049{
2050 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00002051 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00002052 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002053 __h.get_deleter().__value_constructed = true;
2054 __h->__hash_ = hash_function()(__h->__value_);
2055 __h->__next_ = nullptr;
2056 return __h;
2057}
2058
Howard Hinnant73d21a42010-09-04 23:28:19 +00002059#endif // _LIBCPP_HAS_NO_VARIADICS
2060
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002061template <class _Tp, class _Hash, class _Equal, class _Alloc>
2062typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
2063__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(value_type&& __v,
2064 size_t __hash)
2065{
2066 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00002067 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00002068 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::move(__v));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002069 __h.get_deleter().__value_constructed = true;
2070 __h->__hash_ = __hash;
2071 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00002072 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002073}
2074
Howard Hinnant73d21a42010-09-04 23:28:19 +00002075#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002076
2077template <class _Tp, class _Hash, class _Equal, class _Alloc>
2078typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
2079__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v)
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_), __v);
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;
Howard Hinnant0949eed2011-06-30 21:18:19 +00002087 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002088}
2089
Howard Hinnant73d21a42010-09-04 23:28:19 +00002090#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002091
2092template <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(const 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_), __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
2106template <class _Tp, class _Hash, class _Equal, class _Alloc>
2107typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2108__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p)
2109{
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002110 __node_pointer __np = __p.__node_;
Howard Hinnant39213642013-07-23 22:01:58 +00002111#if _LIBCPP_DEBUG_LEVEL >= 2
2112 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
2113 "unordered container erase(iterator) called with an iterator not"
2114 " referring to this container");
2115 _LIBCPP_ASSERT(__p != end(),
2116 "unordered container erase(iterator) called with a non-dereferenceable iterator");
2117 iterator __r(__np, this);
2118#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002119 iterator __r(__np);
Howard Hinnant39213642013-07-23 22:01:58 +00002120#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002121 ++__r;
2122 remove(__p);
2123 return __r;
2124}
2125
2126template <class _Tp, class _Hash, class _Equal, class _Alloc>
2127typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2128__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first,
2129 const_iterator __last)
2130{
Howard Hinnant39213642013-07-23 22:01:58 +00002131#if _LIBCPP_DEBUG_LEVEL >= 2
2132 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this,
2133 "unodered container::erase(iterator, iterator) called with an iterator not"
2134 " referring to this unodered container");
2135 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__last) == this,
2136 "unodered container::erase(iterator, iterator) called with an iterator not"
2137 " referring to this unodered container");
2138#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002139 for (const_iterator __p = __first; __first != __last; __p = __first)
2140 {
2141 ++__first;
2142 erase(__p);
2143 }
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002144 __node_pointer __np = __last.__node_;
Howard Hinnant39213642013-07-23 22:01:58 +00002145#if _LIBCPP_DEBUG_LEVEL >= 2
2146 return iterator (__np, this);
2147#else
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002148 return iterator (__np);
Howard Hinnant39213642013-07-23 22:01:58 +00002149#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002150}
2151
2152template <class _Tp, class _Hash, class _Equal, class _Alloc>
2153template <class _Key>
2154typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2155__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k)
2156{
2157 iterator __i = find(__k);
2158 if (__i == end())
2159 return 0;
2160 erase(__i);
2161 return 1;
2162}
2163
2164template <class _Tp, class _Hash, class _Equal, class _Alloc>
2165template <class _Key>
2166typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2167__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k)
2168{
2169 size_type __r = 0;
2170 iterator __i = find(__k);
2171 if (__i != end())
2172 {
2173 iterator __e = end();
2174 do
2175 {
2176 erase(__i++);
2177 ++__r;
2178 } while (__i != __e && key_eq()(*__i, __k));
2179 }
2180 return __r;
2181}
2182
2183template <class _Tp, class _Hash, class _Equal, class _Alloc>
2184typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00002185__hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002186{
2187 // current node
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002188 __node_pointer __cn = __p.__node_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002189 size_type __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:14 +00002190 size_t __chash = __constrain_hash(__cn->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002191 // find previous node
2192 __node_pointer __pn = __bucket_list_[__chash];
2193 for (; __pn->__next_ != __cn; __pn = __pn->__next_)
2194 ;
2195 // Fix up __bucket_list_
2196 // if __pn is not in same bucket (before begin is not in same bucket) &&
2197 // if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002198 if (__pn == static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()))
2199 || __constrain_hash(__pn->__hash_, __bc) != __chash)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002200 {
Howard Hinnant7a445152012-07-06 17:31:14 +00002201 if (__cn->__next_ == nullptr || __constrain_hash(__cn->__next_->__hash_, __bc) != __chash)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002202 __bucket_list_[__chash] = nullptr;
2203 }
2204 // if __cn->__next_ is not in same bucket (nullptr is in same bucket)
2205 if (__cn->__next_ != nullptr)
2206 {
Howard Hinnant7a445152012-07-06 17:31:14 +00002207 size_t __nhash = __constrain_hash(__cn->__next_->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002208 if (__nhash != __chash)
2209 __bucket_list_[__nhash] = __pn;
2210 }
2211 // remove __cn
2212 __pn->__next_ = __cn->__next_;
2213 __cn->__next_ = nullptr;
2214 --size();
Howard Hinnant39213642013-07-23 22:01:58 +00002215#if _LIBCPP_DEBUG_LEVEL >= 2
2216 __c_node* __c = __get_db()->__find_c_and_lock(this);
2217 for (__i_node** __p = __c->end_; __p != __c->beg_; )
2218 {
2219 --__p;
2220 iterator* __i = static_cast<iterator*>((*__p)->__i_);
2221 if (__i->__node_ == __cn)
2222 {
2223 (*__p)->__c_ = nullptr;
2224 if (--__c->end_ != __p)
2225 memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*));
2226 }
2227 }
2228 __get_db()->unlock();
2229#endif
Howard Hinnant99968442011-11-29 18:15:50 +00002230 return __node_holder(__cn, _Dp(__node_alloc(), true));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002231}
2232
2233template <class _Tp, class _Hash, class _Equal, class _Alloc>
2234template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39 +00002235inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002236typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2237__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const
2238{
2239 return static_cast<size_type>(find(__k) != end());
2240}
2241
2242template <class _Tp, class _Hash, class _Equal, class _Alloc>
2243template <class _Key>
2244typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2245__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const
2246{
2247 size_type __r = 0;
2248 const_iterator __i = find(__k);
2249 if (__i != end())
2250 {
2251 const_iterator __e = end();
2252 do
2253 {
2254 ++__i;
2255 ++__r;
2256 } while (__i != __e && key_eq()(*__i, __k));
2257 }
2258 return __r;
2259}
2260
2261template <class _Tp, class _Hash, class _Equal, class _Alloc>
2262template <class _Key>
2263pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
2264 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
2265__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
2266 const _Key& __k)
2267{
2268 iterator __i = find(__k);
2269 iterator __j = __i;
2270 if (__i != end())
2271 ++__j;
2272 return pair<iterator, iterator>(__i, __j);
2273}
2274
2275template <class _Tp, class _Hash, class _Equal, class _Alloc>
2276template <class _Key>
2277pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
2278 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
2279__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
2280 const _Key& __k) const
2281{
2282 const_iterator __i = find(__k);
2283 const_iterator __j = __i;
2284 if (__i != end())
2285 ++__j;
2286 return pair<const_iterator, const_iterator>(__i, __j);
2287}
2288
2289template <class _Tp, class _Hash, class _Equal, class _Alloc>
2290template <class _Key>
2291pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
2292 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
2293__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
2294 const _Key& __k)
2295{
2296 iterator __i = find(__k);
2297 iterator __j = __i;
2298 if (__i != end())
2299 {
2300 iterator __e = end();
2301 do
2302 {
2303 ++__j;
2304 } while (__j != __e && key_eq()(*__j, __k));
2305 }
2306 return pair<iterator, iterator>(__i, __j);
2307}
2308
2309template <class _Tp, class _Hash, class _Equal, class _Alloc>
2310template <class _Key>
2311pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
2312 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
2313__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
2314 const _Key& __k) const
2315{
2316 const_iterator __i = find(__k);
2317 const_iterator __j = __i;
2318 if (__i != end())
2319 {
2320 const_iterator __e = end();
2321 do
2322 {
2323 ++__j;
2324 } while (__j != __e && key_eq()(*__j, __k));
2325 }
2326 return pair<const_iterator, const_iterator>(__i, __j);
2327}
2328
2329template <class _Tp, class _Hash, class _Equal, class _Alloc>
2330void
2331__hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00002332 _NOEXCEPT_(
2333 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
2334 __is_nothrow_swappable<__pointer_allocator>::value) &&
2335 (!__node_traits::propagate_on_container_swap::value ||
2336 __is_nothrow_swappable<__node_allocator>::value) &&
2337 __is_nothrow_swappable<hasher>::value &&
2338 __is_nothrow_swappable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002339{
2340 {
2341 __node_pointer_pointer __npp = __bucket_list_.release();
2342 __bucket_list_.reset(__u.__bucket_list_.release());
2343 __u.__bucket_list_.reset(__npp);
2344 }
Howard Hinnant0949eed2011-06-30 21:18:19 +00002345 _VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002346 __swap_alloc(__bucket_list_.get_deleter().__alloc(),
2347 __u.__bucket_list_.get_deleter().__alloc());
2348 __swap_alloc(__node_alloc(), __u.__node_alloc());
Howard Hinnant0949eed2011-06-30 21:18:19 +00002349 _VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002350 __p2_.swap(__u.__p2_);
2351 __p3_.swap(__u.__p3_);
2352 if (size() > 0)
Howard Hinnant7a445152012-07-06 17:31:14 +00002353 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002354 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002355 if (__u.size() > 0)
Howard Hinnant7a445152012-07-06 17:31:14 +00002356 __u.__bucket_list_[__constrain_hash(__u.__p1_.first().__next_->__hash_, __u.bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00002357 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__u.__p1_.first()));
Howard Hinnant39213642013-07-23 22:01:58 +00002358#if _LIBCPP_DEBUG_LEVEL >= 2
2359 __get_db()->swap(this, &__u);
2360#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002361}
2362
2363template <class _Tp, class _Hash, class _Equal, class _Alloc>
2364typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2365__hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const
2366{
2367 __node_const_pointer __np = __bucket_list_[__n];
2368 size_type __bc = bucket_count();
2369 size_type __r = 0;
2370 if (__np != nullptr)
2371 {
2372 for (__np = __np->__next_; __np != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00002373 __constrain_hash(__np->__hash_, __bc) == __n;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002374 __np = __np->__next_, ++__r)
2375 ;
2376 }
2377 return __r;
2378}
2379
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00002380template <class _Tp, class _Hash, class _Equal, class _Alloc>
2381inline _LIBCPP_INLINE_VISIBILITY
2382void
2383swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x,
2384 __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y)
2385 _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
2386{
2387 __x.swap(__y);
2388}
2389
Howard Hinnant39213642013-07-23 22:01:58 +00002390#if _LIBCPP_DEBUG_LEVEL >= 2
2391
2392template <class _Tp, class _Hash, class _Equal, class _Alloc>
2393bool
2394__hash_table<_Tp, _Hash, _Equal, _Alloc>::__dereferenceable(const const_iterator* __i) const
2395{
2396 return __i->__node_ != nullptr;
2397}
2398
2399template <class _Tp, class _Hash, class _Equal, class _Alloc>
2400bool
2401__hash_table<_Tp, _Hash, _Equal, _Alloc>::__decrementable(const const_iterator*) const
2402{
2403 return false;
2404}
2405
2406template <class _Tp, class _Hash, class _Equal, class _Alloc>
2407bool
2408__hash_table<_Tp, _Hash, _Equal, _Alloc>::__addable(const const_iterator*, ptrdiff_t) const
2409{
2410 return false;
2411}
2412
2413template <class _Tp, class _Hash, class _Equal, class _Alloc>
2414bool
2415__hash_table<_Tp, _Hash, _Equal, _Alloc>::__subscriptable(const const_iterator*, ptrdiff_t) const
2416{
2417 return false;
2418}
2419
2420#endif // _LIBCPP_DEBUG_LEVEL >= 2
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00002421_LIBCPP_END_NAMESPACE_STD
2422
2423#endif // _LIBCPP__HASH_TABLE