blob: 6f6050d33ebb2a7f7334d87bced3327b76040cf1 [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 Hinnantdf85e572011-02-27 18:02:02 +000036 // typedef _NodePtr pointer;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000037
Howard Hinnantdf85e572011-02-27 18:02:02 +000038 _NodePtr __next_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000039
Howard Hinnant5f2f14c2011-06-04 18:54:24 +000040 _LIBCPP_INLINE_VISIBILITY __hash_node_base() _NOEXCEPT : __next_(nullptr) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000041};
42
43template <class _Tp, class _VoidPtr>
44struct __hash_node
45 : public __hash_node_base
46 <
47 typename pointer_traits<_VoidPtr>::template
48#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
49 rebind<__hash_node<_Tp, _VoidPtr> >
50#else
51 rebind<__hash_node<_Tp, _VoidPtr> >::other
52#endif
53 >
54{
55 typedef _Tp value_type;
56
57 size_t __hash_;
58 value_type __value_;
59};
60
Howard Hinnant7a445152012-07-06 17:31:14 +000061inline _LIBCPP_INLINE_VISIBILITY
62bool
63__is_power2(size_t __bc)
64{
65 return __bc > 2 && !(__bc & (__bc - 1));
66}
67
68inline _LIBCPP_INLINE_VISIBILITY
69size_t
70__constrain_hash(size_t __h, size_t __bc)
71{
72 return !(__bc & (__bc - 1)) ? __h & (__bc - 1) : __h % __bc;
73}
74
75inline _LIBCPP_INLINE_VISIBILITY
76size_t
77__next_pow2(size_t __n)
78{
79 return size_t(1) << (std::numeric_limits<size_t>::digits - __clz(__n-1));
80}
81
Howard Hinnant2b1b2d42011-06-14 19:58:17 +000082template <class _Tp, class _Hash, class _Equal, class _Alloc> class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19 +000083template <class _ConstNodePtr> class _LIBCPP_TYPE_VIS __hash_const_iterator;
84template <class _HashIterator> class _LIBCPP_TYPE_VIS __hash_map_iterator;
85template <class _HashIterator> class _LIBCPP_TYPE_VIS __hash_map_const_iterator;
Howard Hinnant2b1b2d42011-06-14 19:58:17 +000086template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
Howard Hinnant83eade62013-03-06 23:30:19 +000087 class _LIBCPP_TYPE_VIS unordered_map;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000088
89template <class _NodePtr>
Howard Hinnant83eade62013-03-06 23:30:19 +000090class _LIBCPP_TYPE_VIS __hash_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000091{
92 typedef _NodePtr __node_pointer;
93
94 __node_pointer __node_;
95
96public:
97 typedef forward_iterator_tag iterator_category;
98 typedef typename pointer_traits<__node_pointer>::element_type::value_type value_type;
99 typedef typename pointer_traits<__node_pointer>::difference_type difference_type;
100 typedef value_type& reference;
101 typedef typename pointer_traits<__node_pointer>::template
102#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
103 rebind<value_type>
104#else
105 rebind<value_type>::other
106#endif
107 pointer;
108
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000109 _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000110
Howard Hinnant99acc502010-09-21 17:32:39 +0000111 _LIBCPP_INLINE_VISIBILITY
112 reference operator*() const {return __node_->__value_;}
113 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant0949eed2011-06-30 21:18:19 +0000114 pointer operator->() const {return _VSTD::addressof(__node_->__value_);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000115
Howard Hinnant99acc502010-09-21 17:32:39 +0000116 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000117 __hash_iterator& operator++()
118 {
119 __node_ = __node_->__next_;
120 return *this;
121 }
122
Howard Hinnant99acc502010-09-21 17:32:39 +0000123 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000124 __hash_iterator operator++(int)
125 {
126 __hash_iterator __t(*this);
127 ++(*this);
128 return __t;
129 }
130
Howard Hinnant99acc502010-09-21 17:32:39 +0000131 friend _LIBCPP_INLINE_VISIBILITY
132 bool operator==(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000133 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000134 friend _LIBCPP_INLINE_VISIBILITY
135 bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000136 {return __x.__node_ != __y.__node_;}
137
138private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000139 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000140 __hash_iterator(__node_pointer __node) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000141 : __node_(__node)
142 {}
143
144 template <class, class, class, class> friend class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19 +0000145 template <class> friend class _LIBCPP_TYPE_VIS __hash_const_iterator;
146 template <class> friend class _LIBCPP_TYPE_VIS __hash_map_iterator;
147 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_map;
148 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000149};
150
151template <class _ConstNodePtr>
Howard Hinnant83eade62013-03-06 23:30:19 +0000152class _LIBCPP_TYPE_VIS __hash_const_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000153{
154 typedef _ConstNodePtr __node_pointer;
155
156 __node_pointer __node_;
157
158 typedef typename remove_const<
159 typename pointer_traits<__node_pointer>::element_type
160 >::type __node;
161
162public:
163 typedef forward_iterator_tag iterator_category;
164 typedef typename __node::value_type value_type;
165 typedef typename pointer_traits<__node_pointer>::difference_type difference_type;
166 typedef const value_type& reference;
167 typedef typename pointer_traits<__node_pointer>::template
168#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
169 rebind<const value_type>
170#else
171 rebind<const value_type>::other
172#endif
173 pointer;
174 typedef typename pointer_traits<__node_pointer>::template
175#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
176 rebind<__node>
177#else
178 rebind<__node>::other
179#endif
180 __non_const_node_pointer;
181 typedef __hash_iterator<__non_const_node_pointer> __non_const_iterator;
182
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000183 _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000184 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000185 __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000186 : __node_(__x.__node_)
187 {}
188
Howard Hinnant99acc502010-09-21 17:32:39 +0000189 _LIBCPP_INLINE_VISIBILITY
190 reference operator*() const {return __node_->__value_;}
191 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant0949eed2011-06-30 21:18:19 +0000192 pointer operator->() const {return _VSTD::addressof(__node_->__value_);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000193
Howard Hinnant99acc502010-09-21 17:32:39 +0000194 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000195 __hash_const_iterator& operator++()
196 {
197 __node_ = __node_->__next_;
198 return *this;
199 }
200
Howard Hinnant99acc502010-09-21 17:32:39 +0000201 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000202 __hash_const_iterator operator++(int)
203 {
204 __hash_const_iterator __t(*this);
205 ++(*this);
206 return __t;
207 }
208
Howard Hinnant99acc502010-09-21 17:32:39 +0000209 friend _LIBCPP_INLINE_VISIBILITY
210 bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000211 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000212 friend _LIBCPP_INLINE_VISIBILITY
213 bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000214 {return __x.__node_ != __y.__node_;}
215
216private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000217 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000218 __hash_const_iterator(__node_pointer __node) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000219 : __node_(__node)
220 {}
221
222 template <class, class, class, class> friend class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19 +0000223 template <class> friend class _LIBCPP_TYPE_VIS __hash_map_const_iterator;
224 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_map;
225 template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000226};
227
Howard Hinnant83eade62013-03-06 23:30:19 +0000228template <class _ConstNodePtr> class _LIBCPP_TYPE_VIS __hash_const_local_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000229
230template <class _NodePtr>
Howard Hinnant83eade62013-03-06 23:30:19 +0000231class _LIBCPP_TYPE_VIS __hash_local_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000232{
233 typedef _NodePtr __node_pointer;
234
235 __node_pointer __node_;
236 size_t __bucket_;
237 size_t __bucket_count_;
238
239 typedef pointer_traits<__node_pointer> __pointer_traits;
240public:
241 typedef forward_iterator_tag iterator_category;
242 typedef typename __pointer_traits::element_type::value_type value_type;
243 typedef typename __pointer_traits::difference_type difference_type;
244 typedef value_type& reference;
245 typedef typename __pointer_traits::template
246#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
247 rebind<value_type>
248#else
249 rebind<value_type>::other
250#endif
251 pointer;
252
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000253 _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000254
Howard Hinnant99acc502010-09-21 17:32:39 +0000255 _LIBCPP_INLINE_VISIBILITY
256 reference operator*() const {return __node_->__value_;}
257 _LIBCPP_INLINE_VISIBILITY
258 pointer operator->() const {return &__node_->__value_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000259
Howard Hinnant99acc502010-09-21 17:32:39 +0000260 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000261 __hash_local_iterator& operator++()
262 {
263 __node_ = __node_->__next_;
Howard Hinnant7a445152012-07-06 17:31:14 +0000264 if (__node_ != nullptr && __constrain_hash(__node_->__hash_, __bucket_count_) != __bucket_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000265 __node_ = nullptr;
266 return *this;
267 }
268
Howard Hinnant99acc502010-09-21 17:32:39 +0000269 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000270 __hash_local_iterator operator++(int)
271 {
272 __hash_local_iterator __t(*this);
273 ++(*this);
274 return __t;
275 }
276
Howard Hinnant99acc502010-09-21 17:32:39 +0000277 friend _LIBCPP_INLINE_VISIBILITY
278 bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000279 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000280 friend _LIBCPP_INLINE_VISIBILITY
281 bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000282 {return __x.__node_ != __y.__node_;}
283
284private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000285 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000286 __hash_local_iterator(__node_pointer __node, size_t __bucket,
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000287 size_t __bucket_count) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000288 : __node_(__node),
289 __bucket_(__bucket),
290 __bucket_count_(__bucket_count)
291 {
292 if (__node_ != nullptr)
293 __node_ = __node_->__next_;
294 }
295
296 template <class, class, class, class> friend class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19 +0000297 template <class> friend class _LIBCPP_TYPE_VIS __hash_const_local_iterator;
298 template <class> friend class _LIBCPP_TYPE_VIS __hash_map_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000299};
300
301template <class _ConstNodePtr>
Howard Hinnant83eade62013-03-06 23:30:19 +0000302class _LIBCPP_TYPE_VIS __hash_const_local_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000303{
304 typedef _ConstNodePtr __node_pointer;
305
306 __node_pointer __node_;
307 size_t __bucket_;
308 size_t __bucket_count_;
309
310 typedef pointer_traits<__node_pointer> __pointer_traits;
311 typedef typename __pointer_traits::element_type __node;
312 typedef typename remove_const<__node>::type __non_const_node;
313 typedef typename pointer_traits<__node_pointer>::template
314#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
315 rebind<__non_const_node>
316#else
317 rebind<__non_const_node>::other
318#endif
319 __non_const_node_pointer;
320 typedef __hash_local_iterator<__non_const_node_pointer>
321 __non_const_iterator;
322public:
323 typedef forward_iterator_tag iterator_category;
324 typedef typename remove_const<
325 typename __pointer_traits::element_type::value_type
326 >::type value_type;
327 typedef typename __pointer_traits::difference_type difference_type;
328 typedef const value_type& reference;
329 typedef typename __pointer_traits::template
330#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
331 rebind<const value_type>
332#else
333 rebind<const value_type>::other
334#endif
335 pointer;
336
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000337 _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000338 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000339 __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000340 : __node_(__x.__node_),
341 __bucket_(__x.__bucket_),
342 __bucket_count_(__x.__bucket_count_)
343 {}
344
Howard Hinnant99acc502010-09-21 17:32:39 +0000345 _LIBCPP_INLINE_VISIBILITY
346 reference operator*() const {return __node_->__value_;}
347 _LIBCPP_INLINE_VISIBILITY
348 pointer operator->() const {return &__node_->__value_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000349
Howard Hinnant99acc502010-09-21 17:32:39 +0000350 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000351 __hash_const_local_iterator& operator++()
352 {
353 __node_ = __node_->__next_;
Howard Hinnant7a445152012-07-06 17:31:14 +0000354 if (__node_ != nullptr && __constrain_hash(__node_->__hash_, __bucket_count_) != __bucket_)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000355 __node_ = nullptr;
356 return *this;
357 }
358
Howard Hinnant99acc502010-09-21 17:32:39 +0000359 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000360 __hash_const_local_iterator operator++(int)
361 {
362 __hash_const_local_iterator __t(*this);
363 ++(*this);
364 return __t;
365 }
366
Howard Hinnant99acc502010-09-21 17:32:39 +0000367 friend _LIBCPP_INLINE_VISIBILITY
368 bool operator==(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000369 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000370 friend _LIBCPP_INLINE_VISIBILITY
371 bool operator!=(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000372 {return __x.__node_ != __y.__node_;}
373
374private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000375 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000376 __hash_const_local_iterator(__node_pointer __node, size_t __bucket,
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000377 size_t __bucket_count) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000378 : __node_(__node),
379 __bucket_(__bucket),
380 __bucket_count_(__bucket_count)
381 {
382 if (__node_ != nullptr)
383 __node_ = __node_->__next_;
384 }
385
386 template <class, class, class, class> friend class __hash_table;
Howard Hinnant83eade62013-03-06 23:30:19 +0000387 template <class> friend class _LIBCPP_TYPE_VIS __hash_map_const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000388};
389
390template <class _Alloc>
391class __bucket_list_deallocator
392{
393 typedef _Alloc allocator_type;
394 typedef allocator_traits<allocator_type> __alloc_traits;
395 typedef typename __alloc_traits::size_type size_type;
396
397 __compressed_pair<size_type, allocator_type> __data_;
398public:
399 typedef typename __alloc_traits::pointer pointer;
400
Howard Hinnant99acc502010-09-21 17:32:39 +0000401 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000402 __bucket_list_deallocator()
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000403 _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000404 : __data_(0) {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000405
406 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000407 __bucket_list_deallocator(const allocator_type& __a, size_type __size)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000408 _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000409 : __data_(__size, __a) {}
410
Howard Hinnant73d21a42010-09-04 23:28:19 +0000411#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000412
Howard Hinnant99acc502010-09-21 17:32:39 +0000413 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000414 __bucket_list_deallocator(__bucket_list_deallocator&& __x)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000415 _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000416 : __data_(_VSTD::move(__x.__data_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000417 {
418 __x.size() = 0;
419 }
420
Howard Hinnant73d21a42010-09-04 23:28:19 +0000421#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000422
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000423 _LIBCPP_INLINE_VISIBILITY
424 size_type& size() _NOEXCEPT {return __data_.first();}
425 _LIBCPP_INLINE_VISIBILITY
426 size_type size() const _NOEXCEPT {return __data_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000427
Howard Hinnant99acc502010-09-21 17:32:39 +0000428 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000429 allocator_type& __alloc() _NOEXCEPT {return __data_.second();}
430 _LIBCPP_INLINE_VISIBILITY
431 const allocator_type& __alloc() const _NOEXCEPT {return __data_.second();}
432
433 _LIBCPP_INLINE_VISIBILITY
434 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000435 {
436 __alloc_traits::deallocate(__alloc(), __p, size());
437 }
438};
439
Howard Hinnant2b1b2d42011-06-14 19:58:17 +0000440template <class _Alloc> class __hash_map_node_destructor;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000441
442template <class _Alloc>
443class __hash_node_destructor
444{
445 typedef _Alloc allocator_type;
446 typedef allocator_traits<allocator_type> __alloc_traits;
447 typedef typename __alloc_traits::value_type::value_type value_type;
448public:
449 typedef typename __alloc_traits::pointer pointer;
450private:
451
452 allocator_type& __na_;
453
454 __hash_node_destructor& operator=(const __hash_node_destructor&);
455
456public:
457 bool __value_constructed;
458
Howard Hinnant99acc502010-09-21 17:32:39 +0000459 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant199d0ae2011-07-31 17:04:30 +0000460 explicit __hash_node_destructor(allocator_type& __na,
461 bool __constructed = false) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000462 : __na_(__na),
Howard Hinnant199d0ae2011-07-31 17:04:30 +0000463 __value_constructed(__constructed)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000464 {}
465
Howard Hinnant99acc502010-09-21 17:32:39 +0000466 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000467 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000468 {
469 if (__value_constructed)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000470 __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000471 if (__p)
472 __alloc_traits::deallocate(__na_, __p, 1);
473 }
474
475 template <class> friend class __hash_map_node_destructor;
476};
477
478template <class _Tp, class _Hash, class _Equal, class _Alloc>
479class __hash_table
480{
481public:
482 typedef _Tp value_type;
483 typedef _Hash hasher;
484 typedef _Equal key_equal;
485 typedef _Alloc allocator_type;
486
487private:
488 typedef allocator_traits<allocator_type> __alloc_traits;
489public:
490 typedef value_type& reference;
491 typedef const value_type& const_reference;
492 typedef typename __alloc_traits::pointer pointer;
493 typedef typename __alloc_traits::const_pointer const_pointer;
494 typedef typename __alloc_traits::size_type size_type;
495 typedef typename __alloc_traits::difference_type difference_type;
496public:
497 // Create __node
498 typedef __hash_node<value_type, typename __alloc_traits::void_pointer> __node;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000499 typedef typename __alloc_traits::template
500#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
501 rebind_alloc<__node>
502#else
503 rebind_alloc<__node>::other
504#endif
505 __node_allocator;
506 typedef allocator_traits<__node_allocator> __node_traits;
507 typedef typename __node_traits::pointer __node_pointer;
508 typedef typename __node_traits::const_pointer __node_const_pointer;
Howard Hinnantf8880d02011-12-12 17:26:24 +0000509 typedef __hash_node_base<__node_pointer> __first_node;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000510
511private:
512
513 typedef typename __node_traits::template
514#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
515 rebind_alloc<__node_pointer>
516#else
517 rebind_alloc<__node_pointer>::other
518#endif
519 __pointer_allocator;
520 typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter;
521 typedef unique_ptr<__node_pointer[], __bucket_list_deleter> __bucket_list;
522 typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits;
523 typedef typename __bucket_list_deleter::pointer __node_pointer_pointer;
524
525 // --- Member data begin ---
526 __bucket_list __bucket_list_;
527 __compressed_pair<__first_node, __node_allocator> __p1_;
528 __compressed_pair<size_type, hasher> __p2_;
529 __compressed_pair<float, key_equal> __p3_;
530 // --- Member data end ---
531
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000532 _LIBCPP_INLINE_VISIBILITY
533 size_type& size() _NOEXCEPT {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000534public:
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000535 _LIBCPP_INLINE_VISIBILITY
536 size_type size() const _NOEXCEPT {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000537
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000538 _LIBCPP_INLINE_VISIBILITY
539 hasher& hash_function() _NOEXCEPT {return __p2_.second();}
540 _LIBCPP_INLINE_VISIBILITY
541 const hasher& hash_function() const _NOEXCEPT {return __p2_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000542
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000543 _LIBCPP_INLINE_VISIBILITY
544 float& max_load_factor() _NOEXCEPT {return __p3_.first();}
545 _LIBCPP_INLINE_VISIBILITY
546 float max_load_factor() const _NOEXCEPT {return __p3_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000547
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000548 _LIBCPP_INLINE_VISIBILITY
549 key_equal& key_eq() _NOEXCEPT {return __p3_.second();}
550 _LIBCPP_INLINE_VISIBILITY
551 const key_equal& key_eq() const _NOEXCEPT {return __p3_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000552
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000553 _LIBCPP_INLINE_VISIBILITY
554 __node_allocator& __node_alloc() _NOEXCEPT {return __p1_.second();}
555 _LIBCPP_INLINE_VISIBILITY
556 const __node_allocator& __node_alloc() const _NOEXCEPT
557 {return __p1_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000558
559public:
560 typedef __hash_iterator<__node_pointer> iterator;
561 typedef __hash_const_iterator<__node_const_pointer> const_iterator;
562 typedef __hash_local_iterator<__node_pointer> local_iterator;
563 typedef __hash_const_local_iterator<__node_const_pointer> const_local_iterator;
564
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000565 __hash_table()
566 _NOEXCEPT_(
567 is_nothrow_default_constructible<__bucket_list>::value &&
568 is_nothrow_default_constructible<__first_node>::value &&
569 is_nothrow_default_constructible<__node_allocator>::value &&
570 is_nothrow_default_constructible<hasher>::value &&
571 is_nothrow_default_constructible<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000572 __hash_table(const hasher& __hf, const key_equal& __eql);
573 __hash_table(const hasher& __hf, const key_equal& __eql,
574 const allocator_type& __a);
575 explicit __hash_table(const allocator_type& __a);
576 __hash_table(const __hash_table& __u);
577 __hash_table(const __hash_table& __u, const allocator_type& __a);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000578#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000579 __hash_table(__hash_table&& __u)
580 _NOEXCEPT_(
581 is_nothrow_move_constructible<__bucket_list>::value &&
582 is_nothrow_move_constructible<__first_node>::value &&
583 is_nothrow_move_constructible<__node_allocator>::value &&
584 is_nothrow_move_constructible<hasher>::value &&
585 is_nothrow_move_constructible<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000586 __hash_table(__hash_table&& __u, const allocator_type& __a);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000587#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000588 ~__hash_table();
589
590 __hash_table& operator=(const __hash_table& __u);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000591#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000592 __hash_table& operator=(__hash_table&& __u)
593 _NOEXCEPT_(
594 __node_traits::propagate_on_container_move_assignment::value &&
595 is_nothrow_move_assignable<__node_allocator>::value &&
596 is_nothrow_move_assignable<hasher>::value &&
597 is_nothrow_move_assignable<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000598#endif
599 template <class _InputIterator>
600 void __assign_unique(_InputIterator __first, _InputIterator __last);
601 template <class _InputIterator>
602 void __assign_multi(_InputIterator __first, _InputIterator __last);
603
Howard Hinnant99acc502010-09-21 17:32:39 +0000604 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000605 size_type max_size() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000606 {
607 return allocator_traits<__pointer_allocator>::max_size(
608 __bucket_list_.get_deleter().__alloc());
609 }
610
611 pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
612 iterator __node_insert_multi(__node_pointer __nd);
613 iterator __node_insert_multi(const_iterator __p,
614 __node_pointer __nd);
615
Howard Hinnant73d21a42010-09-04 23:28:19 +0000616#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000617 template <class... _Args>
618 pair<iterator, bool> __emplace_unique(_Args&&... __args);
619 template <class... _Args>
620 iterator __emplace_multi(_Args&&... __args);
621 template <class... _Args>
622 iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000623#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000624
625 pair<iterator, bool> __insert_unique(const value_type& __x);
626
Howard Hinnant73d21a42010-09-04 23:28:19 +0000627#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant99968442011-11-29 18:15:50 +0000628 template <class _Pp>
629 pair<iterator, bool> __insert_unique(_Pp&& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000630#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000631
Howard Hinnant73d21a42010-09-04 23:28:19 +0000632#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant99968442011-11-29 18:15:50 +0000633 template <class _Pp>
634 iterator __insert_multi(_Pp&& __x);
635 template <class _Pp>
636 iterator __insert_multi(const_iterator __p, _Pp&& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000637#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000638 iterator __insert_multi(const value_type& __x);
639 iterator __insert_multi(const_iterator __p, const value_type& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000640#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000641
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000642 void clear() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000643 void rehash(size_type __n);
Howard Hinnant99acc502010-09-21 17:32:39 +0000644 _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000645 {rehash(static_cast<size_type>(ceil(__n / max_load_factor())));}
Howard Hinnant99acc502010-09-21 17:32:39 +0000646
647 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000648 size_type bucket_count() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000649 {
650 return __bucket_list_.get_deleter().size();
651 }
652
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000653 iterator begin() _NOEXCEPT;
654 iterator end() _NOEXCEPT;
655 const_iterator begin() const _NOEXCEPT;
656 const_iterator end() const _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000657
658 template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39 +0000659 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000660 size_type bucket(const _Key& __k) const
Howard Hinnant7a445152012-07-06 17:31:14 +0000661 {return __constrain_hash(hash_function()(__k), bucket_count());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000662
663 template <class _Key>
664 iterator find(const _Key& __x);
665 template <class _Key>
666 const_iterator find(const _Key& __x) const;
667
Howard Hinnant99968442011-11-29 18:15:50 +0000668 typedef __hash_node_destructor<__node_allocator> _Dp;
669 typedef unique_ptr<__node, _Dp> __node_holder;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000670
671 iterator erase(const_iterator __p);
672 iterator erase(const_iterator __first, const_iterator __last);
673 template <class _Key>
674 size_type __erase_unique(const _Key& __k);
675 template <class _Key>
676 size_type __erase_multi(const _Key& __k);
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000677 __node_holder remove(const_iterator __p) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000678
679 template <class _Key>
680 size_type __count_unique(const _Key& __k) const;
681 template <class _Key>
682 size_type __count_multi(const _Key& __k) const;
683
684 template <class _Key>
685 pair<iterator, iterator>
686 __equal_range_unique(const _Key& __k);
687 template <class _Key>
688 pair<const_iterator, const_iterator>
689 __equal_range_unique(const _Key& __k) const;
690
691 template <class _Key>
692 pair<iterator, iterator>
693 __equal_range_multi(const _Key& __k);
694 template <class _Key>
695 pair<const_iterator, const_iterator>
696 __equal_range_multi(const _Key& __k) const;
697
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000698 void swap(__hash_table& __u)
699 _NOEXCEPT_(
700 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
701 __is_nothrow_swappable<__pointer_allocator>::value) &&
702 (!__node_traits::propagate_on_container_swap::value ||
703 __is_nothrow_swappable<__node_allocator>::value) &&
704 __is_nothrow_swappable<hasher>::value &&
705 __is_nothrow_swappable<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000706
Howard Hinnant99acc502010-09-21 17:32:39 +0000707 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000708 size_type max_bucket_count() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000709 {return __bucket_list_.get_deleter().__alloc().max_size();}
710 size_type bucket_size(size_type __n) const;
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000711 _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000712 {
713 size_type __bc = bucket_count();
714 return __bc != 0 ? (float)size() / __bc : 0.f;
715 }
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000716 _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT
Howard Hinnant0949eed2011-06-30 21:18:19 +0000717 {max_load_factor() = _VSTD::max(__mlf, load_factor());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000718
Howard Hinnant99acc502010-09-21 17:32:39 +0000719 _LIBCPP_INLINE_VISIBILITY local_iterator begin(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000720 {return local_iterator(__bucket_list_[__n], __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000721 _LIBCPP_INLINE_VISIBILITY local_iterator end(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000722 {return local_iterator(nullptr, __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000723 _LIBCPP_INLINE_VISIBILITY const_local_iterator cbegin(size_type __n) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000724 {return const_local_iterator(__bucket_list_[__n], __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000725 _LIBCPP_INLINE_VISIBILITY const_local_iterator cend(size_type __n) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000726 {return const_local_iterator(nullptr, __n, bucket_count());}
727private:
728 void __rehash(size_type __n);
729
Howard Hinnant73d21a42010-09-04 23:28:19 +0000730#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
731#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000732 template <class ..._Args>
733 __node_holder __construct_node(_Args&& ...__args);
Howard Hinnantbfd55302010-09-04 23:46:48 +0000734#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000735 __node_holder __construct_node(value_type&& __v, size_t __hash);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000736#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000737 __node_holder __construct_node(const value_type& __v);
738#endif
739 __node_holder __construct_node(const value_type& __v, size_t __hash);
740
Howard Hinnant99acc502010-09-21 17:32:39 +0000741 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000742 void __copy_assign_alloc(const __hash_table& __u)
743 {__copy_assign_alloc(__u, integral_constant<bool,
744 __node_traits::propagate_on_container_copy_assignment::value>());}
745 void __copy_assign_alloc(const __hash_table& __u, true_type);
Howard Hinnant99acc502010-09-21 17:32:39 +0000746 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantec3773c2011-12-01 20:21:04 +0000747 void __copy_assign_alloc(const __hash_table&, false_type) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000748
749 void __move_assign(__hash_table& __u, false_type);
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000750 void __move_assign(__hash_table& __u, true_type)
751 _NOEXCEPT_(
752 is_nothrow_move_assignable<__node_allocator>::value &&
753 is_nothrow_move_assignable<hasher>::value &&
754 is_nothrow_move_assignable<key_equal>::value);
755 _LIBCPP_INLINE_VISIBILITY
756 void __move_assign_alloc(__hash_table& __u)
757 _NOEXCEPT_(
758 !__node_traits::propagate_on_container_move_assignment::value ||
759 (is_nothrow_move_assignable<__pointer_allocator>::value &&
760 is_nothrow_move_assignable<__node_allocator>::value))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000761 {__move_assign_alloc(__u, integral_constant<bool,
762 __node_traits::propagate_on_container_move_assignment::value>());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000763 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000764 void __move_assign_alloc(__hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000765 _NOEXCEPT_(
766 is_nothrow_move_assignable<__pointer_allocator>::value &&
767 is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000768 {
769 __bucket_list_.get_deleter().__alloc() =
Howard Hinnant0949eed2011-06-30 21:18:19 +0000770 _VSTD::move(__u.__bucket_list_.get_deleter().__alloc());
771 __node_alloc() = _VSTD::move(__u.__node_alloc());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000772 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000773 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000774 void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000775
Howard Hinnant99968442011-11-29 18:15:50 +0000776 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:39 +0000777 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000778 static
779 void
Howard Hinnant99968442011-11-29 18:15:50 +0000780 __swap_alloc(_Ap& __x, _Ap& __y)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000781 _NOEXCEPT_(
Howard Hinnant99968442011-11-29 18:15:50 +0000782 !allocator_traits<_Ap>::propagate_on_container_swap::value ||
783 __is_nothrow_swappable<_Ap>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000784 {
785 __swap_alloc(__x, __y,
786 integral_constant<bool,
Howard Hinnant99968442011-11-29 18:15:50 +0000787 allocator_traits<_Ap>::propagate_on_container_swap::value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000788 >());
789 }
790
Howard Hinnant99968442011-11-29 18:15:50 +0000791 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:39 +0000792 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000793 static
794 void
Howard Hinnant99968442011-11-29 18:15:50 +0000795 __swap_alloc(_Ap& __x, _Ap& __y, true_type)
796 _NOEXCEPT_(__is_nothrow_swappable<_Ap>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000797 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000798 using _VSTD::swap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000799 swap(__x, __y);
800 }
801
Howard Hinnant99968442011-11-29 18:15:50 +0000802 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:39 +0000803 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000804 static
805 void
Howard Hinnantec3773c2011-12-01 20:21:04 +0000806 __swap_alloc(_Ap&, _Ap&, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000807
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000808 void __deallocate(__node_pointer __np) _NOEXCEPT;
809 __node_pointer __detach() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000810};
811
812template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +0000813inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000814__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table()
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000815 _NOEXCEPT_(
816 is_nothrow_default_constructible<__bucket_list>::value &&
817 is_nothrow_default_constructible<__first_node>::value &&
818 is_nothrow_default_constructible<hasher>::value &&
819 is_nothrow_default_constructible<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000820 : __p2_(0),
821 __p3_(1.0f)
822{
823}
824
825template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +0000826inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000827__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
828 const key_equal& __eql)
829 : __bucket_list_(nullptr, __bucket_list_deleter()),
830 __p1_(),
831 __p2_(0, __hf),
832 __p3_(1.0f, __eql)
833{
834}
835
836template <class _Tp, class _Hash, class _Equal, class _Alloc>
837__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
838 const key_equal& __eql,
839 const allocator_type& __a)
840 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
841 __p1_(__node_allocator(__a)),
842 __p2_(0, __hf),
843 __p3_(1.0f, __eql)
844{
845}
846
847template <class _Tp, class _Hash, class _Equal, class _Alloc>
848__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
849 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
850 __p1_(__node_allocator(__a)),
851 __p2_(0),
852 __p3_(1.0f)
853{
854}
855
856template <class _Tp, class _Hash, class _Equal, class _Alloc>
857__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
858 : __bucket_list_(nullptr,
859 __bucket_list_deleter(allocator_traits<__pointer_allocator>::
860 select_on_container_copy_construction(
861 __u.__bucket_list_.get_deleter().__alloc()), 0)),
862 __p1_(allocator_traits<__node_allocator>::
863 select_on_container_copy_construction(__u.__node_alloc())),
864 __p2_(0, __u.hash_function()),
865 __p3_(__u.__p3_)
866{
867}
868
869template <class _Tp, class _Hash, class _Equal, class _Alloc>
870__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u,
871 const allocator_type& __a)
872 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
873 __p1_(__node_allocator(__a)),
874 __p2_(0, __u.hash_function()),
875 __p3_(__u.__p3_)
876{
877}
878
Howard Hinnant73d21a42010-09-04 23:28:19 +0000879#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000880
881template <class _Tp, class _Hash, class _Equal, class _Alloc>
882__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000883 _NOEXCEPT_(
884 is_nothrow_move_constructible<__bucket_list>::value &&
885 is_nothrow_move_constructible<__first_node>::value &&
886 is_nothrow_move_constructible<hasher>::value &&
887 is_nothrow_move_constructible<key_equal>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000888 : __bucket_list_(_VSTD::move(__u.__bucket_list_)),
889 __p1_(_VSTD::move(__u.__p1_)),
890 __p2_(_VSTD::move(__u.__p2_)),
891 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000892{
893 if (size() > 0)
894 {
Howard Hinnant7a445152012-07-06 17:31:14 +0000895 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant0949eed2011-06-30 21:18:19 +0000896 static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000897 __u.__p1_.first().__next_ = nullptr;
898 __u.size() = 0;
899 }
900}
901
902template <class _Tp, class _Hash, class _Equal, class _Alloc>
903__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u,
904 const allocator_type& __a)
905 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
906 __p1_(__node_allocator(__a)),
Howard Hinnant0949eed2011-06-30 21:18:19 +0000907 __p2_(0, _VSTD::move(__u.hash_function())),
908 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000909{
910 if (__a == allocator_type(__u.__node_alloc()))
911 {
912 __bucket_list_.reset(__u.__bucket_list_.release());
913 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
914 __u.__bucket_list_.get_deleter().size() = 0;
915 if (__u.size() > 0)
916 {
917 __p1_.first().__next_ = __u.__p1_.first().__next_;
918 __u.__p1_.first().__next_ = nullptr;
Howard Hinnant7a445152012-07-06 17:31:14 +0000919 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant0949eed2011-06-30 21:18:19 +0000920 static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000921 size() = __u.size();
922 __u.size() = 0;
923 }
924 }
925}
926
Howard Hinnant73d21a42010-09-04 23:28:19 +0000927#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000928
929template <class _Tp, class _Hash, class _Equal, class _Alloc>
930__hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table()
931{
932 __deallocate(__p1_.first().__next_);
933}
934
935template <class _Tp, class _Hash, class _Equal, class _Alloc>
936void
937__hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc(
938 const __hash_table& __u, true_type)
939{
940 if (__node_alloc() != __u.__node_alloc())
941 {
942 clear();
943 __bucket_list_.reset();
944 __bucket_list_.get_deleter().size() = 0;
945 }
946 __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc();
947 __node_alloc() = __u.__node_alloc();
948}
949
950template <class _Tp, class _Hash, class _Equal, class _Alloc>
951__hash_table<_Tp, _Hash, _Equal, _Alloc>&
952__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u)
953{
954 if (this != &__u)
955 {
956 __copy_assign_alloc(__u);
957 hash_function() = __u.hash_function();
958 key_eq() = __u.key_eq();
959 max_load_factor() = __u.max_load_factor();
960 __assign_multi(__u.begin(), __u.end());
961 }
962 return *this;
963}
964
965template <class _Tp, class _Hash, class _Equal, class _Alloc>
966void
967__hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate(__node_pointer __np)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000968 _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000969{
970 __node_allocator& __na = __node_alloc();
971 while (__np != nullptr)
972 {
973 __node_pointer __next = __np->__next_;
Howard Hinnant0949eed2011-06-30 21:18:19 +0000974 __node_traits::destroy(__na, _VSTD::addressof(__np->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000975 __node_traits::deallocate(__na, __np, 1);
976 __np = __next;
977 }
978}
979
980template <class _Tp, class _Hash, class _Equal, class _Alloc>
981typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_pointer
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000982__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000983{
984 size_type __bc = bucket_count();
985 for (size_type __i = 0; __i < __bc; ++__i)
986 __bucket_list_[__i] = nullptr;
987 size() = 0;
988 __node_pointer __cache = __p1_.first().__next_;
989 __p1_.first().__next_ = nullptr;
990 return __cache;
991}
992
Howard Hinnant73d21a42010-09-04 23:28:19 +0000993#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000994
995template <class _Tp, class _Hash, class _Equal, class _Alloc>
996void
997__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
998 __hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000999 _NOEXCEPT_(
1000 is_nothrow_move_assignable<__node_allocator>::value &&
1001 is_nothrow_move_assignable<hasher>::value &&
1002 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001003{
1004 clear();
1005 __bucket_list_.reset(__u.__bucket_list_.release());
1006 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
1007 __u.__bucket_list_.get_deleter().size() = 0;
1008 __move_assign_alloc(__u);
1009 size() = __u.size();
Howard Hinnant0949eed2011-06-30 21:18:19 +00001010 hash_function() = _VSTD::move(__u.hash_function());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001011 max_load_factor() = __u.max_load_factor();
Howard Hinnant0949eed2011-06-30 21:18:19 +00001012 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001013 __p1_.first().__next_ = __u.__p1_.first().__next_;
1014 if (size() > 0)
1015 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001016 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant0949eed2011-06-30 21:18:19 +00001017 static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001018 __u.__p1_.first().__next_ = nullptr;
1019 __u.size() = 0;
1020 }
1021}
1022
1023template <class _Tp, class _Hash, class _Equal, class _Alloc>
1024void
1025__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
1026 __hash_table& __u, false_type)
1027{
1028 if (__node_alloc() == __u.__node_alloc())
1029 __move_assign(__u, true_type());
1030 else
1031 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001032 hash_function() = _VSTD::move(__u.hash_function());
1033 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001034 max_load_factor() = __u.max_load_factor();
1035 if (bucket_count() != 0)
1036 {
1037 __node_pointer __cache = __detach();
1038#ifndef _LIBCPP_NO_EXCEPTIONS
1039 try
1040 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001041#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001042 const_iterator __i = __u.begin();
1043 while (__cache != nullptr && __u.size() != 0)
1044 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001045 __cache->__value_ = _VSTD::move(__u.remove(__i++)->__value_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001046 __node_pointer __next = __cache->__next_;
1047 __node_insert_multi(__cache);
1048 __cache = __next;
1049 }
1050#ifndef _LIBCPP_NO_EXCEPTIONS
1051 }
1052 catch (...)
1053 {
1054 __deallocate(__cache);
1055 throw;
1056 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001057#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001058 __deallocate(__cache);
1059 }
1060 const_iterator __i = __u.begin();
1061 while (__u.size() != 0)
1062 {
1063 __node_holder __h =
Howard Hinnant0949eed2011-06-30 21:18:19 +00001064 __construct_node(_VSTD::move(__u.remove(__i++)->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001065 __node_insert_multi(__h.get());
1066 __h.release();
1067 }
1068 }
1069}
1070
1071template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001072inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001073__hash_table<_Tp, _Hash, _Equal, _Alloc>&
1074__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001075 _NOEXCEPT_(
1076 __node_traits::propagate_on_container_move_assignment::value &&
1077 is_nothrow_move_assignable<__node_allocator>::value &&
1078 is_nothrow_move_assignable<hasher>::value &&
1079 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001080{
1081 __move_assign(__u, integral_constant<bool,
1082 __node_traits::propagate_on_container_move_assignment::value>());
1083 return *this;
1084}
1085
Howard Hinnant73d21a42010-09-04 23:28:19 +00001086#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001087
1088template <class _Tp, class _Hash, class _Equal, class _Alloc>
1089template <class _InputIterator>
1090void
1091__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first,
1092 _InputIterator __last)
1093{
1094 if (bucket_count() != 0)
1095 {
1096 __node_pointer __cache = __detach();
1097#ifndef _LIBCPP_NO_EXCEPTIONS
1098 try
1099 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001100#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001101 for (; __cache != nullptr && __first != __last; ++__first)
1102 {
1103 __cache->__value_ = *__first;
1104 __node_pointer __next = __cache->__next_;
1105 __node_insert_unique(__cache);
1106 __cache = __next;
1107 }
1108#ifndef _LIBCPP_NO_EXCEPTIONS
1109 }
1110 catch (...)
1111 {
1112 __deallocate(__cache);
1113 throw;
1114 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001115#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001116 __deallocate(__cache);
1117 }
1118 for (; __first != __last; ++__first)
1119 __insert_unique(*__first);
1120}
1121
1122template <class _Tp, class _Hash, class _Equal, class _Alloc>
1123template <class _InputIterator>
1124void
1125__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first,
1126 _InputIterator __last)
1127{
1128 if (bucket_count() != 0)
1129 {
1130 __node_pointer __cache = __detach();
1131#ifndef _LIBCPP_NO_EXCEPTIONS
1132 try
1133 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001134#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001135 for (; __cache != nullptr && __first != __last; ++__first)
1136 {
1137 __cache->__value_ = *__first;
1138 __node_pointer __next = __cache->__next_;
1139 __node_insert_multi(__cache);
1140 __cache = __next;
1141 }
1142#ifndef _LIBCPP_NO_EXCEPTIONS
1143 }
1144 catch (...)
1145 {
1146 __deallocate(__cache);
1147 throw;
1148 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001149#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001150 __deallocate(__cache);
1151 }
1152 for (; __first != __last; ++__first)
1153 __insert_multi(*__first);
1154}
1155
1156template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001157inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001158typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001159__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001160{
1161 return iterator(__p1_.first().__next_);
1162}
1163
1164template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001165inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001166typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001167__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001168{
1169 return iterator(nullptr);
1170}
1171
1172template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001173inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001174typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001175__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001176{
1177 return const_iterator(__p1_.first().__next_);
1178}
1179
1180template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001181inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001182typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001183__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001184{
1185 return const_iterator(nullptr);
1186}
1187
1188template <class _Tp, class _Hash, class _Equal, class _Alloc>
1189void
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001190__hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001191{
1192 if (size() > 0)
1193 {
1194 __deallocate(__p1_.first().__next_);
1195 __p1_.first().__next_ = nullptr;
1196 size_type __bc = bucket_count();
Howard Hinnant9f66bff2011-07-05 14:14:17 +00001197 for (size_type __i = 0; __i < __bc; ++__i)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001198 __bucket_list_[__i] = nullptr;
1199 size() = 0;
1200 }
1201}
1202
1203template <class _Tp, class _Hash, class _Equal, class _Alloc>
1204pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1205__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd)
1206{
1207 __nd->__hash_ = hash_function()(__nd->__value_);
1208 size_type __bc = bucket_count();
1209 bool __inserted = false;
1210 __node_pointer __ndptr;
1211 size_t __chash;
1212 if (__bc != 0)
1213 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001214 __chash = __constrain_hash(__nd->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001215 __ndptr = __bucket_list_[__chash];
1216 if (__ndptr != nullptr)
1217 {
1218 for (__ndptr = __ndptr->__next_; __ndptr != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001219 __constrain_hash(__ndptr->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001220 __ndptr = __ndptr->__next_)
1221 {
1222 if (key_eq()(__ndptr->__value_, __nd->__value_))
1223 goto __done;
1224 }
1225 }
1226 }
1227 {
1228 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1229 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001230 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001231 size_type(ceil(float(size() + 1) / max_load_factor()))));
1232 __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:14 +00001233 __chash = __constrain_hash(__nd->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001234 }
1235 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1236 __node_pointer __pn = __bucket_list_[__chash];
1237 if (__pn == nullptr)
1238 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001239 __pn = static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001240 __nd->__next_ = __pn->__next_;
1241 __pn->__next_ = __nd;
1242 // fix up __bucket_list_
1243 __bucket_list_[__chash] = __pn;
1244 if (__nd->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:14 +00001245 __bucket_list_[__constrain_hash(__nd->__next_->__hash_, __bc)] = __nd;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001246 }
1247 else
1248 {
1249 __nd->__next_ = __pn->__next_;
1250 __pn->__next_ = __nd;
1251 }
1252 __ndptr = __nd;
1253 // increment size
1254 ++size();
1255 __inserted = true;
1256 }
1257__done:
1258 return pair<iterator, bool>(iterator(__ndptr), __inserted);
1259}
1260
1261template <class _Tp, class _Hash, class _Equal, class _Alloc>
1262typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1263__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp)
1264{
1265 __cp->__hash_ = hash_function()(__cp->__value_);
1266 size_type __bc = bucket_count();
1267 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1268 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001269 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001270 size_type(ceil(float(size() + 1) / max_load_factor()))));
1271 __bc = bucket_count();
1272 }
Howard Hinnant7a445152012-07-06 17:31:14 +00001273 size_t __chash = __constrain_hash(__cp->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001274 __node_pointer __pn = __bucket_list_[__chash];
1275 if (__pn == nullptr)
1276 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001277 __pn = static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001278 __cp->__next_ = __pn->__next_;
1279 __pn->__next_ = __cp;
1280 // fix up __bucket_list_
1281 __bucket_list_[__chash] = __pn;
1282 if (__cp->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:14 +00001283 __bucket_list_[__constrain_hash(__cp->__next_->__hash_, __bc)] = __cp;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001284 }
1285 else
1286 {
1287 for (bool __found = false; __pn->__next_ != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001288 __constrain_hash(__pn->__next_->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001289 __pn = __pn->__next_)
Howard Hinnant324bb032010-08-22 00:02:43 +00001290 {
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001291 // __found key_eq() action
1292 // false false loop
1293 // true true loop
1294 // false true set __found to true
1295 // true false break
1296 if (__found != (__pn->__next_->__hash_ == __cp->__hash_ &&
1297 key_eq()(__pn->__next_->__value_, __cp->__value_)))
1298 {
1299 if (!__found)
1300 __found = true;
1301 else
1302 break;
1303 }
1304 }
1305 __cp->__next_ = __pn->__next_;
1306 __pn->__next_ = __cp;
1307 if (__cp->__next_ != nullptr)
1308 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001309 size_t __nhash = __constrain_hash(__cp->__next_->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001310 if (__nhash != __chash)
1311 __bucket_list_[__nhash] = __cp;
1312 }
1313 }
1314 ++size();
1315 return iterator(__cp);
1316}
1317
1318template <class _Tp, class _Hash, class _Equal, class _Alloc>
1319typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1320__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(
1321 const_iterator __p, __node_pointer __cp)
1322{
1323 if (__p != end() && key_eq()(*__p, __cp->__value_))
1324 {
1325 __node_pointer __np = const_cast<__node_pointer>(__p.__node_);
1326 __cp->__hash_ = __np->__hash_;
1327 size_type __bc = bucket_count();
1328 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1329 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001330 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001331 size_type(ceil(float(size() + 1) / max_load_factor()))));
1332 __bc = bucket_count();
1333 }
Howard Hinnant7a445152012-07-06 17:31:14 +00001334 size_t __chash = __constrain_hash(__cp->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001335 __node_pointer __pp = __bucket_list_[__chash];
1336 while (__pp->__next_ != __np)
1337 __pp = __pp->__next_;
1338 __cp->__next_ = __np;
1339 __pp->__next_ = __cp;
1340 ++size();
1341 return iterator(__cp);
1342 }
1343 return __node_insert_multi(__cp);
1344}
1345
1346template <class _Tp, class _Hash, class _Equal, class _Alloc>
1347pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1348__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(const value_type& __x)
1349{
1350 size_t __hash = hash_function()(__x);
1351 size_type __bc = bucket_count();
1352 bool __inserted = false;
1353 __node_pointer __nd;
1354 size_t __chash;
1355 if (__bc != 0)
1356 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001357 __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001358 __nd = __bucket_list_[__chash];
1359 if (__nd != nullptr)
1360 {
1361 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001362 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001363 __nd = __nd->__next_)
1364 {
1365 if (key_eq()(__nd->__value_, __x))
1366 goto __done;
1367 }
1368 }
1369 }
1370 {
1371 __node_holder __h = __construct_node(__x, __hash);
1372 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1373 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001374 rehash(_VSTD::max<size_type>(2 * __bc + !__is_power2(__bc),
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001375 size_type(ceil(float(size() + 1) / max_load_factor()))));
1376 __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:14 +00001377 __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001378 }
1379 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1380 __node_pointer __pn = __bucket_list_[__chash];
1381 if (__pn == nullptr)
1382 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001383 __pn = static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001384 __h->__next_ = __pn->__next_;
1385 __pn->__next_ = __h.get();
1386 // fix up __bucket_list_
1387 __bucket_list_[__chash] = __pn;
1388 if (__h->__next_ != nullptr)
Howard Hinnant7a445152012-07-06 17:31:14 +00001389 __bucket_list_[__constrain_hash(__h->__next_->__hash_, __bc)] = __h.get();
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001390 }
1391 else
1392 {
1393 __h->__next_ = __pn->__next_;
1394 __pn->__next_ = __h.get();
1395 }
1396 __nd = __h.release();
1397 // increment size
1398 ++size();
1399 __inserted = true;
1400 }
1401__done:
1402 return pair<iterator, bool>(iterator(__nd), __inserted);
1403}
1404
Howard Hinnant73d21a42010-09-04 23:28:19 +00001405#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1406#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001407
1408template <class _Tp, class _Hash, class _Equal, class _Alloc>
1409template <class... _Args>
1410pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1411__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique(_Args&&... __args)
1412{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001413 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001414 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1415 if (__r.second)
1416 __h.release();
1417 return __r;
1418}
1419
1420template <class _Tp, class _Hash, class _Equal, class _Alloc>
1421template <class... _Args>
1422typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1423__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args)
1424{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001425 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001426 iterator __r = __node_insert_multi(__h.get());
1427 __h.release();
1428 return __r;
1429}
1430
1431template <class _Tp, class _Hash, class _Equal, class _Alloc>
1432template <class... _Args>
1433typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1434__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi(
1435 const_iterator __p, _Args&&... __args)
1436{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001437 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001438 iterator __r = __node_insert_multi(__p, __h.get());
1439 __h.release();
1440 return __r;
1441}
1442
Howard Hinnant73d21a42010-09-04 23:28:19 +00001443#endif // _LIBCPP_HAS_NO_VARIADICS
1444
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001445template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:50 +00001446template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001447pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
Howard Hinnant99968442011-11-29 18:15:50 +00001448__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(_Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001449{
Howard Hinnant99968442011-11-29 18:15:50 +00001450 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001451 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1452 if (__r.second)
1453 __h.release();
1454 return __r;
1455}
1456
Howard Hinnant73d21a42010-09-04 23:28:19 +00001457#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001458
Howard Hinnant73d21a42010-09-04 23:28:19 +00001459#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001460
1461template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:50 +00001462template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001463typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant99968442011-11-29 18:15:50 +00001464__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(_Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001465{
Howard Hinnant99968442011-11-29 18:15:50 +00001466 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001467 iterator __r = __node_insert_multi(__h.get());
1468 __h.release();
1469 return __r;
1470}
1471
1472template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:50 +00001473template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001474typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1475__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
Howard Hinnant99968442011-11-29 18:15:50 +00001476 _Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001477{
Howard Hinnant99968442011-11-29 18:15:50 +00001478 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001479 iterator __r = __node_insert_multi(__p, __h.get());
1480 __h.release();
1481 return __r;
1482}
1483
Howard Hinnant73d21a42010-09-04 23:28:19 +00001484#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001485
1486template <class _Tp, class _Hash, class _Equal, class _Alloc>
1487typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1488__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const value_type& __x)
1489{
1490 __node_holder __h = __construct_node(__x);
1491 iterator __r = __node_insert_multi(__h.get());
1492 __h.release();
1493 return __r;
1494}
1495
1496template <class _Tp, class _Hash, class _Equal, class _Alloc>
1497typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1498__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
1499 const value_type& __x)
1500{
1501 __node_holder __h = __construct_node(__x);
1502 iterator __r = __node_insert_multi(__p, __h.get());
1503 __h.release();
1504 return __r;
1505}
1506
Howard Hinnant73d21a42010-09-04 23:28:19 +00001507#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001508
1509template <class _Tp, class _Hash, class _Equal, class _Alloc>
1510void
1511__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n)
1512{
Howard Hinnant7a445152012-07-06 17:31:14 +00001513 if (__n == 1)
1514 __n = 2;
1515 else if (__n & (__n - 1))
1516 __n = __next_prime(__n);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001517 size_type __bc = bucket_count();
1518 if (__n > __bc)
1519 __rehash(__n);
Howard Hinnant7a445152012-07-06 17:31:14 +00001520 else if (__n < __bc)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001521 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001522 __n = _VSTD::max<size_type>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001523 (
1524 __n,
Howard Hinnant7a445152012-07-06 17:31:14 +00001525 __is_power2(__bc) ? __next_pow2(size_t(ceil(float(size()) / max_load_factor()))) :
1526 __next_prime(size_t(ceil(float(size()) / max_load_factor())))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001527 );
1528 if (__n < __bc)
1529 __rehash(__n);
1530 }
1531}
1532
1533template <class _Tp, class _Hash, class _Equal, class _Alloc>
1534void
1535__hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc)
1536{
1537 __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc();
1538 __bucket_list_.reset(__nbc > 0 ?
1539 __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr);
1540 __bucket_list_.get_deleter().size() = __nbc;
1541 if (__nbc > 0)
1542 {
1543 for (size_type __i = 0; __i < __nbc; ++__i)
1544 __bucket_list_[__i] = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00001545 __node_pointer __pp(static_cast<__node_pointer>(_VSTD::addressof(__p1_.first())));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001546 __node_pointer __cp = __pp->__next_;
1547 if (__cp != nullptr)
1548 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001549 size_type __chash = __constrain_hash(__cp->__hash_, __nbc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001550 __bucket_list_[__chash] = __pp;
1551 size_type __phash = __chash;
1552 for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr;
1553 __cp = __pp->__next_)
1554 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001555 __chash = __constrain_hash(__cp->__hash_, __nbc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001556 if (__chash == __phash)
1557 __pp = __cp;
1558 else
1559 {
1560 if (__bucket_list_[__chash] == nullptr)
1561 {
1562 __bucket_list_[__chash] = __pp;
1563 __pp = __cp;
1564 __phash = __chash;
1565 }
1566 else
1567 {
1568 __node_pointer __np = __cp;
1569 for (; __np->__next_ != nullptr &&
1570 key_eq()(__cp->__value_, __np->__next_->__value_);
1571 __np = __np->__next_)
1572 ;
1573 __pp->__next_ = __np->__next_;
1574 __np->__next_ = __bucket_list_[__chash]->__next_;
1575 __bucket_list_[__chash]->__next_ = __cp;
Howard Hinnant324bb032010-08-22 00:02:43 +00001576
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001577 }
1578 }
1579 }
1580 }
1581 }
1582}
1583
1584template <class _Tp, class _Hash, class _Equal, class _Alloc>
1585template <class _Key>
1586typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1587__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k)
1588{
1589 size_t __hash = hash_function()(__k);
1590 size_type __bc = bucket_count();
1591 if (__bc != 0)
1592 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001593 size_t __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001594 __node_pointer __nd = __bucket_list_[__chash];
1595 if (__nd != nullptr)
1596 {
1597 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001598 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001599 __nd = __nd->__next_)
1600 {
1601 if (key_eq()(__nd->__value_, __k))
1602 return iterator(__nd);
1603 }
1604 }
1605 }
1606 return end();
1607}
1608
1609template <class _Tp, class _Hash, class _Equal, class _Alloc>
1610template <class _Key>
1611typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1612__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const
1613{
1614 size_t __hash = hash_function()(__k);
1615 size_type __bc = bucket_count();
1616 if (__bc != 0)
1617 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001618 size_t __chash = __constrain_hash(__hash, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001619 __node_const_pointer __nd = __bucket_list_[__chash];
1620 if (__nd != nullptr)
1621 {
1622 for (__nd = __nd->__next_; __nd != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001623 __constrain_hash(__nd->__hash_, __bc) == __chash;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001624 __nd = __nd->__next_)
1625 {
1626 if (key_eq()(__nd->__value_, __k))
1627 return const_iterator(__nd);
1628 }
1629 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001630
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001631 }
1632 return end();
1633}
1634
Howard Hinnant73d21a42010-09-04 23:28:19 +00001635#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1636#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001637
1638template <class _Tp, class _Hash, class _Equal, class _Alloc>
1639template <class ..._Args>
1640typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1641__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args)
1642{
1643 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00001644 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001645 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001646 __h.get_deleter().__value_constructed = true;
1647 __h->__hash_ = hash_function()(__h->__value_);
1648 __h->__next_ = nullptr;
1649 return __h;
1650}
1651
Howard Hinnant73d21a42010-09-04 23:28:19 +00001652#endif // _LIBCPP_HAS_NO_VARIADICS
1653
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001654template <class _Tp, class _Hash, class _Equal, class _Alloc>
1655typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1656__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(value_type&& __v,
1657 size_t __hash)
1658{
1659 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00001660 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001661 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::move(__v));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001662 __h.get_deleter().__value_constructed = true;
1663 __h->__hash_ = __hash;
1664 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00001665 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001666}
1667
Howard Hinnant73d21a42010-09-04 23:28:19 +00001668#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001669
1670template <class _Tp, class _Hash, class _Equal, class _Alloc>
1671typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1672__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v)
1673{
1674 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00001675 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001676 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001677 __h.get_deleter().__value_constructed = true;
1678 __h->__hash_ = hash_function()(__h->__value_);
1679 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00001680 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001681}
1682
Howard Hinnant73d21a42010-09-04 23:28:19 +00001683#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001684
1685template <class _Tp, class _Hash, class _Equal, class _Alloc>
1686typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1687__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v,
1688 size_t __hash)
1689{
1690 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00001691 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001692 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001693 __h.get_deleter().__value_constructed = true;
1694 __h->__hash_ = __hash;
1695 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00001696 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001697}
1698
1699template <class _Tp, class _Hash, class _Equal, class _Alloc>
1700typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1701__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p)
1702{
1703 __node_pointer __np = const_cast<__node_pointer>(__p.__node_);
1704 iterator __r(__np);
1705 ++__r;
1706 remove(__p);
1707 return __r;
1708}
1709
1710template <class _Tp, class _Hash, class _Equal, class _Alloc>
1711typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1712__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first,
1713 const_iterator __last)
1714{
1715 for (const_iterator __p = __first; __first != __last; __p = __first)
1716 {
1717 ++__first;
1718 erase(__p);
1719 }
1720 __node_pointer __np = const_cast<__node_pointer>(__last.__node_);
1721 return iterator (__np);
1722}
1723
1724template <class _Tp, class _Hash, class _Equal, class _Alloc>
1725template <class _Key>
1726typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1727__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k)
1728{
1729 iterator __i = find(__k);
1730 if (__i == end())
1731 return 0;
1732 erase(__i);
1733 return 1;
1734}
1735
1736template <class _Tp, class _Hash, class _Equal, class _Alloc>
1737template <class _Key>
1738typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1739__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k)
1740{
1741 size_type __r = 0;
1742 iterator __i = find(__k);
1743 if (__i != end())
1744 {
1745 iterator __e = end();
1746 do
1747 {
1748 erase(__i++);
1749 ++__r;
1750 } while (__i != __e && key_eq()(*__i, __k));
1751 }
1752 return __r;
1753}
1754
1755template <class _Tp, class _Hash, class _Equal, class _Alloc>
1756typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001757__hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001758{
1759 // current node
1760 __node_pointer __cn = const_cast<__node_pointer>(__p.__node_);
1761 size_type __bc = bucket_count();
Howard Hinnant7a445152012-07-06 17:31:14 +00001762 size_t __chash = __constrain_hash(__cn->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001763 // find previous node
1764 __node_pointer __pn = __bucket_list_[__chash];
1765 for (; __pn->__next_ != __cn; __pn = __pn->__next_)
1766 ;
1767 // Fix up __bucket_list_
1768 // if __pn is not in same bucket (before begin is not in same bucket) &&
1769 // if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
Howard Hinnant7a445152012-07-06 17:31:14 +00001770 if (__pn == _VSTD::addressof(__p1_.first()) || __constrain_hash(__pn->__hash_, __bc) != __chash)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001771 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001772 if (__cn->__next_ == nullptr || __constrain_hash(__cn->__next_->__hash_, __bc) != __chash)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001773 __bucket_list_[__chash] = nullptr;
1774 }
1775 // if __cn->__next_ is not in same bucket (nullptr is in same bucket)
1776 if (__cn->__next_ != nullptr)
1777 {
Howard Hinnant7a445152012-07-06 17:31:14 +00001778 size_t __nhash = __constrain_hash(__cn->__next_->__hash_, __bc);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001779 if (__nhash != __chash)
1780 __bucket_list_[__nhash] = __pn;
1781 }
1782 // remove __cn
1783 __pn->__next_ = __cn->__next_;
1784 __cn->__next_ = nullptr;
1785 --size();
Howard Hinnant99968442011-11-29 18:15:50 +00001786 return __node_holder(__cn, _Dp(__node_alloc(), true));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001787}
1788
1789template <class _Tp, class _Hash, class _Equal, class _Alloc>
1790template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39 +00001791inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001792typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1793__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const
1794{
1795 return static_cast<size_type>(find(__k) != end());
1796}
1797
1798template <class _Tp, class _Hash, class _Equal, class _Alloc>
1799template <class _Key>
1800typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1801__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const
1802{
1803 size_type __r = 0;
1804 const_iterator __i = find(__k);
1805 if (__i != end())
1806 {
1807 const_iterator __e = end();
1808 do
1809 {
1810 ++__i;
1811 ++__r;
1812 } while (__i != __e && key_eq()(*__i, __k));
1813 }
1814 return __r;
1815}
1816
1817template <class _Tp, class _Hash, class _Equal, class _Alloc>
1818template <class _Key>
1819pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
1820 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1821__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
1822 const _Key& __k)
1823{
1824 iterator __i = find(__k);
1825 iterator __j = __i;
1826 if (__i != end())
1827 ++__j;
1828 return pair<iterator, iterator>(__i, __j);
1829}
1830
1831template <class _Tp, class _Hash, class _Equal, class _Alloc>
1832template <class _Key>
1833pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
1834 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1835__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
1836 const _Key& __k) const
1837{
1838 const_iterator __i = find(__k);
1839 const_iterator __j = __i;
1840 if (__i != end())
1841 ++__j;
1842 return pair<const_iterator, const_iterator>(__i, __j);
1843}
1844
1845template <class _Tp, class _Hash, class _Equal, class _Alloc>
1846template <class _Key>
1847pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
1848 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1849__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
1850 const _Key& __k)
1851{
1852 iterator __i = find(__k);
1853 iterator __j = __i;
1854 if (__i != end())
1855 {
1856 iterator __e = end();
1857 do
1858 {
1859 ++__j;
1860 } while (__j != __e && key_eq()(*__j, __k));
1861 }
1862 return pair<iterator, iterator>(__i, __j);
1863}
1864
1865template <class _Tp, class _Hash, class _Equal, class _Alloc>
1866template <class _Key>
1867pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
1868 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1869__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
1870 const _Key& __k) const
1871{
1872 const_iterator __i = find(__k);
1873 const_iterator __j = __i;
1874 if (__i != end())
1875 {
1876 const_iterator __e = end();
1877 do
1878 {
1879 ++__j;
1880 } while (__j != __e && key_eq()(*__j, __k));
1881 }
1882 return pair<const_iterator, const_iterator>(__i, __j);
1883}
1884
1885template <class _Tp, class _Hash, class _Equal, class _Alloc>
1886void
1887__hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001888 _NOEXCEPT_(
1889 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
1890 __is_nothrow_swappable<__pointer_allocator>::value) &&
1891 (!__node_traits::propagate_on_container_swap::value ||
1892 __is_nothrow_swappable<__node_allocator>::value) &&
1893 __is_nothrow_swappable<hasher>::value &&
1894 __is_nothrow_swappable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001895{
1896 {
1897 __node_pointer_pointer __npp = __bucket_list_.release();
1898 __bucket_list_.reset(__u.__bucket_list_.release());
1899 __u.__bucket_list_.reset(__npp);
1900 }
Howard Hinnant0949eed2011-06-30 21:18:19 +00001901 _VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001902 __swap_alloc(__bucket_list_.get_deleter().__alloc(),
1903 __u.__bucket_list_.get_deleter().__alloc());
1904 __swap_alloc(__node_alloc(), __u.__node_alloc());
Howard Hinnant0949eed2011-06-30 21:18:19 +00001905 _VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001906 __p2_.swap(__u.__p2_);
1907 __p3_.swap(__u.__p3_);
1908 if (size() > 0)
Howard Hinnant7a445152012-07-06 17:31:14 +00001909 __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] =
Howard Hinnant0949eed2011-06-30 21:18:19 +00001910 static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001911 if (__u.size() > 0)
Howard Hinnant7a445152012-07-06 17:31:14 +00001912 __u.__bucket_list_[__constrain_hash(__u.__p1_.first().__next_->__hash_, __u.bucket_count())] =
Howard Hinnant0949eed2011-06-30 21:18:19 +00001913 static_cast<__node_pointer>(_VSTD::addressof(__u.__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001914}
1915
1916template <class _Tp, class _Hash, class _Equal, class _Alloc>
1917typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1918__hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const
1919{
1920 __node_const_pointer __np = __bucket_list_[__n];
1921 size_type __bc = bucket_count();
1922 size_type __r = 0;
1923 if (__np != nullptr)
1924 {
1925 for (__np = __np->__next_; __np != nullptr &&
Howard Hinnant7a445152012-07-06 17:31:14 +00001926 __constrain_hash(__np->__hash_, __bc) == __n;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001927 __np = __np->__next_, ++__r)
1928 ;
1929 }
1930 return __r;
1931}
1932
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001933template <class _Tp, class _Hash, class _Equal, class _Alloc>
1934inline _LIBCPP_INLINE_VISIBILITY
1935void
1936swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x,
1937 __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y)
1938 _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
1939{
1940 __x.swap(__y);
1941}
1942
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001943_LIBCPP_END_NAMESPACE_STD
1944
1945#endif // _LIBCPP__HASH_TABLE