blob: 0f722948f5492a91420f9c9583de9676dc812b90 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:161// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:014// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:165//
Howard Hinnantb64f8b02010-11-16 22:09:026// 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:168//
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:2721#include <__undef_min_max>
22
Howard Hinnant08e17472011-10-17 20:05:1023#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:1624#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:1025#endif
Howard Hinnantbc8d3f92010-05-11 19:42:1626
27_LIBCPP_BEGIN_NAMESPACE_STD
28
Howard Hinnant83eade62013-03-06 23:30:1929_LIBCPP_FUNC_VIS
Howard Hinnant2b1b2d42011-06-14 19:58:1730size_t __next_prime(size_t __n);
Howard Hinnantbc8d3f92010-05-11 19:42:1631
32template <class _NodePtr>
33struct __hash_node_base
34{
35 typedef __hash_node_base __first_node;
Howard Hinnantbc8d3f92010-05-11 19:42:1636
Howard Hinnantdf85e572011-02-27 18:02:0237 _NodePtr __next_;
Howard Hinnantbc8d3f92010-05-11 19:42:1638
Howard Hinnant5f2f14c2011-06-04 18:54:2439 _LIBCPP_INLINE_VISIBILITY __hash_node_base() _NOEXCEPT : __next_(nullptr) {}
Howard Hinnantbc8d3f92010-05-11 19:42:1640};
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:1460inline _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:1781template <class _Tp, class _Hash, class _Equal, class _Alloc> class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:1982template <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:1785template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
Howard Hinnant83eade62013-03-06 23:30:1986 class _LIBCPP_TYPE_VIS unordered_map;
Howard Hinnantbc8d3f92010-05-11 19:42:1687
88template <class _NodePtr>
Howard Hinnant83eade62013-03-06 23:30:1989class _LIBCPP_TYPE_VIS __hash_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:1690{
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:58108 _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:16116
Howard Hinnant99acc502010-09-21 17:32:39117 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58118 __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:39124 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58125 ~__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:16161
Howard Hinnant99acc502010-09-21 17:32:39162 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16163 __hash_iterator& operator++()
164 {
Howard Hinnant39213642013-07-23 22:01:58165#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:16169 __node_ = __node_->__next_;
170 return *this;
171 }
172
Howard Hinnant99acc502010-09-21 17:32:39173 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16174 __hash_iterator operator++(int)
175 {
176 __hash_iterator __t(*this);
177 ++(*this);
178 return __t;
179 }
180
Howard Hinnant99acc502010-09-21 17:32:39181 friend _LIBCPP_INLINE_VISIBILITY
182 bool operator==(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58183 {
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:39190 friend _LIBCPP_INLINE_VISIBILITY
191 bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58192 {return !(__x == __y);}
Howard Hinnantbc8d3f92010-05-11 19:42:16193
194private:
Howard Hinnant39213642013-07-23 22:01:58195#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:39203 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24204 __hash_iterator(__node_pointer __node) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16205 : __node_(__node)
206 {}
Howard Hinnant39213642013-07-23 22:01:58207#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16208
209 template <class, class, class, class> friend class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19210 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:16214};
215
216template <class _ConstNodePtr>
Howard Hinnant83eade62013-03-06 23:30:19217class _LIBCPP_TYPE_VIS __hash_const_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16218{
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:58248 _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:39254 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24255 __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16256 : __node_(__x.__node_)
Howard Hinnant39213642013-07-23 22:01:58257 {
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:16264
Howard Hinnant99acc502010-09-21 17:32:39265 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58266 __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:39272 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58273 ~__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:16309
Howard Hinnant99acc502010-09-21 17:32:39310 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16311 __hash_const_iterator& operator++()
312 {
Howard Hinnant39213642013-07-23 22:01:58313#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:16317 __node_ = __node_->__next_;
318 return *this;
319 }
320
Howard Hinnant99acc502010-09-21 17:32:39321 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16322 __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:39329 friend _LIBCPP_INLINE_VISIBILITY
330 bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58331 {
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:39338 friend _LIBCPP_INLINE_VISIBILITY
339 bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58340 {return !(__x == __y);}
Howard Hinnantbc8d3f92010-05-11 19:42:16341
342private:
Howard Hinnant39213642013-07-23 22:01:58343#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:39351 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24352 __hash_const_iterator(__node_pointer __node) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16353 : __node_(__node)
354 {}
Howard Hinnant39213642013-07-23 22:01:58355#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16356
357 template <class, class, class, class> friend class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19358 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:16361};
362
Howard Hinnant83eade62013-03-06 23:30:19363template <class _ConstNodePtr> class _LIBCPP_TYPE_VIS __hash_const_local_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16364
365template <class _NodePtr>
Howard Hinnant83eade62013-03-06 23:30:19366class _LIBCPP_TYPE_VIS __hash_local_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16367{
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:58388 _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:16396
Howard Hinnant99acc502010-09-21 17:32:39397 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58398 __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:39406 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58407 ~__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:16445
Howard Hinnant99acc502010-09-21 17:32:39446 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16447 __hash_local_iterator& operator++()
448 {
Howard Hinnant39213642013-07-23 22:01:58449#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:16453 __node_ = __node_->__next_;
Howard Hinnant7a445152012-07-06 17:31:14454 if (__node_ != nullptr && __constrain_hash(__node_->__hash_, __bucket_count_) != __bucket_)
Howard Hinnantbc8d3f92010-05-11 19:42:16455 __node_ = nullptr;
456 return *this;
457 }
458
Howard Hinnant99acc502010-09-21 17:32:39459 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16460 __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:39467 friend _LIBCPP_INLINE_VISIBILITY
468 bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58469 {
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:39476 friend _LIBCPP_INLINE_VISIBILITY
477 bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnant39213642013-07-23 22:01:58478 {return !(__x == __y);}
Howard Hinnantbc8d3f92010-05-11 19:42:16479
480private:
Howard Hinnant39213642013-07-23 22:01:58481#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:39494 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16495 __hash_local_iterator(__node_pointer __node, size_t __bucket,
Howard Hinnant5f2f14c2011-06-04 18:54:24496 size_t __bucket_count) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16497 : __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:58504#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16505 template <class, class, class, class> friend class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19506 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:16508};
509
510template <class _ConstNodePtr>
Howard Hinnant83eade62013-03-06 23:30:19511class _LIBCPP_TYPE_VIS __hash_const_local_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16512{
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:58546 _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:39553 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24554 __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16555 : __node_(__x.__node_),
556 __bucket_(__x.__bucket_),
557 __bucket_count_(__x.__bucket_count_)
Howard Hinnant39213642013-07-23 22:01:58558 {
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:16565
Howard Hinnant99acc502010-09-21 17:32:39566 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58567 __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:39575 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant39213642013-07-23 22:01:58576 ~__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:16614
Howard Hinnant99acc502010-09-21 17:32:39615 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16616 __hash_const_local_iterator& operator++()
617 {
Howard Hinnant39213642013-07-23 22:01:58618#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:16622 __node_ = __node_->__next_;
Howard Hinnant7a445152012-07-06 17:31:14623 if (__node_ != nullptr && __constrain_hash(__node_->__hash_, __bucket_count_) != __bucket_)
Howard Hinnantbc8d3f92010-05-11 19:42:16624 __node_ = nullptr;
625 return *this;
626 }
627
Howard Hinnant99acc502010-09-21 17:32:39628 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16629 __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:39636 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:58638 {
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:39645 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:58647 {return !(__x == __y);}
Howard Hinnantbc8d3f92010-05-11 19:42:16648
649private:
Howard Hinnant39213642013-07-23 22:01:58650#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:39663 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16664 __hash_const_local_iterator(__node_pointer __node, size_t __bucket,
Howard Hinnant5f2f14c2011-06-04 18:54:24665 size_t __bucket_count) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16666 : __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:58673#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16674 template <class, class, class, class> friend class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19675 template <class> friend class _LIBCPP_TYPE_VIS __hash_map_const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16676};
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:39689 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16690 __bucket_list_deallocator()
Howard Hinnant5f2f14c2011-06-04 18:54:24691 _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16692 : __data_(0) {}
Howard Hinnant99acc502010-09-21 17:32:39693
694 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16695 __bucket_list_deallocator(const allocator_type& __a, size_type __size)
Howard Hinnant5f2f14c2011-06-04 18:54:24696 _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16697 : __data_(__size, __a) {}
698
Howard Hinnant73d21a42010-09-04 23:28:19699#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16700
Howard Hinnant99acc502010-09-21 17:32:39701 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16702 __bucket_list_deallocator(__bucket_list_deallocator&& __x)
Howard Hinnant5f2f14c2011-06-04 18:54:24703 _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
Howard Hinnant0949eed2011-06-30 21:18:19704 : __data_(_VSTD::move(__x.__data_))
Howard Hinnantbc8d3f92010-05-11 19:42:16705 {
706 __x.size() = 0;
707 }
708
Howard Hinnant73d21a42010-09-04 23:28:19709#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16710
Howard Hinnant5f2f14c2011-06-04 18:54:24711 _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:16715
Howard Hinnant99acc502010-09-21 17:32:39716 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24717 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:16723 {
724 __alloc_traits::deallocate(__alloc(), __p, size());
725 }
726};
727
Howard Hinnant2b1b2d42011-06-14 19:58:17728template <class _Alloc> class __hash_map_node_destructor;
Howard Hinnantbc8d3f92010-05-11 19:42:16729
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:39747 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant199d0ae2011-07-31 17:04:30748 explicit __hash_node_destructor(allocator_type& __na,
749 bool __constructed = false) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16750 : __na_(__na),
Howard Hinnant199d0ae2011-07-31 17:04:30751 __value_constructed(__constructed)
Howard Hinnantbc8d3f92010-05-11 19:42:16752 {}
753
Howard Hinnant99acc502010-09-21 17:32:39754 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24755 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16756 {
757 if (__value_constructed)
Howard Hinnant0949eed2011-06-30 21:18:19758 __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16759 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:16787 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:29796 typedef typename __node_traits::pointer __node_const_pointer;
Howard Hinnantf8880d02011-12-12 17:26:24797 typedef __hash_node_base<__node_pointer> __first_node;
Howard Hinnant7a6b7ce2013-06-22 15:21:29798 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:16805
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:24827 _LIBCPP_INLINE_VISIBILITY
828 size_type& size() _NOEXCEPT {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16829public:
Howard Hinnant5f2f14c2011-06-04 18:54:24830 _LIBCPP_INLINE_VISIBILITY
831 size_type size() const _NOEXCEPT {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16832
Howard Hinnant5f2f14c2011-06-04 18:54:24833 _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:16837
Howard Hinnant5f2f14c2011-06-04 18:54:24838 _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:16842
Howard Hinnant5f2f14c2011-06-04 18:54:24843 _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:16847
Howard Hinnant5f2f14c2011-06-04 18:54:24848 _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:16853
854public:
855 typedef __hash_iterator<__node_pointer> iterator;
Howard Hinnant7a6b7ce2013-06-22 15:21:29856 typedef __hash_const_iterator<__node_pointer> const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16857 typedef __hash_local_iterator<__node_pointer> local_iterator;
Howard Hinnant7a6b7ce2013-06-22 15:21:29858 typedef __hash_const_local_iterator<__node_pointer> const_local_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16859
Howard Hinnant5f2f14c2011-06-04 18:54:24860 __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:16867 __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:19873#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5f2f14c2011-06-04 18:54:24874 __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:16881 __hash_table(__hash_table&& __u, const allocator_type& __a);
Howard Hinnant73d21a42010-09-04 23:28:19882#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16883 ~__hash_table();
884
885 __hash_table& operator=(const __hash_table& __u);
Howard Hinnant73d21a42010-09-04 23:28:19886#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5f2f14c2011-06-04 18:54:24887 __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:16893#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:39899 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24900 size_type max_size() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16901 {
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:19911#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16912 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:19918#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16919
920 pair<iterator, bool> __insert_unique(const value_type& __x);
921
Howard Hinnant73d21a42010-09-04 23:28:19922#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant99968442011-11-29 18:15:50923 template <class _Pp>
924 pair<iterator, bool> __insert_unique(_Pp&& __x);
Howard Hinnant73d21a42010-09-04 23:28:19925#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16926
Howard Hinnant73d21a42010-09-04 23:28:19927#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant99968442011-11-29 18:15:50928 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:19932#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16933 iterator __insert_multi(const value_type& __x);
934 iterator __insert_multi(const_iterator __p, const value_type& __x);
Howard Hinnant73d21a42010-09-04 23:28:19935#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16936
Howard Hinnant5f2f14c2011-06-04 18:54:24937 void clear() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16938 void rehash(size_type __n);
Howard Hinnant99acc502010-09-21 17:32:39939 _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16940 {rehash(static_cast<size_type>(ceil(__n / max_load_factor())));}
Howard Hinnant99acc502010-09-21 17:32:39941
942 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24943 size_type bucket_count() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16944 {
945 return __bucket_list_.get_deleter().size();
946 }
947
Howard Hinnant5f2f14c2011-06-04 18:54:24948 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:16952
953 template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39954 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16955 size_type bucket(const _Key& __k) const
Howard Hinnant0bb0a7c2013-07-29 19:05:47956 {
957 _LIBCPP_ASSERT(bucket_count() > 0,
958 "unordered container::bucket(key) called when bucket_count() == 0");
959 return __constrain_hash(hash_function()(__k), bucket_count());
960 }
Howard Hinnantbc8d3f92010-05-11 19:42:16961
962 template <class _Key>
963 iterator find(const _Key& __x);
964 template <class _Key>
965 const_iterator find(const _Key& __x) const;
966
Howard Hinnant99968442011-11-29 18:15:50967 typedef __hash_node_destructor<__node_allocator> _Dp;
968 typedef unique_ptr<__node, _Dp> __node_holder;
Howard Hinnantbc8d3f92010-05-11 19:42:16969
970 iterator erase(const_iterator __p);
971 iterator erase(const_iterator __first, const_iterator __last);
972 template <class _Key>
973 size_type __erase_unique(const _Key& __k);
974 template <class _Key>
975 size_type __erase_multi(const _Key& __k);
Howard Hinnant5f2f14c2011-06-04 18:54:24976 __node_holder remove(const_iterator __p) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16977
978 template <class _Key>
979 size_type __count_unique(const _Key& __k) const;
980 template <class _Key>
981 size_type __count_multi(const _Key& __k) const;
982
983 template <class _Key>
984 pair<iterator, iterator>
985 __equal_range_unique(const _Key& __k);
986 template <class _Key>
987 pair<const_iterator, const_iterator>
988 __equal_range_unique(const _Key& __k) const;
989
990 template <class _Key>
991 pair<iterator, iterator>
992 __equal_range_multi(const _Key& __k);
993 template <class _Key>
994 pair<const_iterator, const_iterator>
995 __equal_range_multi(const _Key& __k) const;
996
Howard Hinnant5f2f14c2011-06-04 18:54:24997 void swap(__hash_table& __u)
998 _NOEXCEPT_(
999 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
1000 __is_nothrow_swappable<__pointer_allocator>::value) &&
1001 (!__node_traits::propagate_on_container_swap::value ||
1002 __is_nothrow_swappable<__node_allocator>::value) &&
1003 __is_nothrow_swappable<hasher>::value &&
1004 __is_nothrow_swappable<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:161005
Howard Hinnant99acc502010-09-21 17:32:391006 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:241007 size_type max_bucket_count() const _NOEXCEPT
Howard Hinnant7a6b7ce2013-06-22 15:21:291008 {return __pointer_alloc_traits::max_size(__bucket_list_.get_deleter().__alloc());}
Howard Hinnantbc8d3f92010-05-11 19:42:161009 size_type bucket_size(size_type __n) const;
Howard Hinnant5f2f14c2011-06-04 18:54:241010 _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:161011 {
1012 size_type __bc = bucket_count();
1013 return __bc != 0 ? (float)size() / __bc : 0.f;
1014 }
Howard Hinnant5f2f14c2011-06-04 18:54:241015 _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT
Howard Hinnant0bb0a7c2013-07-29 19:05:471016 {
1017 _LIBCPP_ASSERT(__mlf > 0,
1018 "unordered container::max_load_factor(lf) called with lf <= 0");
1019 max_load_factor() = _VSTD::max(__mlf, load_factor());
1020 }
Howard Hinnantbc8d3f92010-05-11 19:42:161021
Howard Hinnant39213642013-07-23 22:01:581022 _LIBCPP_INLINE_VISIBILITY
1023 local_iterator
1024 begin(size_type __n)
1025 {
Howard Hinnant0bb0a7c2013-07-29 19:05:471026 _LIBCPP_ASSERT(__n < bucket_count(),
1027 "unordered container::begin(n) called with n >= bucket_count()");
Howard Hinnant39213642013-07-23 22:01:581028#if _LIBCPP_DEBUG_LEVEL >= 2
1029 return local_iterator(__bucket_list_[__n], __n, bucket_count(), this);
1030#else
1031 return local_iterator(__bucket_list_[__n], __n, bucket_count());
1032#endif
1033 }
1034
1035 _LIBCPP_INLINE_VISIBILITY
1036 local_iterator
1037 end(size_type __n)
1038 {
Howard Hinnant0bb0a7c2013-07-29 19:05:471039 _LIBCPP_ASSERT(__n < bucket_count(),
1040 "unordered container::end(n) called with n >= bucket_count()");
Howard Hinnant39213642013-07-23 22:01:581041#if _LIBCPP_DEBUG_LEVEL >= 2
1042 return local_iterator(nullptr, __n, bucket_count(), this);
1043#else
1044 return local_iterator(nullptr, __n, bucket_count());
1045#endif
1046 }
1047
1048 _LIBCPP_INLINE_VISIBILITY
1049 const_local_iterator
1050 cbegin(size_type __n) const
1051 {
Howard Hinnant0bb0a7c2013-07-29 19:05:471052 _LIBCPP_ASSERT(__n < bucket_count(),
1053 "unordered container::cbegin(n) called with n >= bucket_count()");
Howard Hinnant39213642013-07-23 22:01:581054#if _LIBCPP_DEBUG_LEVEL >= 2
1055 return const_local_iterator(__bucket_list_[__n], __n, bucket_count(), this);
1056#else
1057 return const_local_iterator(__bucket_list_[__n], __n, bucket_count());
1058#endif
1059 }
1060
1061 _LIBCPP_INLINE_VISIBILITY
1062 const_local_iterator
1063 cend(size_type __n) const
1064 {
Howard Hinnant0bb0a7c2013-07-29 19:05:471065 _LIBCPP_ASSERT(__n < bucket_count(),
1066 "unordered container::cend(n) called with n >= bucket_count()");
Howard Hinnant39213642013-07-23 22:01:581067#if _LIBCPP_DEBUG_LEVEL >= 2
1068 return const_local_iterator(nullptr, __n, bucket_count(), this);
1069#else
1070 return const_local_iterator(nullptr, __n, bucket_count());
1071#endif
1072 }
1073
1074#if _LIBCPP_DEBUG_LEVEL >= 2
1075
1076 bool __dereferenceable(const const_iterator* __i) const;
1077 bool __decrementable(const const_iterator* __i) const;
1078 bool __addable(const const_iterator* __i, ptrdiff_t __n) const;
1079 bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const;
1080
1081#endif // _LIBCPP_DEBUG_LEVEL >= 2
1082
Howard Hinnantbc8d3f92010-05-11 19:42:161083private:
1084 void __rehash(size_type __n);
1085
Howard Hinnant73d21a42010-09-04 23:28:191086#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1087#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:161088 template <class ..._Args>
1089 __node_holder __construct_node(_Args&& ...__args);
Howard Hinnantbfd55302010-09-04 23:46:481090#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:161091 __node_holder __construct_node(value_type&& __v, size_t __hash);
Howard Hinnant73d21a42010-09-04 23:28:191092#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:161093 __node_holder __construct_node(const value_type& __v);
1094#endif
1095 __node_holder __construct_node(const value_type& __v, size_t __hash);
1096
Howard Hinnant99acc502010-09-21 17:32:391097 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:161098 void __copy_assign_alloc(const __hash_table& __u)
1099 {__copy_assign_alloc(__u, integral_constant<bool,
1100 __node_traits::propagate_on_container_copy_assignment::value>());}
1101 void __copy_assign_alloc(const __hash_table& __u, true_type);
Howard Hinnant99acc502010-09-21 17:32:391102 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantec3773c2011-12-01 20:21:041103 void __copy_assign_alloc(const __hash_table&, false_type) {}
Howard Hinnantbc8d3f92010-05-11 19:42:161104
1105 void __move_assign(__hash_table& __u, false_type);
Howard Hinnant5f2f14c2011-06-04 18:54:241106 void __move_assign(__hash_table& __u, true_type)
1107 _NOEXCEPT_(
1108 is_nothrow_move_assignable<__node_allocator>::value &&
1109 is_nothrow_move_assignable<hasher>::value &&
1110 is_nothrow_move_assignable<key_equal>::value);
1111 _LIBCPP_INLINE_VISIBILITY
1112 void __move_assign_alloc(__hash_table& __u)
1113 _NOEXCEPT_(
1114 !__node_traits::propagate_on_container_move_assignment::value ||
1115 (is_nothrow_move_assignable<__pointer_allocator>::value &&
1116 is_nothrow_move_assignable<__node_allocator>::value))
Howard Hinnantbc8d3f92010-05-11 19:42:161117 {__move_assign_alloc(__u, integral_constant<bool,
1118 __node_traits::propagate_on_container_move_assignment::value>());}
Howard Hinnant99acc502010-09-21 17:32:391119 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:161120 void __move_assign_alloc(__hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:241121 _NOEXCEPT_(
1122 is_nothrow_move_assignable<__pointer_allocator>::value &&
1123 is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:161124 {
1125 __bucket_list_.get_deleter().__alloc() =
Howard Hinnant0949eed2011-06-30 21:18:191126 _VSTD::move(__u.__bucket_list_.get_deleter().__alloc());
1127 __node_alloc() = _VSTD::move(__u.__node_alloc());
Howard Hinnantbc8d3f92010-05-11 19:42:161128 }
Howard Hinnant99acc502010-09-21 17:32:391129 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:241130 void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:161131
Howard Hinnant99968442011-11-29 18:15:501132 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:391133 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:161134 static
1135 void
Howard Hinnant99968442011-11-29 18:15:501136 __swap_alloc(_Ap& __x, _Ap& __y)
Howard Hinnant5f2f14c2011-06-04 18:54:241137 _NOEXCEPT_(
Howard Hinnant99968442011-11-29 18:15:501138 !allocator_traits<_Ap>::propagate_on_container_swap::value ||
1139 __is_nothrow_swappable<_Ap>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:161140 {
1141 __swap_alloc(__x, __y,
1142 integral_constant<bool,
Howard Hinnant99968442011-11-29 18:15:501143 allocator_traits<_Ap>::propagate_on_container_swap::value
Howard Hinnantbc8d3f92010-05-11 19:42:161144 >());
1145 }
1146
Howard Hinnant99968442011-11-29 18:15:501147 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:391148 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:161149 static
1150 void
Howard Hinnant99968442011-11-29 18:15:501151 __swap_alloc(_Ap& __x, _Ap& __y, true_type)
1152 _NOEXCEPT_(__is_nothrow_swappable<_Ap>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:161153 {
Howard Hinnant0949eed2011-06-30 21:18:191154 using _VSTD::swap;
Howard Hinnantbc8d3f92010-05-11 19:42:161155 swap(__x, __y);
1156 }
1157
Howard Hinnant99968442011-11-29 18:15:501158 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:391159 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:161160 static
1161 void
Howard Hinnantec3773c2011-12-01 20:21:041162 __swap_alloc(_Ap&, _Ap&, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:161163
Howard Hinnant5f2f14c2011-06-04 18:54:241164 void __deallocate(__node_pointer __np) _NOEXCEPT;
1165 __node_pointer __detach() _NOEXCEPT;
Howard Hinnant7a6b7ce2013-06-22 15:21:291166
1167 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_map;
1168 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:161169};
1170
1171template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:391172inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:161173__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table()
Howard Hinnant5f2f14c2011-06-04 18:54:241174 _NOEXCEPT_(
1175 is_nothrow_default_constructible<__bucket_list>::value &&
1176 is_nothrow_default_constructible<__first_node>::value &&
1177 is_nothrow_default_constructible<hasher>::value &&
1178 is_nothrow_default_constructible<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:161179 : __p2_(0),
1180 __p3_(1.0f)
1181{
1182}
1183
1184template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:391185inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:161186__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
1187 const key_equal& __eql)
1188 : __bucket_list_(nullptr, __bucket_list_deleter()),
1189 __p1_(),
1190 __p2_(0, __hf),
1191 __p3_(1.0f, __eql)
1192{
1193}
1194
1195template <class _Tp, class _Hash, class _Equal, class _Alloc>
1196__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
1197 const key_equal& __eql,
1198 const allocator_type& __a)
1199 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1200 __p1_(__node_allocator(__a)),
1201 __p2_(0, __hf),
1202 __p3_(1.0f, __eql)
1203{
1204}
1205
1206template <class _Tp, class _Hash, class _Equal, class _Alloc>
1207__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
1208 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1209 __p1_(__node_allocator(__a)),
1210 __p2_(0),
1211 __p3_(1.0f)
1212{
1213}
1214
1215template <class _Tp, class _Hash, class _Equal, class _Alloc>
1216__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
1217 : __bucket_list_(nullptr,
1218 __bucket_list_deleter(allocator_traits<__pointer_allocator>::
1219 select_on_container_copy_construction(
1220 __u.__bucket_list_.get_deleter().__alloc()), 0)),
1221 __p1_(allocator_traits<__node_allocator>::
1222 select_on_container_copy_construction(__u.__node_alloc())),
1223 __p2_(0, __u.hash_function()),
1224 __p3_(__u.__p3_)
1225{
1226}
1227
1228template <class _Tp, class _Hash, class _Equal, class _Alloc>
1229__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u,
1230 const allocator_type& __a)
1231 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1232 __p1_(__node_allocator(__a)),
1233 __p2_(0, __u.hash_function()),
1234 __p3_(__u.__p3_)
1235{
1236}
1237
Howard Hinnant73d21a42010-09-04 23:28:191238#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:161239
1240template <class _Tp, class _Hash, class _Equal, class _Alloc>
1241__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:241242 _NOEXCEPT_(
1243 is_nothrow_move_constructible<__bucket_list>::value &&
1244 is_nothrow_move_constructible<__first_node>::value &&
1245 is_nothrow_move_constructible<hasher>::value &&
1246 is_nothrow_move_constructible<key_equal>::value)
Howard Hinnant0949eed2011-06-30 21:18:191247 : __bucket_list_(_VSTD::move(__u.__bucket_list_)),
1248 __p1_(_VSTD::move(__u.__p1_)),
1249 __p2_(_VSTD::move(__u.__p2_)),
1250 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnantbc8d3f92010-05-11 19:42:161251{
1252 if (size() > 0)
1253 {
Howard Hinnant7a445152012-07-06 17:31:141254 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:291255 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:161256 __u.__p1_.first().__next_ = nullptr;
1257 __u.size() = 0;
1258 }
1259}
1260
1261template <class _Tp, class _Hash, class _Equal, class _Alloc>
1262__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u,
1263 const allocator_type& __a)
1264 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
1265 __p1_(__node_allocator(__a)),
Howard Hinnant0949eed2011-06-30 21:18:191266 __p2_(0, _VSTD::move(__u.hash_function())),
1267 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnantbc8d3f92010-05-11 19:42:161268{
1269 if (__a == allocator_type(__u.__node_alloc()))
1270 {
1271 __bucket_list_.reset(__u.__bucket_list_.release());
1272 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
1273 __u.__bucket_list_.get_deleter().size() = 0;
1274 if (__u.size() > 0)
1275 {
1276 __p1_.first().__next_ = __u.__p1_.first().__next_;
1277 __u.__p1_.first().__next_ = nullptr;
Howard Hinnant7a445152012-07-06 17:31:141278 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:291279 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:161280 size() = __u.size();
1281 __u.size() = 0;
1282 }
1283 }
1284}
1285
Howard Hinnant73d21a42010-09-04 23:28:191286#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:161287
1288template <class _Tp, class _Hash, class _Equal, class _Alloc>
1289__hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table()
1290{
1291 __deallocate(__p1_.first().__next_);
Howard Hinnant39213642013-07-23 22:01:581292#if _LIBCPP_DEBUG_LEVEL >= 2
1293 __get_db()->__erase_c(this);
1294#endif
Howard Hinnantbc8d3f92010-05-11 19:42:161295}
1296
1297template <class _Tp, class _Hash, class _Equal, class _Alloc>
1298void
1299__hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc(
1300 const __hash_table& __u, true_type)
1301{
1302 if (__node_alloc() != __u.__node_alloc())
1303 {
1304 clear();
1305 __bucket_list_.reset();
1306 __bucket_list_.get_deleter().size() = 0;
1307 }
1308 __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc();
1309 __node_alloc() = __u.__node_alloc();
1310}
1311
1312template <class _Tp, class _Hash, class _Equal, class _Alloc>
1313__hash_table<_Tp, _Hash, _Equal, _Alloc>&
1314__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u)
1315{
1316 if (this != &__u)
1317 {
1318 __copy_assign_alloc(__u);
1319 hash_function() = __u.hash_function();
1320 key_eq() = __u.key_eq();
1321 max_load_factor() = __u.max_load_factor();
1322 __assign_multi(__u.begin(), __u.end());
1323 }
1324 return *this;
1325}
1326
1327template <class _Tp, class _Hash, class _Equal, class _Alloc>
1328void
1329__hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate(__node_pointer __np)
Howard Hinnant5f2f14c2011-06-04 18:54:241330 _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:161331{
1332 __node_allocator& __na = __node_alloc();
1333 while (__np != nullptr)
1334 {
1335 __node_pointer __next = __np->__next_;
Howard Hinnant39213642013-07-23 22:01:581336#if _LIBCPP_DEBUG_LEVEL >= 2
1337 __c_node* __c = __get_db()->__find_c_and_lock(this);
1338 for (__i_node** __p = __c->end_; __p != __c->beg_; )
1339 {
1340 --__p;
1341 iterator* __i = static_cast<iterator*>((*__p)->__i_);
1342 if (__i->__node_ == __np)
1343 {
1344 (*__p)->__c_ = nullptr;
1345 if (--__c->end_ != __p)
1346 memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*));
1347 }
1348 }
1349 __get_db()->unlock();
1350#endif
Howard Hinnant0949eed2011-06-30 21:18:191351 __node_traits::destroy(__na, _VSTD::addressof(__np->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:161352 __node_traits::deallocate(__na, __np, 1);
1353 __np = __next;
1354 }
1355}
1356
1357template <class _Tp, class _Hash, class _Equal, class _Alloc>
1358typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_pointer
Howard Hinnant5f2f14c2011-06-04 18:54:241359__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:161360{
1361 size_type __bc = bucket_count();
1362 for (size_type __i = 0; __i < __bc; ++__i)
1363 __bucket_list_[__i] = nullptr;
1364 size() = 0;
1365 __node_pointer __cache = __p1_.first().__next_;
1366 __p1_.first().__next_ = nullptr;
1367 return __cache;
1368}
1369
Howard Hinnant73d21a42010-09-04 23:28:191370#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:161371
1372template <class _Tp, class _Hash, class _Equal, class _Alloc>
1373void
1374__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
1375 __hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:241376 _NOEXCEPT_(
1377 is_nothrow_move_assignable<__node_allocator>::value &&
1378 is_nothrow_move_assignable<hasher>::value &&
1379 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:161380{
1381 clear();
1382 __bucket_list_.reset(__u.__bucket_list_.release());
1383 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
1384 __u.__bucket_list_.get_deleter().size() = 0;
1385 __move_assign_alloc(__u);
1386 size() = __u.size();
Howard Hinnant0949eed2011-06-30 21:18:191387 hash_function() = _VSTD::move(__u.hash_function());
Howard Hinnantbc8d3f92010-05-11 19:42:161388 max_load_factor() = __u.max_load_factor();
Howard Hinnant0949eed2011-06-30 21:18:191389 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnantbc8d3f92010-05-11 19:42:161390 __p1_.first().__next_ = __u.__p1_.first().__next_;
1391 if (size() > 0)
1392 {
Howard Hinnant7a445152012-07-06 17:31:141393 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:291394 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:161395 __u.__p1_.first().__next_ = nullptr;
1396 __u.size() = 0;
1397 }
Howard Hinnant39213642013-07-23 22:01:581398#if _LIBCPP_DEBUG_LEVEL >= 2
1399 __get_db()->swap(this, &__u);
1400#endif
Howard Hinnantbc8d3f92010-05-11 19:42:161401}
1402
1403template <class _Tp, class _Hash, class _Equal, class _Alloc>
1404void
1405__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
1406 __hash_table& __u, false_type)
1407{
1408 if (__node_alloc() == __u.__node_alloc())
1409 __move_assign(__u, true_type());
1410 else
1411 {
Howard Hinnant0949eed2011-06-30 21:18:191412 hash_function() = _VSTD::move(__u.hash_function());
1413 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnantbc8d3f92010-05-11 19:42:161414 max_load_factor() = __u.max_load_factor();
1415 if (bucket_count() != 0)
1416 {
1417 __node_pointer __cache = __detach();
1418#ifndef _LIBCPP_NO_EXCEPTIONS
1419 try
1420 {
Howard Hinnant324bb032010-08-22 00:02:431421#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:161422 const_iterator __i = __u.begin();
1423 while (__cache != nullptr && __u.size() != 0)
1424 {
Howard Hinnant0949eed2011-06-30 21:18:191425 __cache->__value_ = _VSTD::move(__u.remove(__i++)->__value_);
Howard Hinnantbc8d3f92010-05-11 19:42:161426 __node_pointer __next = __cache->__next_;
1427 __node_insert_multi(__cache);
1428 __cache = __next;
1429 }
1430#ifndef _LIBCPP_NO_EXCEPTIONS
1431 }
1432 catch (...)
1433 {
1434 __deallocate(__cache);
1435 throw;
1436 }
Howard Hinnant324bb032010-08-22 00:02:431437#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:161438 __deallocate(__cache);
1439 }
1440 const_iterator __i = __u.begin();
1441 while (__u.size() != 0)
1442 {
1443 __node_holder __h =
Howard Hinnant0949eed2011-06-30 21:18:191444 __construct_node(_VSTD::move(__u.remove(__i++)->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:161445 __node_insert_multi(__h.get());
1446 __h.release();
1447 }
1448 }
1449}
1450
1451template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:391452inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:161453__hash_table<_Tp, _Hash, _Equal, _Alloc>&
1454__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:241455 _NOEXCEPT_(
1456 __node_traits::propagate_on_container_move_assignment::value &&
1457 is_nothrow_move_assignable<__node_allocator>::value &&
1458 is_nothrow_move_assignable<hasher>::value &&
1459 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:161460{
1461 __move_assign(__u, integral_constant<bool,
1462 __node_traits::propagate_on_container_move_assignment::value>());
1463 return *this;
1464}
1465
Howard Hinnant73d21a42010-09-04 23:28:191466#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:161467
1468template <class _Tp, class _Hash, class _Equal, class _Alloc>
1469template <class _InputIterator>
1470void
1471__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first,
1472 _InputIterator __last)
1473{
1474 if (bucket_count() != 0)
1475 {
1476 __node_pointer __cache = __detach();
1477#ifndef _LIBCPP_NO_EXCEPTIONS
1478 try
1479 {
Howard Hinnant324bb032010-08-22 00:02:431480#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:161481 for (; __cache != nullptr && __first != __last; ++__first)
1482 {
1483 __cache->__value_ = *__first;
1484 __node_pointer __next = __cache->__next_;
1485 __node_insert_unique(__cache);
1486 __cache = __next;
1487 }
1488#ifndef _LIBCPP_NO_EXCEPTIONS
1489 }
1490 catch (...)
1491 {
1492 __deallocate(__cache);
1493 throw;
1494 }
Howard Hinnant324bb032010-08-22 00:02:431495#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:161496 __deallocate(__cache);
1497 }
1498 for (; __first != __last; ++__first)
1499 __insert_unique(*__first);
1500}
1501
1502template <class _Tp, class _Hash, class _Equal, class _Alloc>
1503template <class _InputIterator>
1504void
1505__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first,
1506 _InputIterator __last)
1507{
1508 if (bucket_count() != 0)
1509 {
1510 __node_pointer __cache = __detach();
1511#ifndef _LIBCPP_NO_EXCEPTIONS
1512 try
1513 {
Howard Hinnant324bb032010-08-22 00:02:431514#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:161515 for (; __cache != nullptr && __first != __last; ++__first)
1516 {
1517 __cache->__value_ = *__first;
1518 __node_pointer __next = __cache->__next_;
1519 __node_insert_multi(__cache);
1520 __cache = __next;
1521 }
1522#ifndef _LIBCPP_NO_EXCEPTIONS
1523 }
1524 catch (...)
1525 {
1526 __deallocate(__cache);
1527 throw;
1528 }
Howard Hinnant324bb032010-08-22 00:02:431529#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:161530 __deallocate(__cache);
1531 }
1532 for (; __first != __last; ++__first)
1533 __insert_multi(*__first);
1534}
1535
1536template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:391537inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:161538typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:241539__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:161540{
Howard Hinnant39213642013-07-23 22:01:581541#if _LIBCPP_DEBUG_LEVEL >= 2
1542 return iterator(__p1_.first().__next_, this);
1543#else
Howard Hinnantbc8d3f92010-05-11 19:42:161544 return iterator(__p1_.first().__next_);
Howard Hinnant39213642013-07-23 22:01:581545#endif
Howard Hinnantbc8d3f92010-05-11 19:42:161546}
1547
1548template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:391549inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:161550typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:241551__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:161552{
Howard Hinnant39213642013-07-23 22:01:581553#if _LIBCPP_DEBUG_LEVEL >= 2
1554 return iterator(nullptr, this);
1555#else
Howard Hinnantbc8d3f92010-05-11 19:42:161556 return iterator(nullptr);
Howard Hinnant39213642013-07-23 22:01:581557#endif
Howard Hinnantbc8d3f92010-05-11 19:42:161558}
1559
1560template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:391561inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:161562typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:241563__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:161564{
Howard Hinnant39213642013-07-23 22:01:581565#if _LIBCPP_DEBUG_LEVEL >= 2
1566 return const_iterator(__p1_.first().__next_, this);
1567#else
Howard Hinnantbc8d3f92010-05-11 19:42:161568 return const_iterator(__p1_.first().__next_);
Howard Hinnant39213642013-07-23 22:01:581569#endif
Howard Hinnantbc8d3f92010-05-11 19:42:161570}
1571
1572template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:391573inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:161574typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:241575__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:161576{
Howard Hinnant39213642013-07-23 22:01:581577#if _LIBCPP_DEBUG_LEVEL >= 2
1578 return const_iterator(nullptr, this);
1579#else
Howard Hinnantbc8d3f92010-05-11 19:42:161580 return const_iterator(nullptr);
Howard Hinnant39213642013-07-23 22:01:581581#endif
Howard Hinnantbc8d3f92010-05-11 19:42:161582}
1583
1584template <class _Tp, class _Hash, class _Equal, class _Alloc>
1585void
Howard Hinnant5f2f14c2011-06-04 18:54:241586__hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:161587{
1588 if (size() > 0)
1589 {
1590 __deallocate(__p1_.first().__next_);
1591 __p1_.first().__next_ = nullptr;
1592 size_type __bc = bucket_count();
Howard Hinnant9f66bff2011-07-05 14:14:171593 for (size_type __i = 0; __i < __bc; ++__i)
Howard Hinnantbc8d3f92010-05-11 19:42:161594 __bucket_list_[__i] = nullptr;
1595 size() = 0;
1596 }
1597}
1598
1599template <class _Tp, class _Hash, class _Equal, class _Alloc>
1600pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1601__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd)
1602{
1603 __nd->__hash_ = hash_function()(__nd->__value_);
1604 size_type __bc = bucket_count();
1605 bool __inserted = false;
1606 __node_pointer __ndptr;
1607 size_t __chash;
1608 if (__bc != 0)
1609 {
Howard Hinnant7a445152012-07-06 17:31:141610 __chash = __constrain_hash(__nd->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:161611 __ndptr = __bucket_list_[__chash];
1612 if (__ndptr != nullptr)
1613 {
1614 for (__ndptr = __ndptr->__next_; __ndptr != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:141615 __constrain_hash(__ndptr->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:161616 __ndptr = __ndptr->__next_)
1617 {
1618 if (key_eq()(__ndptr->__value_, __nd->__value_))
1619 goto __done;
1620 }
1621 }
1622 }
1623 {
1624 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1625 {
Howard Hinnant7a445152012-07-06 17:31:141626 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:161627 size_type(ceil(float(size() + 1) / max_load_factor()))));
1628 __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:141629 __chash = __constrain_hash(__nd->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:161630 }
1631 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1632 __node_pointer __pn = __bucket_list_[__chash];
1633 if (__pn == nullptr)
1634 {
Howard Hinnant7a6b7ce2013-06-22 15:21:291635 __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:161636 __nd->__next_ = __pn->__next_;
1637 __pn->__next_ = __nd;
1638 // fix up __bucket_list_
1639 __bucket_list_[__chash] = __pn;
1640 if (__nd->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:141641 __bucket_list_[__constrain_hash(__nd->__next_->__hash_, __bc)] = __nd;
Howard Hinnantbc8d3f92010-05-11 19:42:161642 }
1643 else
1644 {
1645 __nd->__next_ = __pn->__next_;
1646 __pn->__next_ = __nd;
1647 }
1648 __ndptr = __nd;
1649 // increment size
1650 ++size();
1651 __inserted = true;
1652 }
1653__done:
Howard Hinnant39213642013-07-23 22:01:581654#if _LIBCPP_DEBUG_LEVEL >= 2
1655 return pair<iterator, bool>(iterator(__ndptr, this), __inserted);
1656#else
Howard Hinnantbc8d3f92010-05-11 19:42:161657 return pair<iterator, bool>(iterator(__ndptr), __inserted);
Howard Hinnant39213642013-07-23 22:01:581658#endif
Howard Hinnantbc8d3f92010-05-11 19:42:161659}
1660
1661template <class _Tp, class _Hash, class _Equal, class _Alloc>
1662typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1663__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp)
1664{
1665 __cp->__hash_ = hash_function()(__cp->__value_);
1666 size_type __bc = bucket_count();
1667 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1668 {
Howard Hinnant7a445152012-07-06 17:31:141669 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:161670 size_type(ceil(float(size() + 1) / max_load_factor()))));
1671 __bc = bucket_count();
1672 }
Howard Hinnant7a445152012-07-06 17:31:141673 size_t __chash = __constrain_hash(__cp->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:161674 __node_pointer __pn = __bucket_list_[__chash];
1675 if (__pn == nullptr)
1676 {
Howard Hinnant7a6b7ce2013-06-22 15:21:291677 __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:161678 __cp->__next_ = __pn->__next_;
1679 __pn->__next_ = __cp;
1680 // fix up __bucket_list_
1681 __bucket_list_[__chash] = __pn;
1682 if (__cp->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:141683 __bucket_list_[__constrain_hash(__cp->__next_->__hash_, __bc)] = __cp;
Howard Hinnantbc8d3f92010-05-11 19:42:161684 }
1685 else
1686 {
1687 for (bool __found = false; __pn->__next_ != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:141688 __constrain_hash(__pn->__next_->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:161689 __pn = __pn->__next_)
Howard Hinnant324bb032010-08-22 00:02:431690 {
Howard Hinnantbc8d3f92010-05-11 19:42:161691 // __found key_eq() action
1692 // false false loop
1693 // true true loop
1694 // false true set __found to true
1695 // true false break
1696 if (__found != (__pn->__next_->__hash_ == __cp->__hash_ &&
1697 key_eq()(__pn->__next_->__value_, __cp->__value_)))
1698 {
1699 if (!__found)
1700 __found = true;
1701 else
1702 break;
1703 }
1704 }
1705 __cp->__next_ = __pn->__next_;
1706 __pn->__next_ = __cp;
1707 if (__cp->__next_ != nullptr)
1708 {
Howard Hinnant7a445152012-07-06 17:31:141709 size_t __nhash = __constrain_hash(__cp->__next_->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:161710 if (__nhash != __chash)
1711 __bucket_list_[__nhash] = __cp;
1712 }
1713 }
1714 ++size();
Howard Hinnant39213642013-07-23 22:01:581715#if _LIBCPP_DEBUG_LEVEL >= 2
1716 return iterator(__cp, this);
1717#else
Howard Hinnantbc8d3f92010-05-11 19:42:161718 return iterator(__cp);
Howard Hinnant39213642013-07-23 22:01:581719#endif
Howard Hinnantbc8d3f92010-05-11 19:42:161720}
1721
1722template <class _Tp, class _Hash, class _Equal, class _Alloc>
1723typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1724__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(
1725 const_iterator __p, __node_pointer __cp)
1726{
1727 if (__p != end() && key_eq()(*__p, __cp->__value_))
1728 {
Howard Hinnant7a6b7ce2013-06-22 15:21:291729 __node_pointer __np = __p.__node_;
Howard Hinnantbc8d3f92010-05-11 19:42:161730 __cp->__hash_ = __np->__hash_;
1731 size_type __bc = bucket_count();
1732 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1733 {
Howard Hinnant7a445152012-07-06 17:31:141734 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:161735 size_type(ceil(float(size() + 1) / max_load_factor()))));
1736 __bc = bucket_count();
1737 }
Howard Hinnant7a445152012-07-06 17:31:141738 size_t __chash = __constrain_hash(__cp->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:161739 __node_pointer __pp = __bucket_list_[__chash];
1740 while (__pp->__next_ != __np)
1741 __pp = __pp->__next_;
1742 __cp->__next_ = __np;
1743 __pp->__next_ = __cp;
1744 ++size();
Howard Hinnant39213642013-07-23 22:01:581745#if _LIBCPP_DEBUG_LEVEL >= 2
1746 return iterator(__cp, this);
1747#else
Howard Hinnantbc8d3f92010-05-11 19:42:161748 return iterator(__cp);
Howard Hinnant39213642013-07-23 22:01:581749#endif
Howard Hinnantbc8d3f92010-05-11 19:42:161750 }
1751 return __node_insert_multi(__cp);
1752}
1753
1754template <class _Tp, class _Hash, class _Equal, class _Alloc>
1755pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1756__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(const value_type& __x)
1757{
1758 size_t __hash = hash_function()(__x);
1759 size_type __bc = bucket_count();
1760 bool __inserted = false;
1761 __node_pointer __nd;
1762 size_t __chash;
1763 if (__bc != 0)
1764 {
Howard Hinnant7a445152012-07-06 17:31:141765 __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:161766 __nd = __bucket_list_[__chash];
1767 if (__nd != nullptr)
1768 {
1769 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:141770 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:161771 __nd = __nd->__next_)
1772 {
1773 if (key_eq()(__nd->__value_, __x))
1774 goto __done;
1775 }
1776 }
1777 }
1778 {
1779 __node_holder __h = __construct_node(__x, __hash);
1780 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1781 {
Howard Hinnant7a445152012-07-06 17:31:141782 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:161783 size_type(ceil(float(size() + 1) / max_load_factor()))));
1784 __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:141785 __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:161786 }
1787 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1788 __node_pointer __pn = __bucket_list_[__chash];
1789 if (__pn == nullptr)
1790 {
Howard Hinnant7a6b7ce2013-06-22 15:21:291791 __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:161792 __h->__next_ = __pn->__next_;
1793 __pn->__next_ = __h.get();
1794 // fix up __bucket_list_
1795 __bucket_list_[__chash] = __pn;
1796 if (__h->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:141797 __bucket_list_[__constrain_hash(__h->__next_->__hash_, __bc)] = __h.get();
Howard Hinnantbc8d3f92010-05-11 19:42:161798 }
1799 else
1800 {
1801 __h->__next_ = __pn->__next_;
1802 __pn->__next_ = __h.get();
1803 }
1804 __nd = __h.release();
1805 // increment size
1806 ++size();
1807 __inserted = true;
1808 }
1809__done:
Howard Hinnant39213642013-07-23 22:01:581810#if _LIBCPP_DEBUG_LEVEL >= 2
1811 return pair<iterator, bool>(iterator(__nd, this), __inserted);
1812#else
Howard Hinnantbc8d3f92010-05-11 19:42:161813 return pair<iterator, bool>(iterator(__nd), __inserted);
Howard Hinnant39213642013-07-23 22:01:581814#endif
Howard Hinnantbc8d3f92010-05-11 19:42:161815}
1816
Howard Hinnant73d21a42010-09-04 23:28:191817#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1818#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:161819
1820template <class _Tp, class _Hash, class _Equal, class _Alloc>
1821template <class... _Args>
1822pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1823__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique(_Args&&... __args)
1824{
Howard Hinnant0949eed2011-06-30 21:18:191825 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:161826 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1827 if (__r.second)
1828 __h.release();
1829 return __r;
1830}
1831
1832template <class _Tp, class _Hash, class _Equal, class _Alloc>
1833template <class... _Args>
1834typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1835__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args)
1836{
Howard Hinnant0949eed2011-06-30 21:18:191837 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:161838 iterator __r = __node_insert_multi(__h.get());
1839 __h.release();
1840 return __r;
1841}
1842
1843template <class _Tp, class _Hash, class _Equal, class _Alloc>
1844template <class... _Args>
1845typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1846__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi(
1847 const_iterator __p, _Args&&... __args)
1848{
Howard Hinnant0bb0a7c2013-07-29 19:05:471849#if _LIBCPP_DEBUG_LEVEL >= 2
1850 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
1851 "unordered container::emplace_hint(const_iterator, args...) called with an iterator not"
1852 " referring to this unordered container");
1853#endif
Howard Hinnant0949eed2011-06-30 21:18:191854 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:161855 iterator __r = __node_insert_multi(__p, __h.get());
1856 __h.release();
1857 return __r;
1858}
1859
Howard Hinnant73d21a42010-09-04 23:28:191860#endif // _LIBCPP_HAS_NO_VARIADICS
1861
Howard Hinnantbc8d3f92010-05-11 19:42:161862template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:501863template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:161864pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
Howard Hinnant99968442011-11-29 18:15:501865__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(_Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:161866{
Howard Hinnant99968442011-11-29 18:15:501867 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:161868 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1869 if (__r.second)
1870 __h.release();
1871 return __r;
1872}
1873
Howard Hinnant73d21a42010-09-04 23:28:191874#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:161875
Howard Hinnant73d21a42010-09-04 23:28:191876#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:161877
1878template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:501879template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:161880typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant99968442011-11-29 18:15:501881__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(_Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:161882{
Howard Hinnant99968442011-11-29 18:15:501883 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:161884 iterator __r = __node_insert_multi(__h.get());
1885 __h.release();
1886 return __r;
1887}
1888
1889template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:501890template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:161891typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1892__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
Howard Hinnant99968442011-11-29 18:15:501893 _Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:161894{
Howard Hinnant0bb0a7c2013-07-29 19:05:471895#if _LIBCPP_DEBUG_LEVEL >= 2
1896 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
1897 "unordered container::insert(const_iterator, rvalue) called with an iterator not"
1898 " referring to this unordered container");
1899#endif
Howard Hinnant99968442011-11-29 18:15:501900 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:161901 iterator __r = __node_insert_multi(__p, __h.get());
1902 __h.release();
1903 return __r;
1904}
1905
Howard Hinnant73d21a42010-09-04 23:28:191906#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:161907
1908template <class _Tp, class _Hash, class _Equal, class _Alloc>
1909typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1910__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const value_type& __x)
1911{
1912 __node_holder __h = __construct_node(__x);
1913 iterator __r = __node_insert_multi(__h.get());
1914 __h.release();
1915 return __r;
1916}
1917
1918template <class _Tp, class _Hash, class _Equal, class _Alloc>
1919typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1920__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
1921 const value_type& __x)
1922{
Howard Hinnant0bb0a7c2013-07-29 19:05:471923#if _LIBCPP_DEBUG_LEVEL >= 2
1924 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
1925 "unordered container::insert(const_iterator, lvalue) called with an iterator not"
1926 " referring to this unordered container");
1927#endif
Howard Hinnantbc8d3f92010-05-11 19:42:161928 __node_holder __h = __construct_node(__x);
1929 iterator __r = __node_insert_multi(__p, __h.get());
1930 __h.release();
1931 return __r;
1932}
1933
Howard Hinnant73d21a42010-09-04 23:28:191934#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:161935
1936template <class _Tp, class _Hash, class _Equal, class _Alloc>
1937void
1938__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n)
1939{
Howard Hinnant7a445152012-07-06 17:31:141940 if (__n == 1)
1941 __n = 2;
1942 else if (__n & (__n - 1))
1943 __n = __next_prime(__n);
Howard Hinnantbc8d3f92010-05-11 19:42:161944 size_type __bc = bucket_count();
1945 if (__n > __bc)
1946 __rehash(__n);
Howard Hinnant7a445152012-07-06 17:31:141947 else if (__n < __bc)
Howard Hinnantbc8d3f92010-05-11 19:42:161948 {
Howard Hinnant0949eed2011-06-30 21:18:191949 __n = _VSTD::max<size_type>
Howard Hinnantbc8d3f92010-05-11 19:42:161950 (
1951 __n,
Howard Hinnant7a445152012-07-06 17:31:141952 __is_power2(__bc) ? __next_pow2(size_t(ceil(float(size()) / max_load_factor()))) :
1953 __next_prime(size_t(ceil(float(size()) / max_load_factor())))
Howard Hinnantbc8d3f92010-05-11 19:42:161954 );
1955 if (__n < __bc)
1956 __rehash(__n);
1957 }
1958}
1959
1960template <class _Tp, class _Hash, class _Equal, class _Alloc>
1961void
1962__hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc)
1963{
Howard Hinnant39213642013-07-23 22:01:581964#if _LIBCPP_DEBUG_LEVEL >= 2
1965 __get_db()->__invalidate_all(this);
1966#endif // _LIBCPP_DEBUG_LEVEL >= 2
Howard Hinnantbc8d3f92010-05-11 19:42:161967 __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc();
1968 __bucket_list_.reset(__nbc > 0 ?
1969 __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr);
1970 __bucket_list_.get_deleter().size() = __nbc;
1971 if (__nbc > 0)
1972 {
1973 for (size_type __i = 0; __i < __nbc; ++__i)
1974 __bucket_list_[__i] = nullptr;
Howard Hinnant7a6b7ce2013-06-22 15:21:291975 __node_pointer __pp(static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())));
Howard Hinnantbc8d3f92010-05-11 19:42:161976 __node_pointer __cp = __pp->__next_;
1977 if (__cp != nullptr)
1978 {
Howard Hinnant7a445152012-07-06 17:31:141979 size_type __chash = __constrain_hash(__cp->__hash_, __nbc);
Howard Hinnantbc8d3f92010-05-11 19:42:161980 __bucket_list_[__chash] = __pp;
1981 size_type __phash = __chash;
1982 for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr;
1983 __cp = __pp->__next_)
1984 {
Howard Hinnant7a445152012-07-06 17:31:141985 __chash = __constrain_hash(__cp->__hash_, __nbc);
Howard Hinnantbc8d3f92010-05-11 19:42:161986 if (__chash == __phash)
1987 __pp = __cp;
1988 else
1989 {
1990 if (__bucket_list_[__chash] == nullptr)
1991 {
1992 __bucket_list_[__chash] = __pp;
1993 __pp = __cp;
1994 __phash = __chash;
1995 }
1996 else
1997 {
1998 __node_pointer __np = __cp;
1999 for (; __np->__next_ != nullptr &&
2000 key_eq()(__cp->__value_, __np->__next_->__value_);
2001 __np = __np->__next_)
2002 ;
2003 __pp->__next_ = __np->__next_;
2004 __np->__next_ = __bucket_list_[__chash]->__next_;
2005 __bucket_list_[__chash]->__next_ = __cp;
Howard Hinnant324bb032010-08-22 00:02:432006
Howard Hinnantbc8d3f92010-05-11 19:42:162007 }
2008 }
2009 }
2010 }
2011 }
2012}
2013
2014template <class _Tp, class _Hash, class _Equal, class _Alloc>
2015template <class _Key>
2016typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2017__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k)
2018{
2019 size_t __hash = hash_function()(__k);
2020 size_type __bc = bucket_count();
2021 if (__bc != 0)
2022 {
Howard Hinnant7a445152012-07-06 17:31:142023 size_t __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:162024 __node_pointer __nd = __bucket_list_[__chash];
2025 if (__nd != nullptr)
2026 {
2027 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:142028 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:162029 __nd = __nd->__next_)
2030 {
2031 if (key_eq()(__nd->__value_, __k))
Howard Hinnant39213642013-07-23 22:01:582032#if _LIBCPP_DEBUG_LEVEL >= 2
2033 return iterator(__nd, this);
2034#else
Howard Hinnantbc8d3f92010-05-11 19:42:162035 return iterator(__nd);
Howard Hinnant39213642013-07-23 22:01:582036#endif
Howard Hinnantbc8d3f92010-05-11 19:42:162037 }
2038 }
2039 }
2040 return end();
2041}
2042
2043template <class _Tp, class _Hash, class _Equal, class _Alloc>
2044template <class _Key>
2045typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
2046__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const
2047{
2048 size_t __hash = hash_function()(__k);
2049 size_type __bc = bucket_count();
2050 if (__bc != 0)
2051 {
Howard Hinnant7a445152012-07-06 17:31:142052 size_t __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:162053 __node_const_pointer __nd = __bucket_list_[__chash];
2054 if (__nd != nullptr)
2055 {
2056 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:142057 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:162058 __nd = __nd->__next_)
2059 {
2060 if (key_eq()(__nd->__value_, __k))
Howard Hinnant39213642013-07-23 22:01:582061#if _LIBCPP_DEBUG_LEVEL >= 2
2062 return const_iterator(__nd, this);
2063#else
Howard Hinnantbc8d3f92010-05-11 19:42:162064 return const_iterator(__nd);
Howard Hinnant39213642013-07-23 22:01:582065#endif
Howard Hinnantbc8d3f92010-05-11 19:42:162066 }
2067 }
Howard Hinnant324bb032010-08-22 00:02:432068
Howard Hinnantbc8d3f92010-05-11 19:42:162069 }
2070 return end();
2071}
2072
Howard Hinnant73d21a42010-09-04 23:28:192073#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
2074#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:162075
2076template <class _Tp, class _Hash, class _Equal, class _Alloc>
2077template <class ..._Args>
2078typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
2079__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args)
2080{
2081 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:502082 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:192083 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:162084 __h.get_deleter().__value_constructed = true;
2085 __h->__hash_ = hash_function()(__h->__value_);
2086 __h->__next_ = nullptr;
2087 return __h;
2088}
2089
Howard Hinnant73d21a42010-09-04 23:28:192090#endif // _LIBCPP_HAS_NO_VARIADICS
2091
Howard Hinnantbc8d3f92010-05-11 19:42:162092template <class _Tp, class _Hash, class _Equal, class _Alloc>
2093typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
2094__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(value_type&& __v,
2095 size_t __hash)
2096{
2097 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:502098 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:192099 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::move(__v));
Howard Hinnantbc8d3f92010-05-11 19:42:162100 __h.get_deleter().__value_constructed = true;
2101 __h->__hash_ = __hash;
2102 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:192103 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:162104}
2105
Howard Hinnant73d21a42010-09-04 23:28:192106#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:162107
2108template <class _Tp, class _Hash, class _Equal, class _Alloc>
2109typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
2110__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v)
2111{
2112 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:502113 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:192114 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:162115 __h.get_deleter().__value_constructed = true;
2116 __h->__hash_ = hash_function()(__h->__value_);
2117 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:192118 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:162119}
2120
Howard Hinnant73d21a42010-09-04 23:28:192121#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:162122
2123template <class _Tp, class _Hash, class _Equal, class _Alloc>
2124typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
2125__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v,
2126 size_t __hash)
2127{
2128 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:502129 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:192130 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:162131 __h.get_deleter().__value_constructed = true;
2132 __h->__hash_ = __hash;
2133 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:192134 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:162135}
2136
2137template <class _Tp, class _Hash, class _Equal, class _Alloc>
2138typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2139__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p)
2140{
Howard Hinnant7a6b7ce2013-06-22 15:21:292141 __node_pointer __np = __p.__node_;
Howard Hinnant39213642013-07-23 22:01:582142#if _LIBCPP_DEBUG_LEVEL >= 2
2143 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this,
2144 "unordered container erase(iterator) called with an iterator not"
2145 " referring to this container");
2146 _LIBCPP_ASSERT(__p != end(),
2147 "unordered container erase(iterator) called with a non-dereferenceable iterator");
2148 iterator __r(__np, this);
2149#else
Howard Hinnantbc8d3f92010-05-11 19:42:162150 iterator __r(__np);
Howard Hinnant39213642013-07-23 22:01:582151#endif
Howard Hinnantbc8d3f92010-05-11 19:42:162152 ++__r;
2153 remove(__p);
2154 return __r;
2155}
2156
2157template <class _Tp, class _Hash, class _Equal, class _Alloc>
2158typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
2159__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first,
2160 const_iterator __last)
2161{
Howard Hinnant39213642013-07-23 22:01:582162#if _LIBCPP_DEBUG_LEVEL >= 2
2163 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this,
2164 "unodered container::erase(iterator, iterator) called with an iterator not"
2165 " referring to this unodered container");
2166 _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__last) == this,
2167 "unodered container::erase(iterator, iterator) called with an iterator not"
2168 " referring to this unodered container");
2169#endif
Howard Hinnantbc8d3f92010-05-11 19:42:162170 for (const_iterator __p = __first; __first != __last; __p = __first)
2171 {
2172 ++__first;
2173 erase(__p);
2174 }
Howard Hinnant7a6b7ce2013-06-22 15:21:292175 __node_pointer __np = __last.__node_;
Howard Hinnant39213642013-07-23 22:01:582176#if _LIBCPP_DEBUG_LEVEL >= 2
2177 return iterator (__np, this);
2178#else
Howard Hinnantbc8d3f92010-05-11 19:42:162179 return iterator (__np);
Howard Hinnant39213642013-07-23 22:01:582180#endif
Howard Hinnantbc8d3f92010-05-11 19:42:162181}
2182
2183template <class _Tp, class _Hash, class _Equal, class _Alloc>
2184template <class _Key>
2185typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2186__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k)
2187{
2188 iterator __i = find(__k);
2189 if (__i == end())
2190 return 0;
2191 erase(__i);
2192 return 1;
2193}
2194
2195template <class _Tp, class _Hash, class _Equal, class _Alloc>
2196template <class _Key>
2197typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2198__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k)
2199{
2200 size_type __r = 0;
2201 iterator __i = find(__k);
2202 if (__i != end())
2203 {
2204 iterator __e = end();
2205 do
2206 {
2207 erase(__i++);
2208 ++__r;
2209 } while (__i != __e && key_eq()(*__i, __k));
2210 }
2211 return __r;
2212}
2213
2214template <class _Tp, class _Hash, class _Equal, class _Alloc>
2215typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
Howard Hinnant5f2f14c2011-06-04 18:54:242216__hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:162217{
2218 // current node
Howard Hinnant7a6b7ce2013-06-22 15:21:292219 __node_pointer __cn = __p.__node_;
Howard Hinnantbc8d3f92010-05-11 19:42:162220 size_type __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:142221 size_t __chash = __constrain_hash(__cn->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:162222 // find previous node
2223 __node_pointer __pn = __bucket_list_[__chash];
2224 for (; __pn->__next_ != __cn; __pn = __pn->__next_)
2225 ;
2226 // Fix up __bucket_list_
2227 // if __pn is not in same bucket (before begin is not in same bucket) &&
2228 // if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
Howard Hinnant7a6b7ce2013-06-22 15:21:292229 if (__pn == static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()))
2230 || __constrain_hash(__pn->__hash_, __bc) != __chash)
Howard Hinnantbc8d3f92010-05-11 19:42:162231 {
Howard Hinnant7a445152012-07-06 17:31:142232 if (__cn->__next_ == nullptr || __constrain_hash(__cn->__next_->__hash_, __bc) != __chash)
Howard Hinnantbc8d3f92010-05-11 19:42:162233 __bucket_list_[__chash] = nullptr;
2234 }
2235 // if __cn->__next_ is not in same bucket (nullptr is in same bucket)
2236 if (__cn->__next_ != nullptr)
2237 {
Howard Hinnant7a445152012-07-06 17:31:142238 size_t __nhash = __constrain_hash(__cn->__next_->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:162239 if (__nhash != __chash)
2240 __bucket_list_[__nhash] = __pn;
2241 }
2242 // remove __cn
2243 __pn->__next_ = __cn->__next_;
2244 __cn->__next_ = nullptr;
2245 --size();
Howard Hinnant39213642013-07-23 22:01:582246#if _LIBCPP_DEBUG_LEVEL >= 2
2247 __c_node* __c = __get_db()->__find_c_and_lock(this);
2248 for (__i_node** __p = __c->end_; __p != __c->beg_; )
2249 {
2250 --__p;
2251 iterator* __i = static_cast<iterator*>((*__p)->__i_);
2252 if (__i->__node_ == __cn)
2253 {
2254 (*__p)->__c_ = nullptr;
2255 if (--__c->end_ != __p)
2256 memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*));
2257 }
2258 }
2259 __get_db()->unlock();
2260#endif
Howard Hinnant99968442011-11-29 18:15:502261 return __node_holder(__cn, _Dp(__node_alloc(), true));
Howard Hinnantbc8d3f92010-05-11 19:42:162262}
2263
2264template <class _Tp, class _Hash, class _Equal, class _Alloc>
2265template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:392266inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:162267typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2268__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const
2269{
2270 return static_cast<size_type>(find(__k) != end());
2271}
2272
2273template <class _Tp, class _Hash, class _Equal, class _Alloc>
2274template <class _Key>
2275typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2276__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const
2277{
2278 size_type __r = 0;
2279 const_iterator __i = find(__k);
2280 if (__i != end())
2281 {
2282 const_iterator __e = end();
2283 do
2284 {
2285 ++__i;
2286 ++__r;
2287 } while (__i != __e && key_eq()(*__i, __k));
2288 }
2289 return __r;
2290}
2291
2292template <class _Tp, class _Hash, class _Equal, class _Alloc>
2293template <class _Key>
2294pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
2295 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
2296__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
2297 const _Key& __k)
2298{
2299 iterator __i = find(__k);
2300 iterator __j = __i;
2301 if (__i != end())
2302 ++__j;
2303 return pair<iterator, iterator>(__i, __j);
2304}
2305
2306template <class _Tp, class _Hash, class _Equal, class _Alloc>
2307template <class _Key>
2308pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
2309 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
2310__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
2311 const _Key& __k) const
2312{
2313 const_iterator __i = find(__k);
2314 const_iterator __j = __i;
2315 if (__i != end())
2316 ++__j;
2317 return pair<const_iterator, const_iterator>(__i, __j);
2318}
2319
2320template <class _Tp, class _Hash, class _Equal, class _Alloc>
2321template <class _Key>
2322pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
2323 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
2324__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
2325 const _Key& __k)
2326{
2327 iterator __i = find(__k);
2328 iterator __j = __i;
2329 if (__i != end())
2330 {
2331 iterator __e = end();
2332 do
2333 {
2334 ++__j;
2335 } while (__j != __e && key_eq()(*__j, __k));
2336 }
2337 return pair<iterator, iterator>(__i, __j);
2338}
2339
2340template <class _Tp, class _Hash, class _Equal, class _Alloc>
2341template <class _Key>
2342pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
2343 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
2344__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
2345 const _Key& __k) const
2346{
2347 const_iterator __i = find(__k);
2348 const_iterator __j = __i;
2349 if (__i != end())
2350 {
2351 const_iterator __e = end();
2352 do
2353 {
2354 ++__j;
2355 } while (__j != __e && key_eq()(*__j, __k));
2356 }
2357 return pair<const_iterator, const_iterator>(__i, __j);
2358}
2359
2360template <class _Tp, class _Hash, class _Equal, class _Alloc>
2361void
2362__hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:242363 _NOEXCEPT_(
2364 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
2365 __is_nothrow_swappable<__pointer_allocator>::value) &&
2366 (!__node_traits::propagate_on_container_swap::value ||
2367 __is_nothrow_swappable<__node_allocator>::value) &&
2368 __is_nothrow_swappable<hasher>::value &&
2369 __is_nothrow_swappable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:162370{
2371 {
2372 __node_pointer_pointer __npp = __bucket_list_.release();
2373 __bucket_list_.reset(__u.__bucket_list_.release());
2374 __u.__bucket_list_.reset(__npp);
2375 }
Howard Hinnant0949eed2011-06-30 21:18:192376 _VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
Howard Hinnantbc8d3f92010-05-11 19:42:162377 __swap_alloc(__bucket_list_.get_deleter().__alloc(),
2378 __u.__bucket_list_.get_deleter().__alloc());
2379 __swap_alloc(__node_alloc(), __u.__node_alloc());
Howard Hinnant0949eed2011-06-30 21:18:192380 _VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
Howard Hinnantbc8d3f92010-05-11 19:42:162381 __p2_.swap(__u.__p2_);
2382 __p3_.swap(__u.__p3_);
2383 if (size() > 0)
Howard Hinnant7a445152012-07-06 17:31:142384 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:292385 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:162386 if (__u.size() > 0)
Howard Hinnant7a445152012-07-06 17:31:142387 __u.__bucket_list_[__constrain_hash(__u.__p1_.first().__next_->__hash_, __u.bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:292388 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__u.__p1_.first()));
Howard Hinnant39213642013-07-23 22:01:582389#if _LIBCPP_DEBUG_LEVEL >= 2
2390 __get_db()->swap(this, &__u);
2391#endif
Howard Hinnantbc8d3f92010-05-11 19:42:162392}
2393
2394template <class _Tp, class _Hash, class _Equal, class _Alloc>
2395typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
2396__hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const
2397{
Howard Hinnant0bb0a7c2013-07-29 19:05:472398 _LIBCPP_ASSERT(__n < bucket_count(),
2399 "unordered container::bucket_size(n) called with n >= bucket_count()");
Howard Hinnantbc8d3f92010-05-11 19:42:162400 __node_const_pointer __np = __bucket_list_[__n];
2401 size_type __bc = bucket_count();
2402 size_type __r = 0;
2403 if (__np != nullptr)
2404 {
2405 for (__np = __np->__next_; __np != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:142406 __constrain_hash(__np->__hash_, __bc) == __n;
Howard Hinnantbc8d3f92010-05-11 19:42:162407 __np = __np->__next_, ++__r)
2408 ;
2409 }
2410 return __r;
2411}
2412
Howard Hinnant5f2f14c2011-06-04 18:54:242413template <class _Tp, class _Hash, class _Equal, class _Alloc>
2414inline _LIBCPP_INLINE_VISIBILITY
2415void
2416swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x,
2417 __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y)
2418 _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
2419{
2420 __x.swap(__y);
2421}
2422
Howard Hinnant39213642013-07-23 22:01:582423#if _LIBCPP_DEBUG_LEVEL >= 2
2424
2425template <class _Tp, class _Hash, class _Equal, class _Alloc>
2426bool
2427__hash_table<_Tp, _Hash, _Equal, _Alloc>::__dereferenceable(const const_iterator* __i) const
2428{
2429 return __i->__node_ != nullptr;
2430}
2431
2432template <class _Tp, class _Hash, class _Equal, class _Alloc>
2433bool
2434__hash_table<_Tp, _Hash, _Equal, _Alloc>::__decrementable(const const_iterator*) const
2435{
2436 return false;
2437}
2438
2439template <class _Tp, class _Hash, class _Equal, class _Alloc>
2440bool
2441__hash_table<_Tp, _Hash, _Equal, _Alloc>::__addable(const const_iterator*, ptrdiff_t) const
2442{
2443 return false;
2444}
2445
2446template <class _Tp, class _Hash, class _Equal, class _Alloc>
2447bool
2448__hash_table<_Tp, _Hash, _Equal, _Alloc>::__subscriptable(const const_iterator*, ptrdiff_t) const
2449{
2450 return false;
2451}
2452
2453#endif // _LIBCPP_DEBUG_LEVEL >= 2
Howard Hinnantbc8d3f92010-05-11 19:42:162454_LIBCPP_END_NAMESPACE_STD
2455
2456#endif // _LIBCPP__HASH_TABLE