blob: ae9ee1c515d79391e7c1995cd6ced22e086a8579 [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
21#pragma GCC system_header
22
23_LIBCPP_BEGIN_NAMESPACE_STD
24
Howard Hinnant99acc502010-09-21 17:32:39 +000025_LIBCPP_VISIBLE
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000026size_t __next_prime(size_t);
27
28template <class _NodePtr>
29struct __hash_node_base
30{
31 typedef __hash_node_base __first_node;
32 typedef _NodePtr pointer;
33
34 pointer __next_;
35
Howard Hinnant99acc502010-09-21 17:32:39 +000036 _LIBCPP_INLINE_VISIBILITY __hash_node_base() : __next_(nullptr) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000037};
38
39template <class _Tp, class _VoidPtr>
40struct __hash_node
41 : public __hash_node_base
42 <
43 typename pointer_traits<_VoidPtr>::template
44#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
45 rebind<__hash_node<_Tp, _VoidPtr> >
46#else
47 rebind<__hash_node<_Tp, _VoidPtr> >::other
48#endif
49 >
50{
51 typedef _Tp value_type;
52
53 size_t __hash_;
54 value_type __value_;
55};
56
57template <class, class, class, class> class __hash_table;
58template <class> class __hash_const_iterator;
59template <class> class __hash_map_iterator;
60template <class> class __hash_map_const_iterator;
Howard Hinnant99acc502010-09-21 17:32:39 +000061template <class, class, class, class, class> class _LIBCPP_VISIBLE unordered_map;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000062
63template <class _NodePtr>
Howard Hinnant99acc502010-09-21 17:32:39 +000064class _LIBCPP_VISIBLE __hash_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000065{
66 typedef _NodePtr __node_pointer;
67
68 __node_pointer __node_;
69
70public:
71 typedef forward_iterator_tag iterator_category;
72 typedef typename pointer_traits<__node_pointer>::element_type::value_type value_type;
73 typedef typename pointer_traits<__node_pointer>::difference_type difference_type;
74 typedef value_type& reference;
75 typedef typename pointer_traits<__node_pointer>::template
76#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
77 rebind<value_type>
78#else
79 rebind<value_type>::other
80#endif
81 pointer;
82
Howard Hinnant99acc502010-09-21 17:32:39 +000083 _LIBCPP_INLINE_VISIBILITY __hash_iterator() {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000084
Howard Hinnant99acc502010-09-21 17:32:39 +000085 _LIBCPP_INLINE_VISIBILITY
86 reference operator*() const {return __node_->__value_;}
87 _LIBCPP_INLINE_VISIBILITY
88 pointer operator->() const {return addressof(__node_->__value_);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000089
Howard Hinnant99acc502010-09-21 17:32:39 +000090 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000091 __hash_iterator& operator++()
92 {
93 __node_ = __node_->__next_;
94 return *this;
95 }
96
Howard Hinnant99acc502010-09-21 17:32:39 +000097 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000098 __hash_iterator operator++(int)
99 {
100 __hash_iterator __t(*this);
101 ++(*this);
102 return __t;
103 }
104
Howard Hinnant99acc502010-09-21 17:32:39 +0000105 friend _LIBCPP_INLINE_VISIBILITY
106 bool operator==(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000107 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000108 friend _LIBCPP_INLINE_VISIBILITY
109 bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000110 {return __x.__node_ != __y.__node_;}
111
112private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000113 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000114 __hash_iterator(__node_pointer __node)
115 : __node_(__node)
116 {}
117
118 template <class, class, class, class> friend class __hash_table;
Howard Hinnant99acc502010-09-21 17:32:39 +0000119 template <class> friend class _LIBCPP_VISIBLE __hash_const_iterator;
120 template <class> friend class _LIBCPP_VISIBLE __hash_map_iterator;
121 template <class, class, class, class, class> friend class _LIBCPP_VISIBLE unordered_map;
122 template <class, class, class, class, class> friend class _LIBCPP_VISIBLE unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000123};
124
125template <class _ConstNodePtr>
Howard Hinnant99acc502010-09-21 17:32:39 +0000126class _LIBCPP_VISIBLE __hash_const_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000127{
128 typedef _ConstNodePtr __node_pointer;
129
130 __node_pointer __node_;
131
132 typedef typename remove_const<
133 typename pointer_traits<__node_pointer>::element_type
134 >::type __node;
135
136public:
137 typedef forward_iterator_tag iterator_category;
138 typedef typename __node::value_type value_type;
139 typedef typename pointer_traits<__node_pointer>::difference_type difference_type;
140 typedef const value_type& reference;
141 typedef typename pointer_traits<__node_pointer>::template
142#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
143 rebind<const value_type>
144#else
145 rebind<const value_type>::other
146#endif
147 pointer;
148 typedef typename pointer_traits<__node_pointer>::template
149#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
150 rebind<__node>
151#else
152 rebind<__node>::other
153#endif
154 __non_const_node_pointer;
155 typedef __hash_iterator<__non_const_node_pointer> __non_const_iterator;
156
Howard Hinnant99acc502010-09-21 17:32:39 +0000157 _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() {}
158 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000159 __hash_const_iterator(const __non_const_iterator& __x)
160 : __node_(__x.__node_)
161 {}
162
Howard Hinnant99acc502010-09-21 17:32:39 +0000163 _LIBCPP_INLINE_VISIBILITY
164 reference operator*() const {return __node_->__value_;}
165 _LIBCPP_INLINE_VISIBILITY
166 pointer operator->() const {return addressof(__node_->__value_);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000167
Howard Hinnant99acc502010-09-21 17:32:39 +0000168 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000169 __hash_const_iterator& operator++()
170 {
171 __node_ = __node_->__next_;
172 return *this;
173 }
174
Howard Hinnant99acc502010-09-21 17:32:39 +0000175 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000176 __hash_const_iterator operator++(int)
177 {
178 __hash_const_iterator __t(*this);
179 ++(*this);
180 return __t;
181 }
182
Howard Hinnant99acc502010-09-21 17:32:39 +0000183 friend _LIBCPP_INLINE_VISIBILITY
184 bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000185 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000186 friend _LIBCPP_INLINE_VISIBILITY
187 bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000188 {return __x.__node_ != __y.__node_;}
189
190private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000191 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000192 __hash_const_iterator(__node_pointer __node)
193 : __node_(__node)
194 {}
195
196 template <class, class, class, class> friend class __hash_table;
Howard Hinnant99acc502010-09-21 17:32:39 +0000197 template <class> friend class _LIBCPP_VISIBLE __hash_map_const_iterator;
198 template <class, class, class, class, class> friend class _LIBCPP_VISIBLE unordered_map;
199 template <class, class, class, class, class> friend class _LIBCPP_VISIBLE unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000200};
201
Howard Hinnant99acc502010-09-21 17:32:39 +0000202template <class> class _LIBCPP_VISIBLE __hash_const_local_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000203
204template <class _NodePtr>
Howard Hinnant99acc502010-09-21 17:32:39 +0000205class _LIBCPP_VISIBLE __hash_local_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000206{
207 typedef _NodePtr __node_pointer;
208
209 __node_pointer __node_;
210 size_t __bucket_;
211 size_t __bucket_count_;
212
213 typedef pointer_traits<__node_pointer> __pointer_traits;
214public:
215 typedef forward_iterator_tag iterator_category;
216 typedef typename __pointer_traits::element_type::value_type value_type;
217 typedef typename __pointer_traits::difference_type difference_type;
218 typedef value_type& reference;
219 typedef typename __pointer_traits::template
220#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
221 rebind<value_type>
222#else
223 rebind<value_type>::other
224#endif
225 pointer;
226
Howard Hinnant99acc502010-09-21 17:32:39 +0000227 _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000228
Howard Hinnant99acc502010-09-21 17:32:39 +0000229 _LIBCPP_INLINE_VISIBILITY
230 reference operator*() const {return __node_->__value_;}
231 _LIBCPP_INLINE_VISIBILITY
232 pointer operator->() const {return &__node_->__value_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000233
Howard Hinnant99acc502010-09-21 17:32:39 +0000234 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000235 __hash_local_iterator& operator++()
236 {
237 __node_ = __node_->__next_;
238 if (__node_ != nullptr && __node_->__hash_ % __bucket_count_ != __bucket_)
239 __node_ = nullptr;
240 return *this;
241 }
242
Howard Hinnant99acc502010-09-21 17:32:39 +0000243 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000244 __hash_local_iterator operator++(int)
245 {
246 __hash_local_iterator __t(*this);
247 ++(*this);
248 return __t;
249 }
250
Howard Hinnant99acc502010-09-21 17:32:39 +0000251 friend _LIBCPP_INLINE_VISIBILITY
252 bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000253 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000254 friend _LIBCPP_INLINE_VISIBILITY
255 bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000256 {return __x.__node_ != __y.__node_;}
257
258private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000259 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000260 __hash_local_iterator(__node_pointer __node, size_t __bucket,
261 size_t __bucket_count)
262 : __node_(__node),
263 __bucket_(__bucket),
264 __bucket_count_(__bucket_count)
265 {
266 if (__node_ != nullptr)
267 __node_ = __node_->__next_;
268 }
269
270 template <class, class, class, class> friend class __hash_table;
Howard Hinnant99acc502010-09-21 17:32:39 +0000271 template <class> friend class _LIBCPP_VISIBLE __hash_const_local_iterator;
272 template <class> friend class _LIBCPP_VISIBLE __hash_map_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000273};
274
275template <class _ConstNodePtr>
Howard Hinnant99acc502010-09-21 17:32:39 +0000276class _LIBCPP_VISIBLE __hash_const_local_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000277{
278 typedef _ConstNodePtr __node_pointer;
279
280 __node_pointer __node_;
281 size_t __bucket_;
282 size_t __bucket_count_;
283
284 typedef pointer_traits<__node_pointer> __pointer_traits;
285 typedef typename __pointer_traits::element_type __node;
286 typedef typename remove_const<__node>::type __non_const_node;
287 typedef typename pointer_traits<__node_pointer>::template
288#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
289 rebind<__non_const_node>
290#else
291 rebind<__non_const_node>::other
292#endif
293 __non_const_node_pointer;
294 typedef __hash_local_iterator<__non_const_node_pointer>
295 __non_const_iterator;
296public:
297 typedef forward_iterator_tag iterator_category;
298 typedef typename remove_const<
299 typename __pointer_traits::element_type::value_type
300 >::type value_type;
301 typedef typename __pointer_traits::difference_type difference_type;
302 typedef const value_type& reference;
303 typedef typename __pointer_traits::template
304#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
305 rebind<const value_type>
306#else
307 rebind<const value_type>::other
308#endif
309 pointer;
310
Howard Hinnant99acc502010-09-21 17:32:39 +0000311 _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() {}
312 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000313 __hash_const_local_iterator(const __non_const_iterator& __x)
314 : __node_(__x.__node_),
315 __bucket_(__x.__bucket_),
316 __bucket_count_(__x.__bucket_count_)
317 {}
318
Howard Hinnant99acc502010-09-21 17:32:39 +0000319 _LIBCPP_INLINE_VISIBILITY
320 reference operator*() const {return __node_->__value_;}
321 _LIBCPP_INLINE_VISIBILITY
322 pointer operator->() const {return &__node_->__value_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000323
Howard Hinnant99acc502010-09-21 17:32:39 +0000324 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000325 __hash_const_local_iterator& operator++()
326 {
327 __node_ = __node_->__next_;
328 if (__node_ != nullptr && __node_->__hash_ % __bucket_count_ != __bucket_)
329 __node_ = nullptr;
330 return *this;
331 }
332
Howard Hinnant99acc502010-09-21 17:32:39 +0000333 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000334 __hash_const_local_iterator operator++(int)
335 {
336 __hash_const_local_iterator __t(*this);
337 ++(*this);
338 return __t;
339 }
340
Howard Hinnant99acc502010-09-21 17:32:39 +0000341 friend _LIBCPP_INLINE_VISIBILITY
342 bool operator==(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000343 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000344 friend _LIBCPP_INLINE_VISIBILITY
345 bool operator!=(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000346 {return __x.__node_ != __y.__node_;}
347
348private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000349 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000350 __hash_const_local_iterator(__node_pointer __node, size_t __bucket,
351 size_t __bucket_count)
352 : __node_(__node),
353 __bucket_(__bucket),
354 __bucket_count_(__bucket_count)
355 {
356 if (__node_ != nullptr)
357 __node_ = __node_->__next_;
358 }
359
360 template <class, class, class, class> friend class __hash_table;
Howard Hinnant99acc502010-09-21 17:32:39 +0000361 template <class> friend class _LIBCPP_VISIBLE __hash_map_const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000362};
363
364template <class _Alloc>
365class __bucket_list_deallocator
366{
367 typedef _Alloc allocator_type;
368 typedef allocator_traits<allocator_type> __alloc_traits;
369 typedef typename __alloc_traits::size_type size_type;
370
371 __compressed_pair<size_type, allocator_type> __data_;
372public:
373 typedef typename __alloc_traits::pointer pointer;
374
Howard Hinnant99acc502010-09-21 17:32:39 +0000375 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000376 __bucket_list_deallocator()
377 : __data_(0) {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000378
379 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000380 __bucket_list_deallocator(const allocator_type& __a, size_type __size)
381 : __data_(__size, __a) {}
382
Howard Hinnant73d21a42010-09-04 23:28:19 +0000383#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000384
Howard Hinnant99acc502010-09-21 17:32:39 +0000385 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000386 __bucket_list_deallocator(__bucket_list_deallocator&& __x)
387 : __data_(_STD::move(__x.__data_))
388 {
389 __x.size() = 0;
390 }
391
Howard Hinnant73d21a42010-09-04 23:28:19 +0000392#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000393
Howard Hinnant99acc502010-09-21 17:32:39 +0000394 _LIBCPP_INLINE_VISIBILITY size_type& size() {return __data_.first();}
395 _LIBCPP_INLINE_VISIBILITY size_type size() const {return __data_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000396
Howard Hinnant99acc502010-09-21 17:32:39 +0000397 _LIBCPP_INLINE_VISIBILITY allocator_type& __alloc() {return __data_.second();}
398 _LIBCPP_INLINE_VISIBILITY const allocator_type& __alloc() const {return __data_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000399
Howard Hinnant99acc502010-09-21 17:32:39 +0000400 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000401 void operator()(pointer __p)
402 {
403 __alloc_traits::deallocate(__alloc(), __p, size());
404 }
405};
406
407template <class> class __hash_map_node_destructor;
408
409template <class _Alloc>
410class __hash_node_destructor
411{
412 typedef _Alloc allocator_type;
413 typedef allocator_traits<allocator_type> __alloc_traits;
414 typedef typename __alloc_traits::value_type::value_type value_type;
415public:
416 typedef typename __alloc_traits::pointer pointer;
417private:
418
419 allocator_type& __na_;
420
421 __hash_node_destructor& operator=(const __hash_node_destructor&);
422
423public:
424 bool __value_constructed;
425
Howard Hinnant99acc502010-09-21 17:32:39 +0000426 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000427 explicit __hash_node_destructor(allocator_type& __na)
428 : __na_(__na),
429 __value_constructed(false)
430 {}
431
Howard Hinnant99acc502010-09-21 17:32:39 +0000432 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000433 void operator()(pointer __p)
434 {
435 if (__value_constructed)
436 __alloc_traits::destroy(__na_, addressof(__p->__value_));
437 if (__p)
438 __alloc_traits::deallocate(__na_, __p, 1);
439 }
440
441 template <class> friend class __hash_map_node_destructor;
442};
443
444template <class _Tp, class _Hash, class _Equal, class _Alloc>
445class __hash_table
446{
447public:
448 typedef _Tp value_type;
449 typedef _Hash hasher;
450 typedef _Equal key_equal;
451 typedef _Alloc allocator_type;
452
453private:
454 typedef allocator_traits<allocator_type> __alloc_traits;
455public:
456 typedef value_type& reference;
457 typedef const value_type& const_reference;
458 typedef typename __alloc_traits::pointer pointer;
459 typedef typename __alloc_traits::const_pointer const_pointer;
460 typedef typename __alloc_traits::size_type size_type;
461 typedef typename __alloc_traits::difference_type difference_type;
462public:
463 // Create __node
464 typedef __hash_node<value_type, typename __alloc_traits::void_pointer> __node;
465 typedef typename __node::__first_node __first_node;
466 typedef typename __alloc_traits::template
467#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
468 rebind_alloc<__node>
469#else
470 rebind_alloc<__node>::other
471#endif
472 __node_allocator;
473 typedef allocator_traits<__node_allocator> __node_traits;
474 typedef typename __node_traits::pointer __node_pointer;
475 typedef typename __node_traits::const_pointer __node_const_pointer;
476
477private:
478
479 typedef typename __node_traits::template
480#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
481 rebind_alloc<__node_pointer>
482#else
483 rebind_alloc<__node_pointer>::other
484#endif
485 __pointer_allocator;
486 typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter;
487 typedef unique_ptr<__node_pointer[], __bucket_list_deleter> __bucket_list;
488 typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits;
489 typedef typename __bucket_list_deleter::pointer __node_pointer_pointer;
490
491 // --- Member data begin ---
492 __bucket_list __bucket_list_;
493 __compressed_pair<__first_node, __node_allocator> __p1_;
494 __compressed_pair<size_type, hasher> __p2_;
495 __compressed_pair<float, key_equal> __p3_;
496 // --- Member data end ---
497
Howard Hinnant99acc502010-09-21 17:32:39 +0000498 _LIBCPP_INLINE_VISIBILITY size_type& size() {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000499public:
Howard Hinnant99acc502010-09-21 17:32:39 +0000500 _LIBCPP_INLINE_VISIBILITY size_type size() const {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000501
Howard Hinnant99acc502010-09-21 17:32:39 +0000502 _LIBCPP_INLINE_VISIBILITY hasher& hash_function() {return __p2_.second();}
503 _LIBCPP_INLINE_VISIBILITY const hasher& hash_function() const {return __p2_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000504
Howard Hinnant99acc502010-09-21 17:32:39 +0000505 _LIBCPP_INLINE_VISIBILITY float& max_load_factor() {return __p3_.first();}
506 _LIBCPP_INLINE_VISIBILITY float max_load_factor() const {return __p3_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000507
Howard Hinnant99acc502010-09-21 17:32:39 +0000508 _LIBCPP_INLINE_VISIBILITY key_equal& key_eq() {return __p3_.second();}
509 _LIBCPP_INLINE_VISIBILITY const key_equal& key_eq() const {return __p3_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000510
Howard Hinnant99acc502010-09-21 17:32:39 +0000511 _LIBCPP_INLINE_VISIBILITY __node_allocator& __node_alloc() {return __p1_.second();}
512 _LIBCPP_INLINE_VISIBILITY const __node_allocator& __node_alloc() const {return __p1_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000513
514public:
515 typedef __hash_iterator<__node_pointer> iterator;
516 typedef __hash_const_iterator<__node_const_pointer> const_iterator;
517 typedef __hash_local_iterator<__node_pointer> local_iterator;
518 typedef __hash_const_local_iterator<__node_const_pointer> const_local_iterator;
519
520 __hash_table();
521 __hash_table(const hasher& __hf, const key_equal& __eql);
522 __hash_table(const hasher& __hf, const key_equal& __eql,
523 const allocator_type& __a);
524 explicit __hash_table(const allocator_type& __a);
525 __hash_table(const __hash_table& __u);
526 __hash_table(const __hash_table& __u, const allocator_type& __a);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000527#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000528 __hash_table(__hash_table&& __u);
529 __hash_table(__hash_table&& __u, const allocator_type& __a);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000530#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000531 ~__hash_table();
532
533 __hash_table& operator=(const __hash_table& __u);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000534#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000535 __hash_table& operator=(__hash_table&& __u);
536#endif
537 template <class _InputIterator>
538 void __assign_unique(_InputIterator __first, _InputIterator __last);
539 template <class _InputIterator>
540 void __assign_multi(_InputIterator __first, _InputIterator __last);
541
Howard Hinnant99acc502010-09-21 17:32:39 +0000542 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000543 size_type max_size() const
544 {
545 return allocator_traits<__pointer_allocator>::max_size(
546 __bucket_list_.get_deleter().__alloc());
547 }
548
549 pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
550 iterator __node_insert_multi(__node_pointer __nd);
551 iterator __node_insert_multi(const_iterator __p,
552 __node_pointer __nd);
553
Howard Hinnant73d21a42010-09-04 23:28:19 +0000554#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000555 template <class... _Args>
556 pair<iterator, bool> __emplace_unique(_Args&&... __args);
557 template <class... _Args>
558 iterator __emplace_multi(_Args&&... __args);
559 template <class... _Args>
560 iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000561#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000562
563 pair<iterator, bool> __insert_unique(const value_type& __x);
564
Howard Hinnant73d21a42010-09-04 23:28:19 +0000565#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000566 template <class _P>
567 pair<iterator, bool> __insert_unique(_P&& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000568#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000569
Howard Hinnant73d21a42010-09-04 23:28:19 +0000570#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000571 template <class _P>
572 iterator __insert_multi(_P&& __x);
573 template <class _P>
574 iterator __insert_multi(const_iterator __p, _P&& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000575#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000576 iterator __insert_multi(const value_type& __x);
577 iterator __insert_multi(const_iterator __p, const value_type& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000578#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000579
580 void clear();
581 void rehash(size_type __n);
Howard Hinnant99acc502010-09-21 17:32:39 +0000582 _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000583 {rehash(static_cast<size_type>(ceil(__n / max_load_factor())));}
Howard Hinnant99acc502010-09-21 17:32:39 +0000584
585 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000586 size_type bucket_count() const
587 {
588 return __bucket_list_.get_deleter().size();
589 }
590
591 iterator begin();
592 iterator end();
593 const_iterator begin() const;
594 const_iterator end() const;
595
596 template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39 +0000597 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000598 size_type bucket(const _Key& __k) const
599 {return hash_function()(__k) % bucket_count();}
600
601 template <class _Key>
602 iterator find(const _Key& __x);
603 template <class _Key>
604 const_iterator find(const _Key& __x) const;
605
606 typedef __hash_node_destructor<__node_allocator> _D;
607 typedef unique_ptr<__node, _D> __node_holder;
608
609 iterator erase(const_iterator __p);
610 iterator erase(const_iterator __first, const_iterator __last);
611 template <class _Key>
612 size_type __erase_unique(const _Key& __k);
613 template <class _Key>
614 size_type __erase_multi(const _Key& __k);
615 __node_holder remove(const_iterator __p);
616
617 template <class _Key>
618 size_type __count_unique(const _Key& __k) const;
619 template <class _Key>
620 size_type __count_multi(const _Key& __k) const;
621
622 template <class _Key>
623 pair<iterator, iterator>
624 __equal_range_unique(const _Key& __k);
625 template <class _Key>
626 pair<const_iterator, const_iterator>
627 __equal_range_unique(const _Key& __k) const;
628
629 template <class _Key>
630 pair<iterator, iterator>
631 __equal_range_multi(const _Key& __k);
632 template <class _Key>
633 pair<const_iterator, const_iterator>
634 __equal_range_multi(const _Key& __k) const;
635
636 void swap(__hash_table& __u);
637
Howard Hinnant99acc502010-09-21 17:32:39 +0000638 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000639 size_type max_bucket_count() const
640 {return __bucket_list_.get_deleter().__alloc().max_size();}
641 size_type bucket_size(size_type __n) const;
Howard Hinnant99acc502010-09-21 17:32:39 +0000642 _LIBCPP_INLINE_VISIBILITY float load_factor() const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000643 {
644 size_type __bc = bucket_count();
645 return __bc != 0 ? (float)size() / __bc : 0.f;
646 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000647 _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000648 {max_load_factor() = _STD::max(__mlf, load_factor());}
649
Howard Hinnant99acc502010-09-21 17:32:39 +0000650 _LIBCPP_INLINE_VISIBILITY local_iterator begin(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000651 {return local_iterator(__bucket_list_[__n], __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000652 _LIBCPP_INLINE_VISIBILITY local_iterator end(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000653 {return local_iterator(nullptr, __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000654 _LIBCPP_INLINE_VISIBILITY const_local_iterator cbegin(size_type __n) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000655 {return const_local_iterator(__bucket_list_[__n], __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000656 _LIBCPP_INLINE_VISIBILITY const_local_iterator cend(size_type __n) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000657 {return const_local_iterator(nullptr, __n, bucket_count());}
658private:
659 void __rehash(size_type __n);
660
Howard Hinnant73d21a42010-09-04 23:28:19 +0000661#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
662#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000663 template <class ..._Args>
664 __node_holder __construct_node(_Args&& ...__args);
Howard Hinnantbfd55302010-09-04 23:46:48 +0000665#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000666 __node_holder __construct_node(value_type&& __v, size_t __hash);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000667#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000668 __node_holder __construct_node(const value_type& __v);
669#endif
670 __node_holder __construct_node(const value_type& __v, size_t __hash);
671
Howard Hinnant99acc502010-09-21 17:32:39 +0000672 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000673 void __copy_assign_alloc(const __hash_table& __u)
674 {__copy_assign_alloc(__u, integral_constant<bool,
675 __node_traits::propagate_on_container_copy_assignment::value>());}
676 void __copy_assign_alloc(const __hash_table& __u, true_type);
Howard Hinnant99acc502010-09-21 17:32:39 +0000677 _LIBCPP_INLINE_VISIBILITY
678 void __copy_assign_alloc(const __hash_table& __u, false_type) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000679
680 void __move_assign(__hash_table& __u, false_type);
681 void __move_assign(__hash_table& __u, true_type);
Howard Hinnant99acc502010-09-21 17:32:39 +0000682 _LIBCPP_INLINE_VISIBILITY void __move_assign_alloc(__hash_table& __u)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000683 {__move_assign_alloc(__u, integral_constant<bool,
684 __node_traits::propagate_on_container_move_assignment::value>());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000685 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000686 void __move_assign_alloc(__hash_table& __u, true_type)
687 {
688 __bucket_list_.get_deleter().__alloc() =
689 _STD::move(__u.__bucket_list_.get_deleter().__alloc());
690 __node_alloc() = _STD::move(__u.__node_alloc());
691 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000692 _LIBCPP_INLINE_VISIBILITY
693 void __move_assign_alloc(__hash_table&, false_type) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000694
695 template <class _A>
Howard Hinnant99acc502010-09-21 17:32:39 +0000696 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000697 static
698 void
699 __swap_alloc(_A& __x, _A& __y)
700 {
701 __swap_alloc(__x, __y,
702 integral_constant<bool,
703 allocator_traits<_A>::propagate_on_container_swap::value
704 >());
705 }
706
707 template <class _A>
Howard Hinnant99acc502010-09-21 17:32:39 +0000708 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000709 static
710 void
711 __swap_alloc(_A& __x, _A& __y, true_type)
712 {
713 using _STD::swap;
714 swap(__x, __y);
715 }
716
717 template <class _A>
Howard Hinnant99acc502010-09-21 17:32:39 +0000718 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000719 static
720 void
721 __swap_alloc(_A& __x, _A& __y, false_type) {}
722
723 void __deallocate(__node_pointer __np);
724 __node_pointer __detach();
725};
726
727template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +0000728inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000729__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table()
730 : __p2_(0),
731 __p3_(1.0f)
732{
733}
734
735template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +0000736inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000737__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
738 const key_equal& __eql)
739 : __bucket_list_(nullptr, __bucket_list_deleter()),
740 __p1_(),
741 __p2_(0, __hf),
742 __p3_(1.0f, __eql)
743{
744}
745
746template <class _Tp, class _Hash, class _Equal, class _Alloc>
747__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
748 const key_equal& __eql,
749 const allocator_type& __a)
750 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
751 __p1_(__node_allocator(__a)),
752 __p2_(0, __hf),
753 __p3_(1.0f, __eql)
754{
755}
756
757template <class _Tp, class _Hash, class _Equal, class _Alloc>
758__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
759 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
760 __p1_(__node_allocator(__a)),
761 __p2_(0),
762 __p3_(1.0f)
763{
764}
765
766template <class _Tp, class _Hash, class _Equal, class _Alloc>
767__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
768 : __bucket_list_(nullptr,
769 __bucket_list_deleter(allocator_traits<__pointer_allocator>::
770 select_on_container_copy_construction(
771 __u.__bucket_list_.get_deleter().__alloc()), 0)),
772 __p1_(allocator_traits<__node_allocator>::
773 select_on_container_copy_construction(__u.__node_alloc())),
774 __p2_(0, __u.hash_function()),
775 __p3_(__u.__p3_)
776{
777}
778
779template <class _Tp, class _Hash, class _Equal, class _Alloc>
780__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u,
781 const allocator_type& __a)
782 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
783 __p1_(__node_allocator(__a)),
784 __p2_(0, __u.hash_function()),
785 __p3_(__u.__p3_)
786{
787}
788
Howard Hinnant73d21a42010-09-04 23:28:19 +0000789#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000790
791template <class _Tp, class _Hash, class _Equal, class _Alloc>
792__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u)
793 : __bucket_list_(_STD::move(__u.__bucket_list_)),
794 __p1_(_STD::move(__u.__p1_)),
795 __p2_(_STD::move(__u.__p2_)),
796 __p3_(_STD::move(__u.__p3_))
797{
798 if (size() > 0)
799 {
800 __bucket_list_[__p1_.first().__next_->__hash_ % bucket_count()] =
801 static_cast<__node_pointer>(addressof(__p1_.first()));
802 __u.__p1_.first().__next_ = nullptr;
803 __u.size() = 0;
804 }
805}
806
807template <class _Tp, class _Hash, class _Equal, class _Alloc>
808__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u,
809 const allocator_type& __a)
810 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
811 __p1_(__node_allocator(__a)),
812 __p2_(0, _STD::move(__u.hash_function())),
813 __p3_(_STD::move(__u.__p3_))
814{
815 if (__a == allocator_type(__u.__node_alloc()))
816 {
817 __bucket_list_.reset(__u.__bucket_list_.release());
818 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
819 __u.__bucket_list_.get_deleter().size() = 0;
820 if (__u.size() > 0)
821 {
822 __p1_.first().__next_ = __u.__p1_.first().__next_;
823 __u.__p1_.first().__next_ = nullptr;
824 __bucket_list_[__p1_.first().__next_->__hash_ % bucket_count()] =
825 static_cast<__node_pointer>(addressof(__p1_.first()));
826 size() = __u.size();
827 __u.size() = 0;
828 }
829 }
830}
831
Howard Hinnant73d21a42010-09-04 23:28:19 +0000832#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000833
834template <class _Tp, class _Hash, class _Equal, class _Alloc>
835__hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table()
836{
837 __deallocate(__p1_.first().__next_);
838}
839
840template <class _Tp, class _Hash, class _Equal, class _Alloc>
841void
842__hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc(
843 const __hash_table& __u, true_type)
844{
845 if (__node_alloc() != __u.__node_alloc())
846 {
847 clear();
848 __bucket_list_.reset();
849 __bucket_list_.get_deleter().size() = 0;
850 }
851 __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc();
852 __node_alloc() = __u.__node_alloc();
853}
854
855template <class _Tp, class _Hash, class _Equal, class _Alloc>
856__hash_table<_Tp, _Hash, _Equal, _Alloc>&
857__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u)
858{
859 if (this != &__u)
860 {
861 __copy_assign_alloc(__u);
862 hash_function() = __u.hash_function();
863 key_eq() = __u.key_eq();
864 max_load_factor() = __u.max_load_factor();
865 __assign_multi(__u.begin(), __u.end());
866 }
867 return *this;
868}
869
870template <class _Tp, class _Hash, class _Equal, class _Alloc>
871void
872__hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate(__node_pointer __np)
873{
874 __node_allocator& __na = __node_alloc();
875 while (__np != nullptr)
876 {
877 __node_pointer __next = __np->__next_;
878 __node_traits::destroy(__na, addressof(__np->__value_));
879 __node_traits::deallocate(__na, __np, 1);
880 __np = __next;
881 }
882}
883
884template <class _Tp, class _Hash, class _Equal, class _Alloc>
885typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_pointer
886__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach()
887{
888 size_type __bc = bucket_count();
889 for (size_type __i = 0; __i < __bc; ++__i)
890 __bucket_list_[__i] = nullptr;
891 size() = 0;
892 __node_pointer __cache = __p1_.first().__next_;
893 __p1_.first().__next_ = nullptr;
894 return __cache;
895}
896
Howard Hinnant73d21a42010-09-04 23:28:19 +0000897#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000898
899template <class _Tp, class _Hash, class _Equal, class _Alloc>
900void
901__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
902 __hash_table& __u, true_type)
903{
904 clear();
905 __bucket_list_.reset(__u.__bucket_list_.release());
906 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
907 __u.__bucket_list_.get_deleter().size() = 0;
908 __move_assign_alloc(__u);
909 size() = __u.size();
910 hash_function() = _STD::move(__u.hash_function());
911 max_load_factor() = __u.max_load_factor();
912 key_eq() = _STD::move(__u.key_eq());
913 __p1_.first().__next_ = __u.__p1_.first().__next_;
914 if (size() > 0)
915 {
916 __bucket_list_[__p1_.first().__next_->__hash_ % bucket_count()] =
917 static_cast<__node_pointer>(addressof(__p1_.first()));
918 __u.__p1_.first().__next_ = nullptr;
919 __u.size() = 0;
920 }
921}
922
923template <class _Tp, class _Hash, class _Equal, class _Alloc>
924void
925__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
926 __hash_table& __u, false_type)
927{
928 if (__node_alloc() == __u.__node_alloc())
929 __move_assign(__u, true_type());
930 else
931 {
932 hash_function() = _STD::move(__u.hash_function());
933 key_eq() = _STD::move(__u.key_eq());
934 max_load_factor() = __u.max_load_factor();
935 if (bucket_count() != 0)
936 {
937 __node_pointer __cache = __detach();
938#ifndef _LIBCPP_NO_EXCEPTIONS
939 try
940 {
Howard Hinnant324bb032010-08-22 00:02:43 +0000941#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000942 const_iterator __i = __u.begin();
943 while (__cache != nullptr && __u.size() != 0)
944 {
945 __cache->__value_ = _STD::move(__u.remove(__i++)->__value_);
946 __node_pointer __next = __cache->__next_;
947 __node_insert_multi(__cache);
948 __cache = __next;
949 }
950#ifndef _LIBCPP_NO_EXCEPTIONS
951 }
952 catch (...)
953 {
954 __deallocate(__cache);
955 throw;
956 }
Howard Hinnant324bb032010-08-22 00:02:43 +0000957#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000958 __deallocate(__cache);
959 }
960 const_iterator __i = __u.begin();
961 while (__u.size() != 0)
962 {
963 __node_holder __h =
964 __construct_node(_STD::move(__u.remove(__i++)->__value_));
965 __node_insert_multi(__h.get());
966 __h.release();
967 }
968 }
969}
970
971template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +0000972inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000973__hash_table<_Tp, _Hash, _Equal, _Alloc>&
974__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u)
975{
976 __move_assign(__u, integral_constant<bool,
977 __node_traits::propagate_on_container_move_assignment::value>());
978 return *this;
979}
980
Howard Hinnant73d21a42010-09-04 23:28:19 +0000981#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000982
983template <class _Tp, class _Hash, class _Equal, class _Alloc>
984template <class _InputIterator>
985void
986__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first,
987 _InputIterator __last)
988{
989 if (bucket_count() != 0)
990 {
991 __node_pointer __cache = __detach();
992#ifndef _LIBCPP_NO_EXCEPTIONS
993 try
994 {
Howard Hinnant324bb032010-08-22 00:02:43 +0000995#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000996 for (; __cache != nullptr && __first != __last; ++__first)
997 {
998 __cache->__value_ = *__first;
999 __node_pointer __next = __cache->__next_;
1000 __node_insert_unique(__cache);
1001 __cache = __next;
1002 }
1003#ifndef _LIBCPP_NO_EXCEPTIONS
1004 }
1005 catch (...)
1006 {
1007 __deallocate(__cache);
1008 throw;
1009 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001010#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001011 __deallocate(__cache);
1012 }
1013 for (; __first != __last; ++__first)
1014 __insert_unique(*__first);
1015}
1016
1017template <class _Tp, class _Hash, class _Equal, class _Alloc>
1018template <class _InputIterator>
1019void
1020__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first,
1021 _InputIterator __last)
1022{
1023 if (bucket_count() != 0)
1024 {
1025 __node_pointer __cache = __detach();
1026#ifndef _LIBCPP_NO_EXCEPTIONS
1027 try
1028 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001029#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001030 for (; __cache != nullptr && __first != __last; ++__first)
1031 {
1032 __cache->__value_ = *__first;
1033 __node_pointer __next = __cache->__next_;
1034 __node_insert_multi(__cache);
1035 __cache = __next;
1036 }
1037#ifndef _LIBCPP_NO_EXCEPTIONS
1038 }
1039 catch (...)
1040 {
1041 __deallocate(__cache);
1042 throw;
1043 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001044#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001045 __deallocate(__cache);
1046 }
1047 for (; __first != __last; ++__first)
1048 __insert_multi(*__first);
1049}
1050
1051template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001052inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001053typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1054__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin()
1055{
1056 return iterator(__p1_.first().__next_);
1057}
1058
1059template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001060inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001061typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1062__hash_table<_Tp, _Hash, _Equal, _Alloc>::end()
1063{
1064 return iterator(nullptr);
1065}
1066
1067template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001068inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001069typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1070__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const
1071{
1072 return const_iterator(__p1_.first().__next_);
1073}
1074
1075template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001076inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001077typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1078__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const
1079{
1080 return const_iterator(nullptr);
1081}
1082
1083template <class _Tp, class _Hash, class _Equal, class _Alloc>
1084void
1085__hash_table<_Tp, _Hash, _Equal, _Alloc>::clear()
1086{
1087 if (size() > 0)
1088 {
1089 __deallocate(__p1_.first().__next_);
1090 __p1_.first().__next_ = nullptr;
1091 size_type __bc = bucket_count();
1092 for (size_type __i; __i < __bc; ++__i)
1093 __bucket_list_[__i] = nullptr;
1094 size() = 0;
1095 }
1096}
1097
1098template <class _Tp, class _Hash, class _Equal, class _Alloc>
1099pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1100__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd)
1101{
1102 __nd->__hash_ = hash_function()(__nd->__value_);
1103 size_type __bc = bucket_count();
1104 bool __inserted = false;
1105 __node_pointer __ndptr;
1106 size_t __chash;
1107 if (__bc != 0)
1108 {
1109 __chash = __nd->__hash_ % __bc;
1110 __ndptr = __bucket_list_[__chash];
1111 if (__ndptr != nullptr)
1112 {
1113 for (__ndptr = __ndptr->__next_; __ndptr != nullptr &&
1114 __ndptr->__hash_ % __bc == __chash;
1115 __ndptr = __ndptr->__next_)
1116 {
1117 if (key_eq()(__ndptr->__value_, __nd->__value_))
1118 goto __done;
1119 }
1120 }
1121 }
1122 {
1123 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1124 {
1125 rehash(_STD::max<size_type>(2 * __bc + 1,
1126 size_type(ceil(float(size() + 1) / max_load_factor()))));
1127 __bc = bucket_count();
1128 __chash = __nd->__hash_ % __bc;
1129 }
1130 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1131 __node_pointer __pn = __bucket_list_[__chash];
1132 if (__pn == nullptr)
1133 {
1134 __pn = static_cast<__node_pointer>(addressof(__p1_.first()));
1135 __nd->__next_ = __pn->__next_;
1136 __pn->__next_ = __nd;
1137 // fix up __bucket_list_
1138 __bucket_list_[__chash] = __pn;
1139 if (__nd->__next_ != nullptr)
1140 __bucket_list_[__nd->__next_->__hash_ % __bc] = __nd;
1141 }
1142 else
1143 {
1144 __nd->__next_ = __pn->__next_;
1145 __pn->__next_ = __nd;
1146 }
1147 __ndptr = __nd;
1148 // increment size
1149 ++size();
1150 __inserted = true;
1151 }
1152__done:
1153 return pair<iterator, bool>(iterator(__ndptr), __inserted);
1154}
1155
1156template <class _Tp, class _Hash, class _Equal, class _Alloc>
1157typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1158__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp)
1159{
1160 __cp->__hash_ = hash_function()(__cp->__value_);
1161 size_type __bc = bucket_count();
1162 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1163 {
1164 rehash(_STD::max<size_type>(2 * __bc + 1,
1165 size_type(ceil(float(size() + 1) / max_load_factor()))));
1166 __bc = bucket_count();
1167 }
1168 size_t __chash = __cp->__hash_ % __bc;
1169 __node_pointer __pn = __bucket_list_[__chash];
1170 if (__pn == nullptr)
1171 {
1172 __pn = static_cast<__node_pointer>(addressof(__p1_.first()));
1173 __cp->__next_ = __pn->__next_;
1174 __pn->__next_ = __cp;
1175 // fix up __bucket_list_
1176 __bucket_list_[__chash] = __pn;
1177 if (__cp->__next_ != nullptr)
1178 __bucket_list_[__cp->__next_->__hash_ % __bc] = __cp;
1179 }
1180 else
1181 {
1182 for (bool __found = false; __pn->__next_ != nullptr &&
1183 __pn->__next_->__hash_ % __bc == __chash;
1184 __pn = __pn->__next_)
Howard Hinnant324bb032010-08-22 00:02:43 +00001185 {
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001186 // __found key_eq() action
1187 // false false loop
1188 // true true loop
1189 // false true set __found to true
1190 // true false break
1191 if (__found != (__pn->__next_->__hash_ == __cp->__hash_ &&
1192 key_eq()(__pn->__next_->__value_, __cp->__value_)))
1193 {
1194 if (!__found)
1195 __found = true;
1196 else
1197 break;
1198 }
1199 }
1200 __cp->__next_ = __pn->__next_;
1201 __pn->__next_ = __cp;
1202 if (__cp->__next_ != nullptr)
1203 {
1204 size_t __nhash = __cp->__next_->__hash_ % __bc;
1205 if (__nhash != __chash)
1206 __bucket_list_[__nhash] = __cp;
1207 }
1208 }
1209 ++size();
1210 return iterator(__cp);
1211}
1212
1213template <class _Tp, class _Hash, class _Equal, class _Alloc>
1214typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1215__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(
1216 const_iterator __p, __node_pointer __cp)
1217{
1218 if (__p != end() && key_eq()(*__p, __cp->__value_))
1219 {
1220 __node_pointer __np = const_cast<__node_pointer>(__p.__node_);
1221 __cp->__hash_ = __np->__hash_;
1222 size_type __bc = bucket_count();
1223 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1224 {
1225 rehash(_STD::max<size_type>(2 * __bc + 1,
1226 size_type(ceil(float(size() + 1) / max_load_factor()))));
1227 __bc = bucket_count();
1228 }
1229 size_t __chash = __cp->__hash_ % __bc;
1230 __node_pointer __pp = __bucket_list_[__chash];
1231 while (__pp->__next_ != __np)
1232 __pp = __pp->__next_;
1233 __cp->__next_ = __np;
1234 __pp->__next_ = __cp;
1235 ++size();
1236 return iterator(__cp);
1237 }
1238 return __node_insert_multi(__cp);
1239}
1240
1241template <class _Tp, class _Hash, class _Equal, class _Alloc>
1242pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1243__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(const value_type& __x)
1244{
1245 size_t __hash = hash_function()(__x);
1246 size_type __bc = bucket_count();
1247 bool __inserted = false;
1248 __node_pointer __nd;
1249 size_t __chash;
1250 if (__bc != 0)
1251 {
1252 __chash = __hash % __bc;
1253 __nd = __bucket_list_[__chash];
1254 if (__nd != nullptr)
1255 {
1256 for (__nd = __nd->__next_; __nd != nullptr &&
1257 __nd->__hash_ % __bc == __chash;
1258 __nd = __nd->__next_)
1259 {
1260 if (key_eq()(__nd->__value_, __x))
1261 goto __done;
1262 }
1263 }
1264 }
1265 {
1266 __node_holder __h = __construct_node(__x, __hash);
1267 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1268 {
1269 rehash(_STD::max<size_type>(2 * __bc + 1,
1270 size_type(ceil(float(size() + 1) / max_load_factor()))));
1271 __bc = bucket_count();
1272 __chash = __hash % __bc;
1273 }
1274 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1275 __node_pointer __pn = __bucket_list_[__chash];
1276 if (__pn == nullptr)
1277 {
1278 __pn = static_cast<__node_pointer>(addressof(__p1_.first()));
1279 __h->__next_ = __pn->__next_;
1280 __pn->__next_ = __h.get();
1281 // fix up __bucket_list_
1282 __bucket_list_[__chash] = __pn;
1283 if (__h->__next_ != nullptr)
1284 __bucket_list_[__h->__next_->__hash_ % __bc] = __h.get();
1285 }
1286 else
1287 {
1288 __h->__next_ = __pn->__next_;
1289 __pn->__next_ = __h.get();
1290 }
1291 __nd = __h.release();
1292 // increment size
1293 ++size();
1294 __inserted = true;
1295 }
1296__done:
1297 return pair<iterator, bool>(iterator(__nd), __inserted);
1298}
1299
Howard Hinnant73d21a42010-09-04 23:28:19 +00001300#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1301#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001302
1303template <class _Tp, class _Hash, class _Equal, class _Alloc>
1304template <class... _Args>
1305pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1306__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique(_Args&&... __args)
1307{
1308 __node_holder __h = __construct_node(_STD::forward<_Args>(__args)...);
1309 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1310 if (__r.second)
1311 __h.release();
1312 return __r;
1313}
1314
1315template <class _Tp, class _Hash, class _Equal, class _Alloc>
1316template <class... _Args>
1317typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1318__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args)
1319{
1320 __node_holder __h = __construct_node(_STD::forward<_Args>(__args)...);
1321 iterator __r = __node_insert_multi(__h.get());
1322 __h.release();
1323 return __r;
1324}
1325
1326template <class _Tp, class _Hash, class _Equal, class _Alloc>
1327template <class... _Args>
1328typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1329__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi(
1330 const_iterator __p, _Args&&... __args)
1331{
1332 __node_holder __h = __construct_node(_STD::forward<_Args>(__args)...);
1333 iterator __r = __node_insert_multi(__p, __h.get());
1334 __h.release();
1335 return __r;
1336}
1337
Howard Hinnant73d21a42010-09-04 23:28:19 +00001338#endif // _LIBCPP_HAS_NO_VARIADICS
1339
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001340template <class _Tp, class _Hash, class _Equal, class _Alloc>
1341template <class _P>
1342pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1343__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(_P&& __x)
1344{
1345 __node_holder __h = __construct_node(_STD::forward<_P>(__x));
1346 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1347 if (__r.second)
1348 __h.release();
1349 return __r;
1350}
1351
Howard Hinnant73d21a42010-09-04 23:28:19 +00001352#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001353
Howard Hinnant73d21a42010-09-04 23:28:19 +00001354#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001355
1356template <class _Tp, class _Hash, class _Equal, class _Alloc>
1357template <class _P>
1358typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1359__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(_P&& __x)
1360{
1361 __node_holder __h = __construct_node(_STD::forward<_P>(__x));
1362 iterator __r = __node_insert_multi(__h.get());
1363 __h.release();
1364 return __r;
1365}
1366
1367template <class _Tp, class _Hash, class _Equal, class _Alloc>
1368template <class _P>
1369typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1370__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
1371 _P&& __x)
1372{
1373 __node_holder __h = __construct_node(_STD::forward<_P>(__x));
1374 iterator __r = __node_insert_multi(__p, __h.get());
1375 __h.release();
1376 return __r;
1377}
1378
Howard Hinnant73d21a42010-09-04 23:28:19 +00001379#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001380
1381template <class _Tp, class _Hash, class _Equal, class _Alloc>
1382typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1383__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const value_type& __x)
1384{
1385 __node_holder __h = __construct_node(__x);
1386 iterator __r = __node_insert_multi(__h.get());
1387 __h.release();
1388 return __r;
1389}
1390
1391template <class _Tp, class _Hash, class _Equal, class _Alloc>
1392typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1393__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
1394 const value_type& __x)
1395{
1396 __node_holder __h = __construct_node(__x);
1397 iterator __r = __node_insert_multi(__p, __h.get());
1398 __h.release();
1399 return __r;
1400}
1401
Howard Hinnant73d21a42010-09-04 23:28:19 +00001402#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001403
1404template <class _Tp, class _Hash, class _Equal, class _Alloc>
1405void
1406__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n)
1407{
1408 __n = __next_prime(_STD::max<size_type>(__n, size() > 0));
1409 size_type __bc = bucket_count();
1410 if (__n > __bc)
1411 __rehash(__n);
1412 else
1413 {
1414 __n = _STD::max<size_type>
1415 (
1416 __n,
1417 __next_prime(size_t(ceil(float(size()) / max_load_factor())))
1418 );
1419 if (__n < __bc)
1420 __rehash(__n);
1421 }
1422}
1423
1424template <class _Tp, class _Hash, class _Equal, class _Alloc>
1425void
1426__hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc)
1427{
1428 __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc();
1429 __bucket_list_.reset(__nbc > 0 ?
1430 __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr);
1431 __bucket_list_.get_deleter().size() = __nbc;
1432 if (__nbc > 0)
1433 {
1434 for (size_type __i = 0; __i < __nbc; ++__i)
1435 __bucket_list_[__i] = nullptr;
1436 __node_pointer __pp(static_cast<__node_pointer>(addressof(__p1_.first())));
1437 __node_pointer __cp = __pp->__next_;
1438 if (__cp != nullptr)
1439 {
1440 size_type __chash = __cp->__hash_ % __nbc;
1441 __bucket_list_[__chash] = __pp;
1442 size_type __phash = __chash;
1443 for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr;
1444 __cp = __pp->__next_)
1445 {
1446 __chash = __cp->__hash_ % __nbc;
1447 if (__chash == __phash)
1448 __pp = __cp;
1449 else
1450 {
1451 if (__bucket_list_[__chash] == nullptr)
1452 {
1453 __bucket_list_[__chash] = __pp;
1454 __pp = __cp;
1455 __phash = __chash;
1456 }
1457 else
1458 {
1459 __node_pointer __np = __cp;
1460 for (; __np->__next_ != nullptr &&
1461 key_eq()(__cp->__value_, __np->__next_->__value_);
1462 __np = __np->__next_)
1463 ;
1464 __pp->__next_ = __np->__next_;
1465 __np->__next_ = __bucket_list_[__chash]->__next_;
1466 __bucket_list_[__chash]->__next_ = __cp;
Howard Hinnant324bb032010-08-22 00:02:43 +00001467
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001468 }
1469 }
1470 }
1471 }
1472 }
1473}
1474
1475template <class _Tp, class _Hash, class _Equal, class _Alloc>
1476template <class _Key>
1477typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1478__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k)
1479{
1480 size_t __hash = hash_function()(__k);
1481 size_type __bc = bucket_count();
1482 if (__bc != 0)
1483 {
1484 size_t __chash = __hash % __bc;
1485 __node_pointer __nd = __bucket_list_[__chash];
1486 if (__nd != nullptr)
1487 {
1488 for (__nd = __nd->__next_; __nd != nullptr &&
1489 __nd->__hash_ % __bc == __chash;
1490 __nd = __nd->__next_)
1491 {
1492 if (key_eq()(__nd->__value_, __k))
1493 return iterator(__nd);
1494 }
1495 }
1496 }
1497 return end();
1498}
1499
1500template <class _Tp, class _Hash, class _Equal, class _Alloc>
1501template <class _Key>
1502typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1503__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const
1504{
1505 size_t __hash = hash_function()(__k);
1506 size_type __bc = bucket_count();
1507 if (__bc != 0)
1508 {
1509 size_t __chash = __hash % __bc;
1510 __node_const_pointer __nd = __bucket_list_[__chash];
1511 if (__nd != nullptr)
1512 {
1513 for (__nd = __nd->__next_; __nd != nullptr &&
1514 __nd->__hash_ % __bc == __chash;
1515 __nd = __nd->__next_)
1516 {
1517 if (key_eq()(__nd->__value_, __k))
1518 return const_iterator(__nd);
1519 }
1520 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001521
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001522 }
1523 return end();
1524}
1525
Howard Hinnant73d21a42010-09-04 23:28:19 +00001526#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1527#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001528
1529template <class _Tp, class _Hash, class _Equal, class _Alloc>
1530template <class ..._Args>
1531typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1532__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args)
1533{
1534 __node_allocator& __na = __node_alloc();
1535 __node_holder __h(__node_traits::allocate(__na, 1), _D(__na));
1536 __node_traits::construct(__na, addressof(__h->__value_), _STD::forward<_Args>(__args)...);
1537 __h.get_deleter().__value_constructed = true;
1538 __h->__hash_ = hash_function()(__h->__value_);
1539 __h->__next_ = nullptr;
1540 return __h;
1541}
1542
Howard Hinnant73d21a42010-09-04 23:28:19 +00001543#endif // _LIBCPP_HAS_NO_VARIADICS
1544
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001545template <class _Tp, class _Hash, class _Equal, class _Alloc>
1546typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1547__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(value_type&& __v,
1548 size_t __hash)
1549{
1550 __node_allocator& __na = __node_alloc();
1551 __node_holder __h(__node_traits::allocate(__na, 1), _D(__na));
1552 __node_traits::construct(__na, addressof(__h->__value_), _STD::move(__v));
1553 __h.get_deleter().__value_constructed = true;
1554 __h->__hash_ = __hash;
1555 __h->__next_ = nullptr;
1556 return _STD::move(__h);
1557}
1558
Howard Hinnant73d21a42010-09-04 23:28:19 +00001559#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001560
1561template <class _Tp, class _Hash, class _Equal, class _Alloc>
1562typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1563__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v)
1564{
1565 __node_allocator& __na = __node_alloc();
1566 __node_holder __h(__node_traits::allocate(__na, 1), _D(__na));
1567 __node_traits::construct(__na, addressof(__h->__value_), __v);
1568 __h.get_deleter().__value_constructed = true;
1569 __h->__hash_ = hash_function()(__h->__value_);
1570 __h->__next_ = nullptr;
1571 return _STD::move(__h);
1572}
1573
Howard Hinnant73d21a42010-09-04 23:28:19 +00001574#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001575
1576template <class _Tp, class _Hash, class _Equal, class _Alloc>
1577typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1578__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v,
1579 size_t __hash)
1580{
1581 __node_allocator& __na = __node_alloc();
1582 __node_holder __h(__node_traits::allocate(__na, 1), _D(__na));
1583 __node_traits::construct(__na, addressof(__h->__value_), __v);
1584 __h.get_deleter().__value_constructed = true;
1585 __h->__hash_ = __hash;
1586 __h->__next_ = nullptr;
1587 return _STD::move(__h);
1588}
1589
1590template <class _Tp, class _Hash, class _Equal, class _Alloc>
1591typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1592__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p)
1593{
1594 __node_pointer __np = const_cast<__node_pointer>(__p.__node_);
1595 iterator __r(__np);
1596 ++__r;
1597 remove(__p);
1598 return __r;
1599}
1600
1601template <class _Tp, class _Hash, class _Equal, class _Alloc>
1602typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1603__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first,
1604 const_iterator __last)
1605{
1606 for (const_iterator __p = __first; __first != __last; __p = __first)
1607 {
1608 ++__first;
1609 erase(__p);
1610 }
1611 __node_pointer __np = const_cast<__node_pointer>(__last.__node_);
1612 return iterator (__np);
1613}
1614
1615template <class _Tp, class _Hash, class _Equal, class _Alloc>
1616template <class _Key>
1617typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1618__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k)
1619{
1620 iterator __i = find(__k);
1621 if (__i == end())
1622 return 0;
1623 erase(__i);
1624 return 1;
1625}
1626
1627template <class _Tp, class _Hash, class _Equal, class _Alloc>
1628template <class _Key>
1629typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1630__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k)
1631{
1632 size_type __r = 0;
1633 iterator __i = find(__k);
1634 if (__i != end())
1635 {
1636 iterator __e = end();
1637 do
1638 {
1639 erase(__i++);
1640 ++__r;
1641 } while (__i != __e && key_eq()(*__i, __k));
1642 }
1643 return __r;
1644}
1645
1646template <class _Tp, class _Hash, class _Equal, class _Alloc>
1647typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1648__hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p)
1649{
1650 // current node
1651 __node_pointer __cn = const_cast<__node_pointer>(__p.__node_);
1652 size_type __bc = bucket_count();
1653 size_t __chash = __cn->__hash_ % __bc;
1654 // find previous node
1655 __node_pointer __pn = __bucket_list_[__chash];
1656 for (; __pn->__next_ != __cn; __pn = __pn->__next_)
1657 ;
1658 // Fix up __bucket_list_
1659 // if __pn is not in same bucket (before begin is not in same bucket) &&
1660 // if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
1661 if (__pn == addressof(__p1_.first()) || __pn->__hash_ % __bc != __chash)
1662 {
1663 if (__cn->__next_ == nullptr || __cn->__next_->__hash_ % __bc != __chash)
1664 __bucket_list_[__chash] = nullptr;
1665 }
1666 // if __cn->__next_ is not in same bucket (nullptr is in same bucket)
1667 if (__cn->__next_ != nullptr)
1668 {
1669 size_t __nhash = __cn->__next_->__hash_ % __bc;
1670 if (__nhash != __chash)
1671 __bucket_list_[__nhash] = __pn;
1672 }
1673 // remove __cn
1674 __pn->__next_ = __cn->__next_;
1675 __cn->__next_ = nullptr;
1676 --size();
1677 return __node_holder(__cn, _D(__node_alloc()));
1678}
1679
1680template <class _Tp, class _Hash, class _Equal, class _Alloc>
1681template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39 +00001682inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001683typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1684__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const
1685{
1686 return static_cast<size_type>(find(__k) != end());
1687}
1688
1689template <class _Tp, class _Hash, class _Equal, class _Alloc>
1690template <class _Key>
1691typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1692__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const
1693{
1694 size_type __r = 0;
1695 const_iterator __i = find(__k);
1696 if (__i != end())
1697 {
1698 const_iterator __e = end();
1699 do
1700 {
1701 ++__i;
1702 ++__r;
1703 } while (__i != __e && key_eq()(*__i, __k));
1704 }
1705 return __r;
1706}
1707
1708template <class _Tp, class _Hash, class _Equal, class _Alloc>
1709template <class _Key>
1710pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
1711 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1712__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
1713 const _Key& __k)
1714{
1715 iterator __i = find(__k);
1716 iterator __j = __i;
1717 if (__i != end())
1718 ++__j;
1719 return pair<iterator, iterator>(__i, __j);
1720}
1721
1722template <class _Tp, class _Hash, class _Equal, class _Alloc>
1723template <class _Key>
1724pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
1725 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1726__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
1727 const _Key& __k) const
1728{
1729 const_iterator __i = find(__k);
1730 const_iterator __j = __i;
1731 if (__i != end())
1732 ++__j;
1733 return pair<const_iterator, const_iterator>(__i, __j);
1734}
1735
1736template <class _Tp, class _Hash, class _Equal, class _Alloc>
1737template <class _Key>
1738pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
1739 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1740__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
1741 const _Key& __k)
1742{
1743 iterator __i = find(__k);
1744 iterator __j = __i;
1745 if (__i != end())
1746 {
1747 iterator __e = end();
1748 do
1749 {
1750 ++__j;
1751 } while (__j != __e && key_eq()(*__j, __k));
1752 }
1753 return pair<iterator, iterator>(__i, __j);
1754}
1755
1756template <class _Tp, class _Hash, class _Equal, class _Alloc>
1757template <class _Key>
1758pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
1759 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1760__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
1761 const _Key& __k) const
1762{
1763 const_iterator __i = find(__k);
1764 const_iterator __j = __i;
1765 if (__i != end())
1766 {
1767 const_iterator __e = end();
1768 do
1769 {
1770 ++__j;
1771 } while (__j != __e && key_eq()(*__j, __k));
1772 }
1773 return pair<const_iterator, const_iterator>(__i, __j);
1774}
1775
1776template <class _Tp, class _Hash, class _Equal, class _Alloc>
1777void
1778__hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
1779{
1780 {
1781 __node_pointer_pointer __npp = __bucket_list_.release();
1782 __bucket_list_.reset(__u.__bucket_list_.release());
1783 __u.__bucket_list_.reset(__npp);
1784 }
1785 _STD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
1786 __swap_alloc(__bucket_list_.get_deleter().__alloc(),
1787 __u.__bucket_list_.get_deleter().__alloc());
1788 __swap_alloc(__node_alloc(), __u.__node_alloc());
1789 _STD::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
1790 __p2_.swap(__u.__p2_);
1791 __p3_.swap(__u.__p3_);
1792 if (size() > 0)
1793 __bucket_list_[__p1_.first().__next_->__hash_ % bucket_count()] =
1794 static_cast<__node_pointer>(addressof(__p1_.first()));
1795 if (__u.size() > 0)
1796 __u.__bucket_list_[__u.__p1_.first().__next_->__hash_ % __u.bucket_count()] =
1797 static_cast<__node_pointer>(addressof(__u.__p1_.first()));
1798}
1799
1800template <class _Tp, class _Hash, class _Equal, class _Alloc>
1801typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1802__hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const
1803{
1804 __node_const_pointer __np = __bucket_list_[__n];
1805 size_type __bc = bucket_count();
1806 size_type __r = 0;
1807 if (__np != nullptr)
1808 {
1809 for (__np = __np->__next_; __np != nullptr &&
1810 __np->__hash_ % __bc == __n;
1811 __np = __np->__next_, ++__r)
1812 ;
1813 }
1814 return __r;
1815}
1816
1817_LIBCPP_END_NAMESPACE_STD
1818
1819#endif // _LIBCPP__HASH_TABLE