blob: 2b282d33a9e3b4239662dcdb932e9a89537b316c [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00006// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00008//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP__HASH_TABLE
12#define _LIBCPP__HASH_TABLE
13
14#include <__config>
15#include <initializer_list>
16#include <memory>
17#include <iterator>
18#include <algorithm>
19#include <cmath>
20
Howard Hinnant66c6f972011-11-29 16:45:27 +000021#include <__undef_min_max>
22
Howard Hinnant08e17472011-10-17 20:05:10 +000023#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000024#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:10 +000025#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000026
27_LIBCPP_BEGIN_NAMESPACE_STD
28
Howard Hinnant83eade62013-03-06 23:30:19 +000029_LIBCPP_FUNC_VIS
Howard Hinnant2b1b2d42011-06-14 19:58:17 +000030size_t __next_prime(size_t __n);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000031
32template <class _NodePtr>
33struct __hash_node_base
34{
35 typedef __hash_node_base __first_node;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000036
Howard Hinnantdf85e572011-02-27 18:02:02 +000037 _NodePtr __next_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000038
Howard Hinnant5f2f14c2011-06-04 18:54:24 +000039 _LIBCPP_INLINE_VISIBILITY __hash_node_base() _NOEXCEPT : __next_(nullptr) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000040};
41
42template <class _Tp, class _VoidPtr>
43struct __hash_node
44 : public __hash_node_base
45 <
46 typename pointer_traits<_VoidPtr>::template
47#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
48 rebind<__hash_node<_Tp, _VoidPtr> >
49#else
50 rebind<__hash_node<_Tp, _VoidPtr> >::other
51#endif
52 >
53{
54 typedef _Tp value_type;
55
56 size_t __hash_;
57 value_type __value_;
58};
59
Howard Hinnant7a445152012-07-06 17:31:14 +000060inline _LIBCPP_INLINE_VISIBILITY
61bool
62__is_power2(size_t __bc)
63{
64 return __bc > 2 && !(__bc & (__bc - 1));
65}
66
67inline _LIBCPP_INLINE_VISIBILITY
68size_t
69__constrain_hash(size_t __h, size_t __bc)
70{
71 return !(__bc & (__bc - 1)) ? __h & (__bc - 1) : __h % __bc;
72}
73
74inline _LIBCPP_INLINE_VISIBILITY
75size_t
76__next_pow2(size_t __n)
77{
78 return size_t(1) << (std::numeric_limits<size_t>::digits - __clz(__n-1));
79}
80
Howard Hinnant2b1b2d42011-06-14 19:58:17 +000081template <class _Tp, class _Hash, class _Equal, class _Alloc> class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19 +000082template <class _ConstNodePtr> class _LIBCPP_TYPE_VIS __hash_const_iterator;
83template <class _HashIterator> class _LIBCPP_TYPE_VIS __hash_map_iterator;
84template <class _HashIterator> class _LIBCPP_TYPE_VIS __hash_map_const_iterator;
Howard Hinnant2b1b2d42011-06-14 19:58:17 +000085template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
Howard Hinnant83eade62013-03-06 23:30:19 +000086 class _LIBCPP_TYPE_VIS unordered_map;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000087
88template <class _NodePtr>
Howard Hinnant83eade62013-03-06 23:30:19 +000089class _LIBCPP_TYPE_VIS __hash_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000090{
91 typedef _NodePtr __node_pointer;
92
93 __node_pointer __node_;
94
95public:
96 typedef forward_iterator_tag iterator_category;
97 typedef typename pointer_traits<__node_pointer>::element_type::value_type value_type;
98 typedef typename pointer_traits<__node_pointer>::difference_type difference_type;
99 typedef value_type& reference;
100 typedef typename pointer_traits<__node_pointer>::template
101#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
102 rebind<value_type>
103#else
104 rebind<value_type>::other
105#endif
106 pointer;
107
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000108 _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000109
Howard Hinnant99acc502010-09-21 17:32:39 +0000110 _LIBCPP_INLINE_VISIBILITY
111 reference operator*() const {return __node_->__value_;}
112 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000113 pointer operator->() const {return pointer_traits<pointer>::pointer_to(__node_->__value_);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000114
Howard Hinnant99acc502010-09-21 17:32:39 +0000115 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000116 __hash_iterator& operator++()
117 {
118 __node_ = __node_->__next_;
119 return *this;
120 }
121
Howard Hinnant99acc502010-09-21 17:32:39 +0000122 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000123 __hash_iterator operator++(int)
124 {
125 __hash_iterator __t(*this);
126 ++(*this);
127 return __t;
128 }
129
Howard Hinnant99acc502010-09-21 17:32:39 +0000130 friend _LIBCPP_INLINE_VISIBILITY
131 bool operator==(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000132 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000133 friend _LIBCPP_INLINE_VISIBILITY
134 bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000135 {return __x.__node_ != __y.__node_;}
136
137private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000138 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000139 __hash_iterator(__node_pointer __node) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000140 : __node_(__node)
141 {}
142
143 template <class, class, class, class> friend class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19 +0000144 template <class> friend class _LIBCPP_TYPE_VIS __hash_const_iterator;
145 template <class> friend class _LIBCPP_TYPE_VIS __hash_map_iterator;
146 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_map;
147 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000148};
149
150template <class _ConstNodePtr>
Howard Hinnant83eade62013-03-06 23:30:19 +0000151class _LIBCPP_TYPE_VIS __hash_const_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000152{
153 typedef _ConstNodePtr __node_pointer;
154
155 __node_pointer __node_;
156
157 typedef typename remove_const<
158 typename pointer_traits<__node_pointer>::element_type
159 >::type __node;
160
161public:
162 typedef forward_iterator_tag iterator_category;
163 typedef typename __node::value_type value_type;
164 typedef typename pointer_traits<__node_pointer>::difference_type difference_type;
165 typedef const value_type& reference;
166 typedef typename pointer_traits<__node_pointer>::template
167#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
168 rebind<const value_type>
169#else
170 rebind<const value_type>::other
171#endif
172 pointer;
173 typedef typename pointer_traits<__node_pointer>::template
174#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
175 rebind<__node>
176#else
177 rebind<__node>::other
178#endif
179 __non_const_node_pointer;
180 typedef __hash_iterator<__non_const_node_pointer> __non_const_iterator;
181
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000182 _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000183 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000184 __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000185 : __node_(__x.__node_)
186 {}
187
Howard Hinnant99acc502010-09-21 17:32:39 +0000188 _LIBCPP_INLINE_VISIBILITY
189 reference operator*() const {return __node_->__value_;}
190 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000191 pointer operator->() const {return pointer_traits<pointer>::pointer_to(__node_->__value_);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000192
Howard Hinnant99acc502010-09-21 17:32:39 +0000193 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000194 __hash_const_iterator& operator++()
195 {
196 __node_ = __node_->__next_;
197 return *this;
198 }
199
Howard Hinnant99acc502010-09-21 17:32:39 +0000200 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000201 __hash_const_iterator operator++(int)
202 {
203 __hash_const_iterator __t(*this);
204 ++(*this);
205 return __t;
206 }
207
Howard Hinnant99acc502010-09-21 17:32:39 +0000208 friend _LIBCPP_INLINE_VISIBILITY
209 bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000210 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000211 friend _LIBCPP_INLINE_VISIBILITY
212 bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000213 {return __x.__node_ != __y.__node_;}
214
215private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000216 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000217 __hash_const_iterator(__node_pointer __node) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000218 : __node_(__node)
219 {}
220
221 template <class, class, class, class> friend class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19 +0000222 template <class> friend class _LIBCPP_TYPE_VIS __hash_map_const_iterator;
223 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_map;
224 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000225};
226
Howard Hinnant83eade62013-03-06 23:30:19 +0000227template <class _ConstNodePtr> class _LIBCPP_TYPE_VIS __hash_const_local_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000228
229template <class _NodePtr>
Howard Hinnant83eade62013-03-06 23:30:19 +0000230class _LIBCPP_TYPE_VIS __hash_local_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000231{
232 typedef _NodePtr __node_pointer;
233
234 __node_pointer __node_;
235 size_t __bucket_;
236 size_t __bucket_count_;
237
238 typedef pointer_traits<__node_pointer> __pointer_traits;
239public:
240 typedef forward_iterator_tag iterator_category;
241 typedef typename __pointer_traits::element_type::value_type value_type;
242 typedef typename __pointer_traits::difference_type difference_type;
243 typedef value_type& reference;
244 typedef typename __pointer_traits::template
245#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
246 rebind<value_type>
247#else
248 rebind<value_type>::other
249#endif
250 pointer;
251
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000252 _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000253
Howard Hinnant99acc502010-09-21 17:32:39 +0000254 _LIBCPP_INLINE_VISIBILITY
255 reference operator*() const {return __node_->__value_;}
256 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000257 pointer operator->() const {return pointer_traits<pointer>::pointer_to(__node_->__value_);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000258
Howard Hinnant99acc502010-09-21 17:32:39 +0000259 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000260 __hash_local_iterator& operator++()
261 {
262 __node_ = __node_->__next_;
Howard Hinnant7a445152012-07-06 17:31:14 +0000263 if (__node_ != nullptr && __constrain_hash(__node_->__hash_, __bucket_count_) != __bucket_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000264 __node_ = nullptr;
265 return *this;
266 }
267
Howard Hinnant99acc502010-09-21 17:32:39 +0000268 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000269 __hash_local_iterator operator++(int)
270 {
271 __hash_local_iterator __t(*this);
272 ++(*this);
273 return __t;
274 }
275
Howard Hinnant99acc502010-09-21 17:32:39 +0000276 friend _LIBCPP_INLINE_VISIBILITY
277 bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000278 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000279 friend _LIBCPP_INLINE_VISIBILITY
280 bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000281 {return __x.__node_ != __y.__node_;}
282
283private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000284 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000285 __hash_local_iterator(__node_pointer __node, size_t __bucket,
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000286 size_t __bucket_count) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000287 : __node_(__node),
288 __bucket_(__bucket),
289 __bucket_count_(__bucket_count)
290 {
291 if (__node_ != nullptr)
292 __node_ = __node_->__next_;
293 }
294
295 template <class, class, class, class> friend class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19 +0000296 template <class> friend class _LIBCPP_TYPE_VIS __hash_const_local_iterator;
297 template <class> friend class _LIBCPP_TYPE_VIS __hash_map_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000298};
299
300template <class _ConstNodePtr>
Howard Hinnant83eade62013-03-06 23:30:19 +0000301class _LIBCPP_TYPE_VIS __hash_const_local_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000302{
303 typedef _ConstNodePtr __node_pointer;
304
305 __node_pointer __node_;
306 size_t __bucket_;
307 size_t __bucket_count_;
308
309 typedef pointer_traits<__node_pointer> __pointer_traits;
310 typedef typename __pointer_traits::element_type __node;
311 typedef typename remove_const<__node>::type __non_const_node;
312 typedef typename pointer_traits<__node_pointer>::template
313#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
314 rebind<__non_const_node>
315#else
316 rebind<__non_const_node>::other
317#endif
318 __non_const_node_pointer;
319 typedef __hash_local_iterator<__non_const_node_pointer>
320 __non_const_iterator;
321public:
322 typedef forward_iterator_tag iterator_category;
323 typedef typename remove_const<
324 typename __pointer_traits::element_type::value_type
325 >::type value_type;
326 typedef typename __pointer_traits::difference_type difference_type;
327 typedef const value_type& reference;
328 typedef typename __pointer_traits::template
329#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
330 rebind<const value_type>
331#else
332 rebind<const value_type>::other
333#endif
334 pointer;
335
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000336 _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000337 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000338 __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000339 : __node_(__x.__node_),
340 __bucket_(__x.__bucket_),
341 __bucket_count_(__x.__bucket_count_)
342 {}
343
Howard Hinnant99acc502010-09-21 17:32:39 +0000344 _LIBCPP_INLINE_VISIBILITY
345 reference operator*() const {return __node_->__value_;}
346 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000347 pointer operator->() const {return pointer_traits<pointer>::pointer_to(__node_->__value_);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000348
Howard Hinnant99acc502010-09-21 17:32:39 +0000349 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000350 __hash_const_local_iterator& operator++()
351 {
352 __node_ = __node_->__next_;
Howard Hinnant7a445152012-07-06 17:31:14 +0000353 if (__node_ != nullptr && __constrain_hash(__node_->__hash_, __bucket_count_) != __bucket_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000354 __node_ = nullptr;
355 return *this;
356 }
357
Howard Hinnant99acc502010-09-21 17:32:39 +0000358 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000359 __hash_const_local_iterator operator++(int)
360 {
361 __hash_const_local_iterator __t(*this);
362 ++(*this);
363 return __t;
364 }
365
Howard Hinnant99acc502010-09-21 17:32:39 +0000366 friend _LIBCPP_INLINE_VISIBILITY
367 bool operator==(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000368 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000369 friend _LIBCPP_INLINE_VISIBILITY
370 bool operator!=(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000371 {return __x.__node_ != __y.__node_;}
372
373private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000374 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000375 __hash_const_local_iterator(__node_pointer __node, size_t __bucket,
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000376 size_t __bucket_count) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000377 : __node_(__node),
378 __bucket_(__bucket),
379 __bucket_count_(__bucket_count)
380 {
381 if (__node_ != nullptr)
382 __node_ = __node_->__next_;
383 }
384
385 template <class, class, class, class> friend class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19 +0000386 template <class> friend class _LIBCPP_TYPE_VIS __hash_map_const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000387};
388
389template <class _Alloc>
390class __bucket_list_deallocator
391{
392 typedef _Alloc allocator_type;
393 typedef allocator_traits<allocator_type> __alloc_traits;
394 typedef typename __alloc_traits::size_type size_type;
395
396 __compressed_pair<size_type, allocator_type> __data_;
397public:
398 typedef typename __alloc_traits::pointer pointer;
399
Howard Hinnant99acc502010-09-21 17:32:39 +0000400 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000401 __bucket_list_deallocator()
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000402 _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000403 : __data_(0) {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000404
405 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000406 __bucket_list_deallocator(const allocator_type& __a, size_type __size)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000407 _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000408 : __data_(__size, __a) {}
409
Howard Hinnant73d21a42010-09-04 23:28:19 +0000410#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000411
Howard Hinnant99acc502010-09-21 17:32:39 +0000412 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000413 __bucket_list_deallocator(__bucket_list_deallocator&& __x)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000414 _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000415 : __data_(_VSTD::move(__x.__data_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000416 {
417 __x.size() = 0;
418 }
419
Howard Hinnant73d21a42010-09-04 23:28:19 +0000420#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000421
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000422 _LIBCPP_INLINE_VISIBILITY
423 size_type& size() _NOEXCEPT {return __data_.first();}
424 _LIBCPP_INLINE_VISIBILITY
425 size_type size() const _NOEXCEPT {return __data_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000426
Howard Hinnant99acc502010-09-21 17:32:39 +0000427 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000428 allocator_type& __alloc() _NOEXCEPT {return __data_.second();}
429 _LIBCPP_INLINE_VISIBILITY
430 const allocator_type& __alloc() const _NOEXCEPT {return __data_.second();}
431
432 _LIBCPP_INLINE_VISIBILITY
433 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000434 {
435 __alloc_traits::deallocate(__alloc(), __p, size());
436 }
437};
438
Howard Hinnant2b1b2d42011-06-14 19:58:17 +0000439template <class _Alloc> class __hash_map_node_destructor;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000440
441template <class _Alloc>
442class __hash_node_destructor
443{
444 typedef _Alloc allocator_type;
445 typedef allocator_traits<allocator_type> __alloc_traits;
446 typedef typename __alloc_traits::value_type::value_type value_type;
447public:
448 typedef typename __alloc_traits::pointer pointer;
449private:
450
451 allocator_type& __na_;
452
453 __hash_node_destructor& operator=(const __hash_node_destructor&);
454
455public:
456 bool __value_constructed;
457
Howard Hinnant99acc502010-09-21 17:32:39 +0000458 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant199d0ae2011-07-31 17:04:30 +0000459 explicit __hash_node_destructor(allocator_type& __na,
460 bool __constructed = false) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000461 : __na_(__na),
Howard Hinnant199d0ae2011-07-31 17:04:30 +0000462 __value_constructed(__constructed)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000463 {}
464
Howard Hinnant99acc502010-09-21 17:32:39 +0000465 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000466 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000467 {
468 if (__value_constructed)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000469 __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000470 if (__p)
471 __alloc_traits::deallocate(__na_, __p, 1);
472 }
473
474 template <class> friend class __hash_map_node_destructor;
475};
476
477template <class _Tp, class _Hash, class _Equal, class _Alloc>
478class __hash_table
479{
480public:
481 typedef _Tp value_type;
482 typedef _Hash hasher;
483 typedef _Equal key_equal;
484 typedef _Alloc allocator_type;
485
486private:
487 typedef allocator_traits<allocator_type> __alloc_traits;
488public:
489 typedef value_type& reference;
490 typedef const value_type& const_reference;
491 typedef typename __alloc_traits::pointer pointer;
492 typedef typename __alloc_traits::const_pointer const_pointer;
493 typedef typename __alloc_traits::size_type size_type;
494 typedef typename __alloc_traits::difference_type difference_type;
495public:
496 // Create __node
497 typedef __hash_node<value_type, typename __alloc_traits::void_pointer> __node;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000498 typedef typename __alloc_traits::template
499#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
500 rebind_alloc<__node>
501#else
502 rebind_alloc<__node>::other
503#endif
504 __node_allocator;
505 typedef allocator_traits<__node_allocator> __node_traits;
506 typedef typename __node_traits::pointer __node_pointer;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000507 typedef typename __node_traits::pointer __node_const_pointer;
Howard Hinnantf8880d02011-12-12 17:26:24 +0000508 typedef __hash_node_base<__node_pointer> __first_node;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000509 typedef typename pointer_traits<__node_pointer>::template
510#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
511 rebind<__first_node>
512#else
513 rebind<__first_node>::other
514#endif
515 __node_base_pointer;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000516
517private:
518
519 typedef typename __node_traits::template
520#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
521 rebind_alloc<__node_pointer>
522#else
523 rebind_alloc<__node_pointer>::other
524#endif
525 __pointer_allocator;
526 typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter;
527 typedef unique_ptr<__node_pointer[], __bucket_list_deleter> __bucket_list;
528 typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits;
529 typedef typename __bucket_list_deleter::pointer __node_pointer_pointer;
530
531 // --- Member data begin ---
532 __bucket_list __bucket_list_;
533 __compressed_pair<__first_node, __node_allocator> __p1_;
534 __compressed_pair<size_type, hasher> __p2_;
535 __compressed_pair<float, key_equal> __p3_;
536 // --- Member data end ---
537
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000538 _LIBCPP_INLINE_VISIBILITY
539 size_type& size() _NOEXCEPT {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000540public:
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000541 _LIBCPP_INLINE_VISIBILITY
542 size_type size() const _NOEXCEPT {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000543
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000544 _LIBCPP_INLINE_VISIBILITY
545 hasher& hash_function() _NOEXCEPT {return __p2_.second();}
546 _LIBCPP_INLINE_VISIBILITY
547 const hasher& hash_function() const _NOEXCEPT {return __p2_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000548
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000549 _LIBCPP_INLINE_VISIBILITY
550 float& max_load_factor() _NOEXCEPT {return __p3_.first();}
551 _LIBCPP_INLINE_VISIBILITY
552 float max_load_factor() const _NOEXCEPT {return __p3_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000553
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000554 _LIBCPP_INLINE_VISIBILITY
555 key_equal& key_eq() _NOEXCEPT {return __p3_.second();}
556 _LIBCPP_INLINE_VISIBILITY
557 const key_equal& key_eq() const _NOEXCEPT {return __p3_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000558
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000559 _LIBCPP_INLINE_VISIBILITY
560 __node_allocator& __node_alloc() _NOEXCEPT {return __p1_.second();}
561 _LIBCPP_INLINE_VISIBILITY
562 const __node_allocator& __node_alloc() const _NOEXCEPT
563 {return __p1_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000564
565public:
566 typedef __hash_iterator<__node_pointer> iterator;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000567 typedef __hash_const_iterator<__node_pointer> const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000568 typedef __hash_local_iterator<__node_pointer> local_iterator;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000569 typedef __hash_const_local_iterator<__node_pointer> const_local_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000570
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000571 __hash_table()
572 _NOEXCEPT_(
573 is_nothrow_default_constructible<__bucket_list>::value &&
574 is_nothrow_default_constructible<__first_node>::value &&
575 is_nothrow_default_constructible<__node_allocator>::value &&
576 is_nothrow_default_constructible<hasher>::value &&
577 is_nothrow_default_constructible<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000578 __hash_table(const hasher& __hf, const key_equal& __eql);
579 __hash_table(const hasher& __hf, const key_equal& __eql,
580 const allocator_type& __a);
581 explicit __hash_table(const allocator_type& __a);
582 __hash_table(const __hash_table& __u);
583 __hash_table(const __hash_table& __u, const allocator_type& __a);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000584#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000585 __hash_table(__hash_table&& __u)
586 _NOEXCEPT_(
587 is_nothrow_move_constructible<__bucket_list>::value &&
588 is_nothrow_move_constructible<__first_node>::value &&
589 is_nothrow_move_constructible<__node_allocator>::value &&
590 is_nothrow_move_constructible<hasher>::value &&
591 is_nothrow_move_constructible<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000592 __hash_table(__hash_table&& __u, const allocator_type& __a);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000593#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000594 ~__hash_table();
595
596 __hash_table& operator=(const __hash_table& __u);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000597#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000598 __hash_table& operator=(__hash_table&& __u)
599 _NOEXCEPT_(
600 __node_traits::propagate_on_container_move_assignment::value &&
601 is_nothrow_move_assignable<__node_allocator>::value &&
602 is_nothrow_move_assignable<hasher>::value &&
603 is_nothrow_move_assignable<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000604#endif
605 template <class _InputIterator>
606 void __assign_unique(_InputIterator __first, _InputIterator __last);
607 template <class _InputIterator>
608 void __assign_multi(_InputIterator __first, _InputIterator __last);
609
Howard Hinnant99acc502010-09-21 17:32:39 +0000610 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000611 size_type max_size() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000612 {
613 return allocator_traits<__pointer_allocator>::max_size(
614 __bucket_list_.get_deleter().__alloc());
615 }
616
617 pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
618 iterator __node_insert_multi(__node_pointer __nd);
619 iterator __node_insert_multi(const_iterator __p,
620 __node_pointer __nd);
621
Howard Hinnant73d21a42010-09-04 23:28:19 +0000622#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000623 template <class... _Args>
624 pair<iterator, bool> __emplace_unique(_Args&&... __args);
625 template <class... _Args>
626 iterator __emplace_multi(_Args&&... __args);
627 template <class... _Args>
628 iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000629#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000630
631 pair<iterator, bool> __insert_unique(const value_type& __x);
632
Howard Hinnant73d21a42010-09-04 23:28:19 +0000633#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant99968442011-11-29 18:15:50 +0000634 template <class _Pp>
635 pair<iterator, bool> __insert_unique(_Pp&& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000636#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000637
Howard Hinnant73d21a42010-09-04 23:28:19 +0000638#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant99968442011-11-29 18:15:50 +0000639 template <class _Pp>
640 iterator __insert_multi(_Pp&& __x);
641 template <class _Pp>
642 iterator __insert_multi(const_iterator __p, _Pp&& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000643#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000644 iterator __insert_multi(const value_type& __x);
645 iterator __insert_multi(const_iterator __p, const value_type& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000646#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000647
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000648 void clear() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000649 void rehash(size_type __n);
Howard Hinnant99acc502010-09-21 17:32:39 +0000650 _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000651 {rehash(static_cast<size_type>(ceil(__n / max_load_factor())));}
Howard Hinnant99acc502010-09-21 17:32:39 +0000652
653 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000654 size_type bucket_count() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000655 {
656 return __bucket_list_.get_deleter().size();
657 }
658
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000659 iterator begin() _NOEXCEPT;
660 iterator end() _NOEXCEPT;
661 const_iterator begin() const _NOEXCEPT;
662 const_iterator end() const _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000663
664 template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39 +0000665 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000666 size_type bucket(const _Key& __k) const
Howard Hinnant7a445152012-07-06 17:31:14 +0000667 {return __constrain_hash(hash_function()(__k), bucket_count());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000668
669 template <class _Key>
670 iterator find(const _Key& __x);
671 template <class _Key>
672 const_iterator find(const _Key& __x) const;
673
Howard Hinnant99968442011-11-29 18:15:50 +0000674 typedef __hash_node_destructor<__node_allocator> _Dp;
675 typedef unique_ptr<__node, _Dp> __node_holder;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000676
677 iterator erase(const_iterator __p);
678 iterator erase(const_iterator __first, const_iterator __last);
679 template <class _Key>
680 size_type __erase_unique(const _Key& __k);
681 template <class _Key>
682 size_type __erase_multi(const _Key& __k);
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000683 __node_holder remove(const_iterator __p) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000684
685 template <class _Key>
686 size_type __count_unique(const _Key& __k) const;
687 template <class _Key>
688 size_type __count_multi(const _Key& __k) const;
689
690 template <class _Key>
691 pair<iterator, iterator>
692 __equal_range_unique(const _Key& __k);
693 template <class _Key>
694 pair<const_iterator, const_iterator>
695 __equal_range_unique(const _Key& __k) const;
696
697 template <class _Key>
698 pair<iterator, iterator>
699 __equal_range_multi(const _Key& __k);
700 template <class _Key>
701 pair<const_iterator, const_iterator>
702 __equal_range_multi(const _Key& __k) const;
703
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000704 void swap(__hash_table& __u)
705 _NOEXCEPT_(
706 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
707 __is_nothrow_swappable<__pointer_allocator>::value) &&
708 (!__node_traits::propagate_on_container_swap::value ||
709 __is_nothrow_swappable<__node_allocator>::value) &&
710 __is_nothrow_swappable<hasher>::value &&
711 __is_nothrow_swappable<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000712
Howard Hinnant99acc502010-09-21 17:32:39 +0000713 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000714 size_type max_bucket_count() const _NOEXCEPT
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000715 {return __pointer_alloc_traits::max_size(__bucket_list_.get_deleter().__alloc());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000716 size_type bucket_size(size_type __n) const;
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000717 _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000718 {
719 size_type __bc = bucket_count();
720 return __bc != 0 ? (float)size() / __bc : 0.f;
721 }
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000722 _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT
Howard Hinnant0949eed2011-06-30 21:18:19 +0000723 {max_load_factor() = _VSTD::max(__mlf, load_factor());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000724
Howard Hinnant99acc502010-09-21 17:32:39 +0000725 _LIBCPP_INLINE_VISIBILITY local_iterator begin(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000726 {return local_iterator(__bucket_list_[__n], __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000727 _LIBCPP_INLINE_VISIBILITY local_iterator end(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000728 {return local_iterator(nullptr, __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000729 _LIBCPP_INLINE_VISIBILITY const_local_iterator cbegin(size_type __n) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000730 {return const_local_iterator(__bucket_list_[__n], __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000731 _LIBCPP_INLINE_VISIBILITY const_local_iterator cend(size_type __n) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000732 {return const_local_iterator(nullptr, __n, bucket_count());}
733private:
734 void __rehash(size_type __n);
735
Howard Hinnant73d21a42010-09-04 23:28:19 +0000736#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
737#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000738 template <class ..._Args>
739 __node_holder __construct_node(_Args&& ...__args);
Howard Hinnantbfd55302010-09-04 23:46:48 +0000740#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000741 __node_holder __construct_node(value_type&& __v, size_t __hash);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000742#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000743 __node_holder __construct_node(const value_type& __v);
744#endif
745 __node_holder __construct_node(const value_type& __v, size_t __hash);
746
Howard Hinnant99acc502010-09-21 17:32:39 +0000747 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000748 void __copy_assign_alloc(const __hash_table& __u)
749 {__copy_assign_alloc(__u, integral_constant<bool,
750 __node_traits::propagate_on_container_copy_assignment::value>());}
751 void __copy_assign_alloc(const __hash_table& __u, true_type);
Howard Hinnant99acc502010-09-21 17:32:39 +0000752 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantec3773c2011-12-01 20:21:04 +0000753 void __copy_assign_alloc(const __hash_table&, false_type) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000754
755 void __move_assign(__hash_table& __u, false_type);
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000756 void __move_assign(__hash_table& __u, true_type)
757 _NOEXCEPT_(
758 is_nothrow_move_assignable<__node_allocator>::value &&
759 is_nothrow_move_assignable<hasher>::value &&
760 is_nothrow_move_assignable<key_equal>::value);
761 _LIBCPP_INLINE_VISIBILITY
762 void __move_assign_alloc(__hash_table& __u)
763 _NOEXCEPT_(
764 !__node_traits::propagate_on_container_move_assignment::value ||
765 (is_nothrow_move_assignable<__pointer_allocator>::value &&
766 is_nothrow_move_assignable<__node_allocator>::value))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000767 {__move_assign_alloc(__u, integral_constant<bool,
768 __node_traits::propagate_on_container_move_assignment::value>());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000769 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000770 void __move_assign_alloc(__hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000771 _NOEXCEPT_(
772 is_nothrow_move_assignable<__pointer_allocator>::value &&
773 is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000774 {
775 __bucket_list_.get_deleter().__alloc() =
Howard Hinnant0949eed2011-06-30 21:18:19 +0000776 _VSTD::move(__u.__bucket_list_.get_deleter().__alloc());
777 __node_alloc() = _VSTD::move(__u.__node_alloc());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000778 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000779 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000780 void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000781
Howard Hinnant99968442011-11-29 18:15:50 +0000782 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:39 +0000783 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000784 static
785 void
Howard Hinnant99968442011-11-29 18:15:50 +0000786 __swap_alloc(_Ap& __x, _Ap& __y)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000787 _NOEXCEPT_(
Howard Hinnant99968442011-11-29 18:15:50 +0000788 !allocator_traits<_Ap>::propagate_on_container_swap::value ||
789 __is_nothrow_swappable<_Ap>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000790 {
791 __swap_alloc(__x, __y,
792 integral_constant<bool,
Howard Hinnant99968442011-11-29 18:15:50 +0000793 allocator_traits<_Ap>::propagate_on_container_swap::value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000794 >());
795 }
796
Howard Hinnant99968442011-11-29 18:15:50 +0000797 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:39 +0000798 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000799 static
800 void
Howard Hinnant99968442011-11-29 18:15:50 +0000801 __swap_alloc(_Ap& __x, _Ap& __y, true_type)
802 _NOEXCEPT_(__is_nothrow_swappable<_Ap>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000803 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000804 using _VSTD::swap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000805 swap(__x, __y);
806 }
807
Howard Hinnant99968442011-11-29 18:15:50 +0000808 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:39 +0000809 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000810 static
811 void
Howard Hinnantec3773c2011-12-01 20:21:04 +0000812 __swap_alloc(_Ap&, _Ap&, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000813
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000814 void __deallocate(__node_pointer __np) _NOEXCEPT;
815 __node_pointer __detach() _NOEXCEPT;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000816
817 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_map;
818 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000819};
820
821template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +0000822inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000823__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table()
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000824 _NOEXCEPT_(
825 is_nothrow_default_constructible<__bucket_list>::value &&
826 is_nothrow_default_constructible<__first_node>::value &&
827 is_nothrow_default_constructible<hasher>::value &&
828 is_nothrow_default_constructible<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000829 : __p2_(0),
830 __p3_(1.0f)
831{
832}
833
834template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +0000835inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000836__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
837 const key_equal& __eql)
838 : __bucket_list_(nullptr, __bucket_list_deleter()),
839 __p1_(),
840 __p2_(0, __hf),
841 __p3_(1.0f, __eql)
842{
843}
844
845template <class _Tp, class _Hash, class _Equal, class _Alloc>
846__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
847 const key_equal& __eql,
848 const allocator_type& __a)
849 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
850 __p1_(__node_allocator(__a)),
851 __p2_(0, __hf),
852 __p3_(1.0f, __eql)
853{
854}
855
856template <class _Tp, class _Hash, class _Equal, class _Alloc>
857__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
858 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
859 __p1_(__node_allocator(__a)),
860 __p2_(0),
861 __p3_(1.0f)
862{
863}
864
865template <class _Tp, class _Hash, class _Equal, class _Alloc>
866__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
867 : __bucket_list_(nullptr,
868 __bucket_list_deleter(allocator_traits<__pointer_allocator>::
869 select_on_container_copy_construction(
870 __u.__bucket_list_.get_deleter().__alloc()), 0)),
871 __p1_(allocator_traits<__node_allocator>::
872 select_on_container_copy_construction(__u.__node_alloc())),
873 __p2_(0, __u.hash_function()),
874 __p3_(__u.__p3_)
875{
876}
877
878template <class _Tp, class _Hash, class _Equal, class _Alloc>
879__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u,
880 const allocator_type& __a)
881 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
882 __p1_(__node_allocator(__a)),
883 __p2_(0, __u.hash_function()),
884 __p3_(__u.__p3_)
885{
886}
887
Howard Hinnant73d21a42010-09-04 23:28:19 +0000888#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000889
890template <class _Tp, class _Hash, class _Equal, class _Alloc>
891__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000892 _NOEXCEPT_(
893 is_nothrow_move_constructible<__bucket_list>::value &&
894 is_nothrow_move_constructible<__first_node>::value &&
895 is_nothrow_move_constructible<hasher>::value &&
896 is_nothrow_move_constructible<key_equal>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000897 : __bucket_list_(_VSTD::move(__u.__bucket_list_)),
898 __p1_(_VSTD::move(__u.__p1_)),
899 __p2_(_VSTD::move(__u.__p2_)),
900 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000901{
902 if (size() > 0)
903 {
Howard Hinnant7a445152012-07-06 17:31:14 +0000904 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000905 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000906 __u.__p1_.first().__next_ = nullptr;
907 __u.size() = 0;
908 }
909}
910
911template <class _Tp, class _Hash, class _Equal, class _Alloc>
912__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u,
913 const allocator_type& __a)
914 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
915 __p1_(__node_allocator(__a)),
Howard Hinnant0949eed2011-06-30 21:18:19 +0000916 __p2_(0, _VSTD::move(__u.hash_function())),
917 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000918{
919 if (__a == allocator_type(__u.__node_alloc()))
920 {
921 __bucket_list_.reset(__u.__bucket_list_.release());
922 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
923 __u.__bucket_list_.get_deleter().size() = 0;
924 if (__u.size() > 0)
925 {
926 __p1_.first().__next_ = __u.__p1_.first().__next_;
927 __u.__p1_.first().__next_ = nullptr;
Howard Hinnant7a445152012-07-06 17:31:14 +0000928 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +0000929 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000930 size() = __u.size();
931 __u.size() = 0;
932 }
933 }
934}
935
Howard Hinnant73d21a42010-09-04 23:28:19 +0000936#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000937
938template <class _Tp, class _Hash, class _Equal, class _Alloc>
939__hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table()
940{
941 __deallocate(__p1_.first().__next_);
942}
943
944template <class _Tp, class _Hash, class _Equal, class _Alloc>
945void
946__hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc(
947 const __hash_table& __u, true_type)
948{
949 if (__node_alloc() != __u.__node_alloc())
950 {
951 clear();
952 __bucket_list_.reset();
953 __bucket_list_.get_deleter().size() = 0;
954 }
955 __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc();
956 __node_alloc() = __u.__node_alloc();
957}
958
959template <class _Tp, class _Hash, class _Equal, class _Alloc>
960__hash_table<_Tp, _Hash, _Equal, _Alloc>&
961__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u)
962{
963 if (this != &__u)
964 {
965 __copy_assign_alloc(__u);
966 hash_function() = __u.hash_function();
967 key_eq() = __u.key_eq();
968 max_load_factor() = __u.max_load_factor();
969 __assign_multi(__u.begin(), __u.end());
970 }
971 return *this;
972}
973
974template <class _Tp, class _Hash, class _Equal, class _Alloc>
975void
976__hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate(__node_pointer __np)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000977 _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000978{
979 __node_allocator& __na = __node_alloc();
980 while (__np != nullptr)
981 {
982 __node_pointer __next = __np->__next_;
Howard Hinnant0949eed2011-06-30 21:18:19 +0000983 __node_traits::destroy(__na, _VSTD::addressof(__np->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000984 __node_traits::deallocate(__na, __np, 1);
985 __np = __next;
986 }
987}
988
989template <class _Tp, class _Hash, class _Equal, class _Alloc>
990typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_pointer
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000991__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000992{
993 size_type __bc = bucket_count();
994 for (size_type __i = 0; __i < __bc; ++__i)
995 __bucket_list_[__i] = nullptr;
996 size() = 0;
997 __node_pointer __cache = __p1_.first().__next_;
998 __p1_.first().__next_ = nullptr;
999 return __cache;
1000}
1001
Howard Hinnant73d21a42010-09-04 23:28:19 +00001002#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001003
1004template <class _Tp, class _Hash, class _Equal, class _Alloc>
1005void
1006__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
1007 __hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001008 _NOEXCEPT_(
1009 is_nothrow_move_assignable<__node_allocator>::value &&
1010 is_nothrow_move_assignable<hasher>::value &&
1011 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001012{
1013 clear();
1014 __bucket_list_.reset(__u.__bucket_list_.release());
1015 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
1016 __u.__bucket_list_.get_deleter().size() = 0;
1017 __move_assign_alloc(__u);
1018 size() = __u.size();
Howard Hinnant0949eed2011-06-30 21:18:19 +00001019 hash_function() = _VSTD::move(__u.hash_function());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001020 max_load_factor() = __u.max_load_factor();
Howard Hinnant0949eed2011-06-30 21:18:19 +00001021 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001022 __p1_.first().__next_ = __u.__p1_.first().__next_;
1023 if (size() > 0)
1024 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001025 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001026 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001027 __u.__p1_.first().__next_ = nullptr;
1028 __u.size() = 0;
1029 }
1030}
1031
1032template <class _Tp, class _Hash, class _Equal, class _Alloc>
1033void
1034__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
1035 __hash_table& __u, false_type)
1036{
1037 if (__node_alloc() == __u.__node_alloc())
1038 __move_assign(__u, true_type());
1039 else
1040 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001041 hash_function() = _VSTD::move(__u.hash_function());
1042 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001043 max_load_factor() = __u.max_load_factor();
1044 if (bucket_count() != 0)
1045 {
1046 __node_pointer __cache = __detach();
1047#ifndef _LIBCPP_NO_EXCEPTIONS
1048 try
1049 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001050#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001051 const_iterator __i = __u.begin();
1052 while (__cache != nullptr && __u.size() != 0)
1053 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001054 __cache->__value_ = _VSTD::move(__u.remove(__i++)->__value_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001055 __node_pointer __next = __cache->__next_;
1056 __node_insert_multi(__cache);
1057 __cache = __next;
1058 }
1059#ifndef _LIBCPP_NO_EXCEPTIONS
1060 }
1061 catch (...)
1062 {
1063 __deallocate(__cache);
1064 throw;
1065 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001066#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001067 __deallocate(__cache);
1068 }
1069 const_iterator __i = __u.begin();
1070 while (__u.size() != 0)
1071 {
1072 __node_holder __h =
Howard Hinnant0949eed2011-06-30 21:18:19 +00001073 __construct_node(_VSTD::move(__u.remove(__i++)->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001074 __node_insert_multi(__h.get());
1075 __h.release();
1076 }
1077 }
1078}
1079
1080template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001081inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001082__hash_table<_Tp, _Hash, _Equal, _Alloc>&
1083__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001084 _NOEXCEPT_(
1085 __node_traits::propagate_on_container_move_assignment::value &&
1086 is_nothrow_move_assignable<__node_allocator>::value &&
1087 is_nothrow_move_assignable<hasher>::value &&
1088 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001089{
1090 __move_assign(__u, integral_constant<bool,
1091 __node_traits::propagate_on_container_move_assignment::value>());
1092 return *this;
1093}
1094
Howard Hinnant73d21a42010-09-04 23:28:19 +00001095#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001096
1097template <class _Tp, class _Hash, class _Equal, class _Alloc>
1098template <class _InputIterator>
1099void
1100__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first,
1101 _InputIterator __last)
1102{
1103 if (bucket_count() != 0)
1104 {
1105 __node_pointer __cache = __detach();
1106#ifndef _LIBCPP_NO_EXCEPTIONS
1107 try
1108 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001109#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001110 for (; __cache != nullptr && __first != __last; ++__first)
1111 {
1112 __cache->__value_ = *__first;
1113 __node_pointer __next = __cache->__next_;
1114 __node_insert_unique(__cache);
1115 __cache = __next;
1116 }
1117#ifndef _LIBCPP_NO_EXCEPTIONS
1118 }
1119 catch (...)
1120 {
1121 __deallocate(__cache);
1122 throw;
1123 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001124#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001125 __deallocate(__cache);
1126 }
1127 for (; __first != __last; ++__first)
1128 __insert_unique(*__first);
1129}
1130
1131template <class _Tp, class _Hash, class _Equal, class _Alloc>
1132template <class _InputIterator>
1133void
1134__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first,
1135 _InputIterator __last)
1136{
1137 if (bucket_count() != 0)
1138 {
1139 __node_pointer __cache = __detach();
1140#ifndef _LIBCPP_NO_EXCEPTIONS
1141 try
1142 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001143#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001144 for (; __cache != nullptr && __first != __last; ++__first)
1145 {
1146 __cache->__value_ = *__first;
1147 __node_pointer __next = __cache->__next_;
1148 __node_insert_multi(__cache);
1149 __cache = __next;
1150 }
1151#ifndef _LIBCPP_NO_EXCEPTIONS
1152 }
1153 catch (...)
1154 {
1155 __deallocate(__cache);
1156 throw;
1157 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001158#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001159 __deallocate(__cache);
1160 }
1161 for (; __first != __last; ++__first)
1162 __insert_multi(*__first);
1163}
1164
1165template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001166inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001167typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001168__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001169{
1170 return iterator(__p1_.first().__next_);
1171}
1172
1173template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001174inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001175typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001176__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001177{
1178 return iterator(nullptr);
1179}
1180
1181template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001182inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001183typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001184__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001185{
1186 return const_iterator(__p1_.first().__next_);
1187}
1188
1189template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001190inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001191typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001192__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001193{
1194 return const_iterator(nullptr);
1195}
1196
1197template <class _Tp, class _Hash, class _Equal, class _Alloc>
1198void
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001199__hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001200{
1201 if (size() > 0)
1202 {
1203 __deallocate(__p1_.first().__next_);
1204 __p1_.first().__next_ = nullptr;
1205 size_type __bc = bucket_count();
Howard Hinnant9f66bff2011-07-05 14:14:17 +00001206 for (size_type __i = 0; __i < __bc; ++__i)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001207 __bucket_list_[__i] = nullptr;
1208 size() = 0;
1209 }
1210}
1211
1212template <class _Tp, class _Hash, class _Equal, class _Alloc>
1213pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1214__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd)
1215{
1216 __nd->__hash_ = hash_function()(__nd->__value_);
1217 size_type __bc = bucket_count();
1218 bool __inserted = false;
1219 __node_pointer __ndptr;
1220 size_t __chash;
1221 if (__bc != 0)
1222 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001223 __chash = __constrain_hash(__nd->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001224 __ndptr = __bucket_list_[__chash];
1225 if (__ndptr != nullptr)
1226 {
1227 for (__ndptr = __ndptr->__next_; __ndptr != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001228 __constrain_hash(__ndptr->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001229 __ndptr = __ndptr->__next_)
1230 {
1231 if (key_eq()(__ndptr->__value_, __nd->__value_))
1232 goto __done;
1233 }
1234 }
1235 }
1236 {
1237 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1238 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001239 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001240 size_type(ceil(float(size() + 1) / max_load_factor()))));
1241 __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:14 +00001242 __chash = __constrain_hash(__nd->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001243 }
1244 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1245 __node_pointer __pn = __bucket_list_[__chash];
1246 if (__pn == nullptr)
1247 {
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001248 __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001249 __nd->__next_ = __pn->__next_;
1250 __pn->__next_ = __nd;
1251 // fix up __bucket_list_
1252 __bucket_list_[__chash] = __pn;
1253 if (__nd->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:14 +00001254 __bucket_list_[__constrain_hash(__nd->__next_->__hash_, __bc)] = __nd;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001255 }
1256 else
1257 {
1258 __nd->__next_ = __pn->__next_;
1259 __pn->__next_ = __nd;
1260 }
1261 __ndptr = __nd;
1262 // increment size
1263 ++size();
1264 __inserted = true;
1265 }
1266__done:
1267 return pair<iterator, bool>(iterator(__ndptr), __inserted);
1268}
1269
1270template <class _Tp, class _Hash, class _Equal, class _Alloc>
1271typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1272__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp)
1273{
1274 __cp->__hash_ = hash_function()(__cp->__value_);
1275 size_type __bc = bucket_count();
1276 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1277 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001278 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001279 size_type(ceil(float(size() + 1) / max_load_factor()))));
1280 __bc = bucket_count();
1281 }
Howard Hinnant7a445152012-07-06 17:31:14 +00001282 size_t __chash = __constrain_hash(__cp->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001283 __node_pointer __pn = __bucket_list_[__chash];
1284 if (__pn == nullptr)
1285 {
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001286 __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001287 __cp->__next_ = __pn->__next_;
1288 __pn->__next_ = __cp;
1289 // fix up __bucket_list_
1290 __bucket_list_[__chash] = __pn;
1291 if (__cp->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:14 +00001292 __bucket_list_[__constrain_hash(__cp->__next_->__hash_, __bc)] = __cp;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001293 }
1294 else
1295 {
1296 for (bool __found = false; __pn->__next_ != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001297 __constrain_hash(__pn->__next_->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001298 __pn = __pn->__next_)
Howard Hinnant324bb032010-08-22 00:02:43 +00001299 {
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001300 // __found key_eq() action
1301 // false false loop
1302 // true true loop
1303 // false true set __found to true
1304 // true false break
1305 if (__found != (__pn->__next_->__hash_ == __cp->__hash_ &&
1306 key_eq()(__pn->__next_->__value_, __cp->__value_)))
1307 {
1308 if (!__found)
1309 __found = true;
1310 else
1311 break;
1312 }
1313 }
1314 __cp->__next_ = __pn->__next_;
1315 __pn->__next_ = __cp;
1316 if (__cp->__next_ != nullptr)
1317 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001318 size_t __nhash = __constrain_hash(__cp->__next_->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001319 if (__nhash != __chash)
1320 __bucket_list_[__nhash] = __cp;
1321 }
1322 }
1323 ++size();
1324 return iterator(__cp);
1325}
1326
1327template <class _Tp, class _Hash, class _Equal, class _Alloc>
1328typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1329__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(
1330 const_iterator __p, __node_pointer __cp)
1331{
1332 if (__p != end() && key_eq()(*__p, __cp->__value_))
1333 {
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001334 __node_pointer __np = __p.__node_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001335 __cp->__hash_ = __np->__hash_;
1336 size_type __bc = bucket_count();
1337 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1338 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001339 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001340 size_type(ceil(float(size() + 1) / max_load_factor()))));
1341 __bc = bucket_count();
1342 }
Howard Hinnant7a445152012-07-06 17:31:14 +00001343 size_t __chash = __constrain_hash(__cp->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001344 __node_pointer __pp = __bucket_list_[__chash];
1345 while (__pp->__next_ != __np)
1346 __pp = __pp->__next_;
1347 __cp->__next_ = __np;
1348 __pp->__next_ = __cp;
1349 ++size();
1350 return iterator(__cp);
1351 }
1352 return __node_insert_multi(__cp);
1353}
1354
1355template <class _Tp, class _Hash, class _Equal, class _Alloc>
1356pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1357__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(const value_type& __x)
1358{
1359 size_t __hash = hash_function()(__x);
1360 size_type __bc = bucket_count();
1361 bool __inserted = false;
1362 __node_pointer __nd;
1363 size_t __chash;
1364 if (__bc != 0)
1365 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001366 __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001367 __nd = __bucket_list_[__chash];
1368 if (__nd != nullptr)
1369 {
1370 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001371 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001372 __nd = __nd->__next_)
1373 {
1374 if (key_eq()(__nd->__value_, __x))
1375 goto __done;
1376 }
1377 }
1378 }
1379 {
1380 __node_holder __h = __construct_node(__x, __hash);
1381 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1382 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001383 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001384 size_type(ceil(float(size() + 1) / max_load_factor()))));
1385 __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:14 +00001386 __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001387 }
1388 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1389 __node_pointer __pn = __bucket_list_[__chash];
1390 if (__pn == nullptr)
1391 {
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001392 __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001393 __h->__next_ = __pn->__next_;
1394 __pn->__next_ = __h.get();
1395 // fix up __bucket_list_
1396 __bucket_list_[__chash] = __pn;
1397 if (__h->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:14 +00001398 __bucket_list_[__constrain_hash(__h->__next_->__hash_, __bc)] = __h.get();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001399 }
1400 else
1401 {
1402 __h->__next_ = __pn->__next_;
1403 __pn->__next_ = __h.get();
1404 }
1405 __nd = __h.release();
1406 // increment size
1407 ++size();
1408 __inserted = true;
1409 }
1410__done:
1411 return pair<iterator, bool>(iterator(__nd), __inserted);
1412}
1413
Howard Hinnant73d21a42010-09-04 23:28:19 +00001414#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1415#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001416
1417template <class _Tp, class _Hash, class _Equal, class _Alloc>
1418template <class... _Args>
1419pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1420__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique(_Args&&... __args)
1421{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001422 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001423 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1424 if (__r.second)
1425 __h.release();
1426 return __r;
1427}
1428
1429template <class _Tp, class _Hash, class _Equal, class _Alloc>
1430template <class... _Args>
1431typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1432__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args)
1433{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001434 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001435 iterator __r = __node_insert_multi(__h.get());
1436 __h.release();
1437 return __r;
1438}
1439
1440template <class _Tp, class _Hash, class _Equal, class _Alloc>
1441template <class... _Args>
1442typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1443__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi(
1444 const_iterator __p, _Args&&... __args)
1445{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001446 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001447 iterator __r = __node_insert_multi(__p, __h.get());
1448 __h.release();
1449 return __r;
1450}
1451
Howard Hinnant73d21a42010-09-04 23:28:19 +00001452#endif // _LIBCPP_HAS_NO_VARIADICS
1453
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001454template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:50 +00001455template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001456pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
Howard Hinnant99968442011-11-29 18:15:50 +00001457__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(_Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001458{
Howard Hinnant99968442011-11-29 18:15:50 +00001459 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001460 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1461 if (__r.second)
1462 __h.release();
1463 return __r;
1464}
1465
Howard Hinnant73d21a42010-09-04 23:28:19 +00001466#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001467
Howard Hinnant73d21a42010-09-04 23:28:19 +00001468#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001469
1470template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:50 +00001471template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001472typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant99968442011-11-29 18:15:50 +00001473__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(_Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001474{
Howard Hinnant99968442011-11-29 18:15:50 +00001475 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001476 iterator __r = __node_insert_multi(__h.get());
1477 __h.release();
1478 return __r;
1479}
1480
1481template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:50 +00001482template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001483typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1484__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
Howard Hinnant99968442011-11-29 18:15:50 +00001485 _Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001486{
Howard Hinnant99968442011-11-29 18:15:50 +00001487 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001488 iterator __r = __node_insert_multi(__p, __h.get());
1489 __h.release();
1490 return __r;
1491}
1492
Howard Hinnant73d21a42010-09-04 23:28:19 +00001493#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001494
1495template <class _Tp, class _Hash, class _Equal, class _Alloc>
1496typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1497__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const value_type& __x)
1498{
1499 __node_holder __h = __construct_node(__x);
1500 iterator __r = __node_insert_multi(__h.get());
1501 __h.release();
1502 return __r;
1503}
1504
1505template <class _Tp, class _Hash, class _Equal, class _Alloc>
1506typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1507__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
1508 const value_type& __x)
1509{
1510 __node_holder __h = __construct_node(__x);
1511 iterator __r = __node_insert_multi(__p, __h.get());
1512 __h.release();
1513 return __r;
1514}
1515
Howard Hinnant73d21a42010-09-04 23:28:19 +00001516#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001517
1518template <class _Tp, class _Hash, class _Equal, class _Alloc>
1519void
1520__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n)
1521{
Howard Hinnant7a445152012-07-06 17:31:14 +00001522 if (__n == 1)
1523 __n = 2;
1524 else if (__n & (__n - 1))
1525 __n = __next_prime(__n);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001526 size_type __bc = bucket_count();
1527 if (__n > __bc)
1528 __rehash(__n);
Howard Hinnant7a445152012-07-06 17:31:14 +00001529 else if (__n < __bc)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001530 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001531 __n = _VSTD::max<size_type>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001532 (
1533 __n,
Howard Hinnant7a445152012-07-06 17:31:14 +00001534 __is_power2(__bc) ? __next_pow2(size_t(ceil(float(size()) / max_load_factor()))) :
1535 __next_prime(size_t(ceil(float(size()) / max_load_factor())))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001536 );
1537 if (__n < __bc)
1538 __rehash(__n);
1539 }
1540}
1541
1542template <class _Tp, class _Hash, class _Equal, class _Alloc>
1543void
1544__hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc)
1545{
1546 __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc();
1547 __bucket_list_.reset(__nbc > 0 ?
1548 __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr);
1549 __bucket_list_.get_deleter().size() = __nbc;
1550 if (__nbc > 0)
1551 {
1552 for (size_type __i = 0; __i < __nbc; ++__i)
1553 __bucket_list_[__i] = nullptr;
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001554 __node_pointer __pp(static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001555 __node_pointer __cp = __pp->__next_;
1556 if (__cp != nullptr)
1557 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001558 size_type __chash = __constrain_hash(__cp->__hash_, __nbc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001559 __bucket_list_[__chash] = __pp;
1560 size_type __phash = __chash;
1561 for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr;
1562 __cp = __pp->__next_)
1563 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001564 __chash = __constrain_hash(__cp->__hash_, __nbc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001565 if (__chash == __phash)
1566 __pp = __cp;
1567 else
1568 {
1569 if (__bucket_list_[__chash] == nullptr)
1570 {
1571 __bucket_list_[__chash] = __pp;
1572 __pp = __cp;
1573 __phash = __chash;
1574 }
1575 else
1576 {
1577 __node_pointer __np = __cp;
1578 for (; __np->__next_ != nullptr &&
1579 key_eq()(__cp->__value_, __np->__next_->__value_);
1580 __np = __np->__next_)
1581 ;
1582 __pp->__next_ = __np->__next_;
1583 __np->__next_ = __bucket_list_[__chash]->__next_;
1584 __bucket_list_[__chash]->__next_ = __cp;
Howard Hinnant324bb032010-08-22 00:02:43 +00001585
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001586 }
1587 }
1588 }
1589 }
1590 }
1591}
1592
1593template <class _Tp, class _Hash, class _Equal, class _Alloc>
1594template <class _Key>
1595typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1596__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k)
1597{
1598 size_t __hash = hash_function()(__k);
1599 size_type __bc = bucket_count();
1600 if (__bc != 0)
1601 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001602 size_t __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001603 __node_pointer __nd = __bucket_list_[__chash];
1604 if (__nd != nullptr)
1605 {
1606 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001607 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001608 __nd = __nd->__next_)
1609 {
1610 if (key_eq()(__nd->__value_, __k))
1611 return iterator(__nd);
1612 }
1613 }
1614 }
1615 return end();
1616}
1617
1618template <class _Tp, class _Hash, class _Equal, class _Alloc>
1619template <class _Key>
1620typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1621__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const
1622{
1623 size_t __hash = hash_function()(__k);
1624 size_type __bc = bucket_count();
1625 if (__bc != 0)
1626 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001627 size_t __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001628 __node_const_pointer __nd = __bucket_list_[__chash];
1629 if (__nd != nullptr)
1630 {
1631 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001632 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001633 __nd = __nd->__next_)
1634 {
1635 if (key_eq()(__nd->__value_, __k))
1636 return const_iterator(__nd);
1637 }
1638 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001639
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001640 }
1641 return end();
1642}
1643
Howard Hinnant73d21a42010-09-04 23:28:19 +00001644#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1645#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001646
1647template <class _Tp, class _Hash, class _Equal, class _Alloc>
1648template <class ..._Args>
1649typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1650__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args)
1651{
1652 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00001653 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001654 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001655 __h.get_deleter().__value_constructed = true;
1656 __h->__hash_ = hash_function()(__h->__value_);
1657 __h->__next_ = nullptr;
1658 return __h;
1659}
1660
Howard Hinnant73d21a42010-09-04 23:28:19 +00001661#endif // _LIBCPP_HAS_NO_VARIADICS
1662
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001663template <class _Tp, class _Hash, class _Equal, class _Alloc>
1664typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1665__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(value_type&& __v,
1666 size_t __hash)
1667{
1668 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00001669 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001670 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::move(__v));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001671 __h.get_deleter().__value_constructed = true;
1672 __h->__hash_ = __hash;
1673 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00001674 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001675}
1676
Howard Hinnant73d21a42010-09-04 23:28:19 +00001677#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001678
1679template <class _Tp, class _Hash, class _Equal, class _Alloc>
1680typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1681__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v)
1682{
1683 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00001684 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001685 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001686 __h.get_deleter().__value_constructed = true;
1687 __h->__hash_ = hash_function()(__h->__value_);
1688 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00001689 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001690}
1691
Howard Hinnant73d21a42010-09-04 23:28:19 +00001692#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001693
1694template <class _Tp, class _Hash, class _Equal, class _Alloc>
1695typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1696__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v,
1697 size_t __hash)
1698{
1699 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00001700 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001701 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001702 __h.get_deleter().__value_constructed = true;
1703 __h->__hash_ = __hash;
1704 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00001705 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001706}
1707
1708template <class _Tp, class _Hash, class _Equal, class _Alloc>
1709typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1710__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p)
1711{
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001712 __node_pointer __np = __p.__node_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001713 iterator __r(__np);
1714 ++__r;
1715 remove(__p);
1716 return __r;
1717}
1718
1719template <class _Tp, class _Hash, class _Equal, class _Alloc>
1720typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1721__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first,
1722 const_iterator __last)
1723{
1724 for (const_iterator __p = __first; __first != __last; __p = __first)
1725 {
1726 ++__first;
1727 erase(__p);
1728 }
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001729 __node_pointer __np = __last.__node_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001730 return iterator (__np);
1731}
1732
1733template <class _Tp, class _Hash, class _Equal, class _Alloc>
1734template <class _Key>
1735typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1736__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k)
1737{
1738 iterator __i = find(__k);
1739 if (__i == end())
1740 return 0;
1741 erase(__i);
1742 return 1;
1743}
1744
1745template <class _Tp, class _Hash, class _Equal, class _Alloc>
1746template <class _Key>
1747typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1748__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k)
1749{
1750 size_type __r = 0;
1751 iterator __i = find(__k);
1752 if (__i != end())
1753 {
1754 iterator __e = end();
1755 do
1756 {
1757 erase(__i++);
1758 ++__r;
1759 } while (__i != __e && key_eq()(*__i, __k));
1760 }
1761 return __r;
1762}
1763
1764template <class _Tp, class _Hash, class _Equal, class _Alloc>
1765typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001766__hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001767{
1768 // current node
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001769 __node_pointer __cn = __p.__node_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001770 size_type __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:14 +00001771 size_t __chash = __constrain_hash(__cn->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001772 // find previous node
1773 __node_pointer __pn = __bucket_list_[__chash];
1774 for (; __pn->__next_ != __cn; __pn = __pn->__next_)
1775 ;
1776 // Fix up __bucket_list_
1777 // if __pn is not in same bucket (before begin is not in same bucket) &&
1778 // if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001779 if (__pn == static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()))
1780 || __constrain_hash(__pn->__hash_, __bc) != __chash)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001781 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001782 if (__cn->__next_ == nullptr || __constrain_hash(__cn->__next_->__hash_, __bc) != __chash)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001783 __bucket_list_[__chash] = nullptr;
1784 }
1785 // if __cn->__next_ is not in same bucket (nullptr is in same bucket)
1786 if (__cn->__next_ != nullptr)
1787 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001788 size_t __nhash = __constrain_hash(__cn->__next_->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001789 if (__nhash != __chash)
1790 __bucket_list_[__nhash] = __pn;
1791 }
1792 // remove __cn
1793 __pn->__next_ = __cn->__next_;
1794 __cn->__next_ = nullptr;
1795 --size();
Howard Hinnant99968442011-11-29 18:15:50 +00001796 return __node_holder(__cn, _Dp(__node_alloc(), true));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001797}
1798
1799template <class _Tp, class _Hash, class _Equal, class _Alloc>
1800template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39 +00001801inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001802typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1803__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const
1804{
1805 return static_cast<size_type>(find(__k) != end());
1806}
1807
1808template <class _Tp, class _Hash, class _Equal, class _Alloc>
1809template <class _Key>
1810typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1811__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const
1812{
1813 size_type __r = 0;
1814 const_iterator __i = find(__k);
1815 if (__i != end())
1816 {
1817 const_iterator __e = end();
1818 do
1819 {
1820 ++__i;
1821 ++__r;
1822 } while (__i != __e && key_eq()(*__i, __k));
1823 }
1824 return __r;
1825}
1826
1827template <class _Tp, class _Hash, class _Equal, class _Alloc>
1828template <class _Key>
1829pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
1830 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1831__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
1832 const _Key& __k)
1833{
1834 iterator __i = find(__k);
1835 iterator __j = __i;
1836 if (__i != end())
1837 ++__j;
1838 return pair<iterator, iterator>(__i, __j);
1839}
1840
1841template <class _Tp, class _Hash, class _Equal, class _Alloc>
1842template <class _Key>
1843pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
1844 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1845__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
1846 const _Key& __k) const
1847{
1848 const_iterator __i = find(__k);
1849 const_iterator __j = __i;
1850 if (__i != end())
1851 ++__j;
1852 return pair<const_iterator, const_iterator>(__i, __j);
1853}
1854
1855template <class _Tp, class _Hash, class _Equal, class _Alloc>
1856template <class _Key>
1857pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
1858 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1859__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
1860 const _Key& __k)
1861{
1862 iterator __i = find(__k);
1863 iterator __j = __i;
1864 if (__i != end())
1865 {
1866 iterator __e = end();
1867 do
1868 {
1869 ++__j;
1870 } while (__j != __e && key_eq()(*__j, __k));
1871 }
1872 return pair<iterator, iterator>(__i, __j);
1873}
1874
1875template <class _Tp, class _Hash, class _Equal, class _Alloc>
1876template <class _Key>
1877pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
1878 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1879__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
1880 const _Key& __k) const
1881{
1882 const_iterator __i = find(__k);
1883 const_iterator __j = __i;
1884 if (__i != end())
1885 {
1886 const_iterator __e = end();
1887 do
1888 {
1889 ++__j;
1890 } while (__j != __e && key_eq()(*__j, __k));
1891 }
1892 return pair<const_iterator, const_iterator>(__i, __j);
1893}
1894
1895template <class _Tp, class _Hash, class _Equal, class _Alloc>
1896void
1897__hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001898 _NOEXCEPT_(
1899 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
1900 __is_nothrow_swappable<__pointer_allocator>::value) &&
1901 (!__node_traits::propagate_on_container_swap::value ||
1902 __is_nothrow_swappable<__node_allocator>::value) &&
1903 __is_nothrow_swappable<hasher>::value &&
1904 __is_nothrow_swappable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001905{
1906 {
1907 __node_pointer_pointer __npp = __bucket_list_.release();
1908 __bucket_list_.reset(__u.__bucket_list_.release());
1909 __u.__bucket_list_.reset(__npp);
1910 }
Howard Hinnant0949eed2011-06-30 21:18:19 +00001911 _VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001912 __swap_alloc(__bucket_list_.get_deleter().__alloc(),
1913 __u.__bucket_list_.get_deleter().__alloc());
1914 __swap_alloc(__node_alloc(), __u.__node_alloc());
Howard Hinnant0949eed2011-06-30 21:18:19 +00001915 _VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001916 __p2_.swap(__u.__p2_);
1917 __p3_.swap(__u.__p3_);
1918 if (size() > 0)
Howard Hinnant7a445152012-07-06 17:31:14 +00001919 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001920 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001921 if (__u.size() > 0)
Howard Hinnant7a445152012-07-06 17:31:14 +00001922 __u.__bucket_list_[__constrain_hash(__u.__p1_.first().__next_->__hash_, __u.bucket_count())] =
Howard Hinnant7a6b7ce2013-06-22 15:21:29 +00001923 static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__u.__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001924}
1925
1926template <class _Tp, class _Hash, class _Equal, class _Alloc>
1927typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1928__hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const
1929{
1930 __node_const_pointer __np = __bucket_list_[__n];
1931 size_type __bc = bucket_count();
1932 size_type __r = 0;
1933 if (__np != nullptr)
1934 {
1935 for (__np = __np->__next_; __np != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001936 __constrain_hash(__np->__hash_, __bc) == __n;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001937 __np = __np->__next_, ++__r)
1938 ;
1939 }
1940 return __r;
1941}
1942
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001943template <class _Tp, class _Hash, class _Equal, class _Alloc>
1944inline _LIBCPP_INLINE_VISIBILITY
1945void
1946swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x,
1947 __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y)
1948 _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
1949{
1950 __x.swap(__y);
1951}
1952
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001953_LIBCPP_END_NAMESPACE_STD
1954
1955#endif // _LIBCPP__HASH_TABLE