blob: 2e371a424ff816ddfa8838715d87a2bb769eb499 [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;
Howard Hinnantdf85e572011-02-27 18:02:02 +000032 // typedef _NodePtr pointer;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000033
Howard Hinnantdf85e572011-02-27 18:02:02 +000034 _NodePtr __next_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000035
Howard Hinnant5f2f14c2011-06-04 18:54:24 +000036 _LIBCPP_INLINE_VISIBILITY __hash_node_base() _NOEXCEPT : __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 Hinnant5f2f14c2011-06-04 18:54:24 +000083 _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT {}
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
Howard Hinnant2529d022011-02-02 17:36:20 +000088 pointer operator->() const {return _STD::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 Hinnant5f2f14c2011-06-04 18:54:24 +0000114 __hash_iterator(__node_pointer __node) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000115 : __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 Hinnant5f2f14c2011-06-04 18:54:24 +0000157 _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000158 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000159 __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000160 : __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
Howard Hinnant2529d022011-02-02 17:36:20 +0000166 pointer operator->() const {return _STD::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 Hinnant5f2f14c2011-06-04 18:54:24 +0000192 __hash_const_iterator(__node_pointer __node) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000193 : __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 Hinnant5f2f14c2011-06-04 18:54:24 +0000227 _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT {}
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,
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000261 size_t __bucket_count) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000262 : __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 Hinnant5f2f14c2011-06-04 18:54:24 +0000311 _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000312 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000313 __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000314 : __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,
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000351 size_t __bucket_count) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000352 : __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()
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000377 _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000378 : __data_(0) {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000379
380 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000381 __bucket_list_deallocator(const allocator_type& __a, size_type __size)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000382 _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000383 : __data_(__size, __a) {}
384
Howard Hinnant73d21a42010-09-04 23:28:19 +0000385#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000386
Howard Hinnant99acc502010-09-21 17:32:39 +0000387 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000388 __bucket_list_deallocator(__bucket_list_deallocator&& __x)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000389 _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000390 : __data_(_STD::move(__x.__data_))
391 {
392 __x.size() = 0;
393 }
394
Howard Hinnant73d21a42010-09-04 23:28:19 +0000395#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000396
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000397 _LIBCPP_INLINE_VISIBILITY
398 size_type& size() _NOEXCEPT {return __data_.first();}
399 _LIBCPP_INLINE_VISIBILITY
400 size_type size() const _NOEXCEPT {return __data_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000401
Howard Hinnant99acc502010-09-21 17:32:39 +0000402 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000403 allocator_type& __alloc() _NOEXCEPT {return __data_.second();}
404 _LIBCPP_INLINE_VISIBILITY
405 const allocator_type& __alloc() const _NOEXCEPT {return __data_.second();}
406
407 _LIBCPP_INLINE_VISIBILITY
408 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000409 {
410 __alloc_traits::deallocate(__alloc(), __p, size());
411 }
412};
413
414template <class> class __hash_map_node_destructor;
415
416template <class _Alloc>
417class __hash_node_destructor
418{
419 typedef _Alloc allocator_type;
420 typedef allocator_traits<allocator_type> __alloc_traits;
421 typedef typename __alloc_traits::value_type::value_type value_type;
422public:
423 typedef typename __alloc_traits::pointer pointer;
424private:
425
426 allocator_type& __na_;
427
428 __hash_node_destructor& operator=(const __hash_node_destructor&);
429
430public:
431 bool __value_constructed;
432
Howard Hinnant99acc502010-09-21 17:32:39 +0000433 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000434 explicit __hash_node_destructor(allocator_type& __na) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000435 : __na_(__na),
436 __value_constructed(false)
437 {}
438
Howard Hinnant99acc502010-09-21 17:32:39 +0000439 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000440 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000441 {
442 if (__value_constructed)
Howard Hinnant2529d022011-02-02 17:36:20 +0000443 __alloc_traits::destroy(__na_, _STD::addressof(__p->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000444 if (__p)
445 __alloc_traits::deallocate(__na_, __p, 1);
446 }
447
448 template <class> friend class __hash_map_node_destructor;
449};
450
451template <class _Tp, class _Hash, class _Equal, class _Alloc>
452class __hash_table
453{
454public:
455 typedef _Tp value_type;
456 typedef _Hash hasher;
457 typedef _Equal key_equal;
458 typedef _Alloc allocator_type;
459
460private:
461 typedef allocator_traits<allocator_type> __alloc_traits;
462public:
463 typedef value_type& reference;
464 typedef const value_type& const_reference;
465 typedef typename __alloc_traits::pointer pointer;
466 typedef typename __alloc_traits::const_pointer const_pointer;
467 typedef typename __alloc_traits::size_type size_type;
468 typedef typename __alloc_traits::difference_type difference_type;
469public:
470 // Create __node
471 typedef __hash_node<value_type, typename __alloc_traits::void_pointer> __node;
472 typedef typename __node::__first_node __first_node;
473 typedef typename __alloc_traits::template
474#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
475 rebind_alloc<__node>
476#else
477 rebind_alloc<__node>::other
478#endif
479 __node_allocator;
480 typedef allocator_traits<__node_allocator> __node_traits;
481 typedef typename __node_traits::pointer __node_pointer;
482 typedef typename __node_traits::const_pointer __node_const_pointer;
483
484private:
485
486 typedef typename __node_traits::template
487#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
488 rebind_alloc<__node_pointer>
489#else
490 rebind_alloc<__node_pointer>::other
491#endif
492 __pointer_allocator;
493 typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter;
494 typedef unique_ptr<__node_pointer[], __bucket_list_deleter> __bucket_list;
495 typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits;
496 typedef typename __bucket_list_deleter::pointer __node_pointer_pointer;
497
498 // --- Member data begin ---
499 __bucket_list __bucket_list_;
500 __compressed_pair<__first_node, __node_allocator> __p1_;
501 __compressed_pair<size_type, hasher> __p2_;
502 __compressed_pair<float, key_equal> __p3_;
503 // --- Member data end ---
504
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000505 _LIBCPP_INLINE_VISIBILITY
506 size_type& size() _NOEXCEPT {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000507public:
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000508 _LIBCPP_INLINE_VISIBILITY
509 size_type size() const _NOEXCEPT {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000510
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000511 _LIBCPP_INLINE_VISIBILITY
512 hasher& hash_function() _NOEXCEPT {return __p2_.second();}
513 _LIBCPP_INLINE_VISIBILITY
514 const hasher& hash_function() const _NOEXCEPT {return __p2_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000515
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000516 _LIBCPP_INLINE_VISIBILITY
517 float& max_load_factor() _NOEXCEPT {return __p3_.first();}
518 _LIBCPP_INLINE_VISIBILITY
519 float max_load_factor() const _NOEXCEPT {return __p3_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000520
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000521 _LIBCPP_INLINE_VISIBILITY
522 key_equal& key_eq() _NOEXCEPT {return __p3_.second();}
523 _LIBCPP_INLINE_VISIBILITY
524 const key_equal& key_eq() const _NOEXCEPT {return __p3_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000525
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000526 _LIBCPP_INLINE_VISIBILITY
527 __node_allocator& __node_alloc() _NOEXCEPT {return __p1_.second();}
528 _LIBCPP_INLINE_VISIBILITY
529 const __node_allocator& __node_alloc() const _NOEXCEPT
530 {return __p1_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000531
532public:
533 typedef __hash_iterator<__node_pointer> iterator;
534 typedef __hash_const_iterator<__node_const_pointer> const_iterator;
535 typedef __hash_local_iterator<__node_pointer> local_iterator;
536 typedef __hash_const_local_iterator<__node_const_pointer> const_local_iterator;
537
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000538 __hash_table()
539 _NOEXCEPT_(
540 is_nothrow_default_constructible<__bucket_list>::value &&
541 is_nothrow_default_constructible<__first_node>::value &&
542 is_nothrow_default_constructible<__node_allocator>::value &&
543 is_nothrow_default_constructible<hasher>::value &&
544 is_nothrow_default_constructible<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000545 __hash_table(const hasher& __hf, const key_equal& __eql);
546 __hash_table(const hasher& __hf, const key_equal& __eql,
547 const allocator_type& __a);
548 explicit __hash_table(const allocator_type& __a);
549 __hash_table(const __hash_table& __u);
550 __hash_table(const __hash_table& __u, const allocator_type& __a);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000551#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000552 __hash_table(__hash_table&& __u)
553 _NOEXCEPT_(
554 is_nothrow_move_constructible<__bucket_list>::value &&
555 is_nothrow_move_constructible<__first_node>::value &&
556 is_nothrow_move_constructible<__node_allocator>::value &&
557 is_nothrow_move_constructible<hasher>::value &&
558 is_nothrow_move_constructible<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000559 __hash_table(__hash_table&& __u, const allocator_type& __a);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000560#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000561 ~__hash_table();
562
563 __hash_table& operator=(const __hash_table& __u);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000564#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000565 __hash_table& operator=(__hash_table&& __u)
566 _NOEXCEPT_(
567 __node_traits::propagate_on_container_move_assignment::value &&
568 is_nothrow_move_assignable<__node_allocator>::value &&
569 is_nothrow_move_assignable<hasher>::value &&
570 is_nothrow_move_assignable<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000571#endif
572 template <class _InputIterator>
573 void __assign_unique(_InputIterator __first, _InputIterator __last);
574 template <class _InputIterator>
575 void __assign_multi(_InputIterator __first, _InputIterator __last);
576
Howard Hinnant99acc502010-09-21 17:32:39 +0000577 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000578 size_type max_size() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000579 {
580 return allocator_traits<__pointer_allocator>::max_size(
581 __bucket_list_.get_deleter().__alloc());
582 }
583
584 pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
585 iterator __node_insert_multi(__node_pointer __nd);
586 iterator __node_insert_multi(const_iterator __p,
587 __node_pointer __nd);
588
Howard Hinnant73d21a42010-09-04 23:28:19 +0000589#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000590 template <class... _Args>
591 pair<iterator, bool> __emplace_unique(_Args&&... __args);
592 template <class... _Args>
593 iterator __emplace_multi(_Args&&... __args);
594 template <class... _Args>
595 iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000596#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000597
598 pair<iterator, bool> __insert_unique(const value_type& __x);
599
Howard Hinnant73d21a42010-09-04 23:28:19 +0000600#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000601 template <class _P>
602 pair<iterator, bool> __insert_unique(_P&& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000603#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000604
Howard Hinnant73d21a42010-09-04 23:28:19 +0000605#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000606 template <class _P>
607 iterator __insert_multi(_P&& __x);
608 template <class _P>
609 iterator __insert_multi(const_iterator __p, _P&& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000610#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000611 iterator __insert_multi(const value_type& __x);
612 iterator __insert_multi(const_iterator __p, const value_type& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000613#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000614
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000615 void clear() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000616 void rehash(size_type __n);
Howard Hinnant99acc502010-09-21 17:32:39 +0000617 _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000618 {rehash(static_cast<size_type>(ceil(__n / max_load_factor())));}
Howard Hinnant99acc502010-09-21 17:32:39 +0000619
620 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000621 size_type bucket_count() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000622 {
623 return __bucket_list_.get_deleter().size();
624 }
625
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000626 iterator begin() _NOEXCEPT;
627 iterator end() _NOEXCEPT;
628 const_iterator begin() const _NOEXCEPT;
629 const_iterator end() const _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000630
631 template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39 +0000632 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000633 size_type bucket(const _Key& __k) const
634 {return hash_function()(__k) % bucket_count();}
635
636 template <class _Key>
637 iterator find(const _Key& __x);
638 template <class _Key>
639 const_iterator find(const _Key& __x) const;
640
641 typedef __hash_node_destructor<__node_allocator> _D;
642 typedef unique_ptr<__node, _D> __node_holder;
643
644 iterator erase(const_iterator __p);
645 iterator erase(const_iterator __first, const_iterator __last);
646 template <class _Key>
647 size_type __erase_unique(const _Key& __k);
648 template <class _Key>
649 size_type __erase_multi(const _Key& __k);
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000650 __node_holder remove(const_iterator __p) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000651
652 template <class _Key>
653 size_type __count_unique(const _Key& __k) const;
654 template <class _Key>
655 size_type __count_multi(const _Key& __k) const;
656
657 template <class _Key>
658 pair<iterator, iterator>
659 __equal_range_unique(const _Key& __k);
660 template <class _Key>
661 pair<const_iterator, const_iterator>
662 __equal_range_unique(const _Key& __k) const;
663
664 template <class _Key>
665 pair<iterator, iterator>
666 __equal_range_multi(const _Key& __k);
667 template <class _Key>
668 pair<const_iterator, const_iterator>
669 __equal_range_multi(const _Key& __k) const;
670
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000671 void swap(__hash_table& __u)
672 _NOEXCEPT_(
673 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
674 __is_nothrow_swappable<__pointer_allocator>::value) &&
675 (!__node_traits::propagate_on_container_swap::value ||
676 __is_nothrow_swappable<__node_allocator>::value) &&
677 __is_nothrow_swappable<hasher>::value &&
678 __is_nothrow_swappable<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000679
Howard Hinnant99acc502010-09-21 17:32:39 +0000680 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000681 size_type max_bucket_count() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000682 {return __bucket_list_.get_deleter().__alloc().max_size();}
683 size_type bucket_size(size_type __n) const;
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000684 _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000685 {
686 size_type __bc = bucket_count();
687 return __bc != 0 ? (float)size() / __bc : 0.f;
688 }
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000689 _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000690 {max_load_factor() = _STD::max(__mlf, load_factor());}
691
Howard Hinnant99acc502010-09-21 17:32:39 +0000692 _LIBCPP_INLINE_VISIBILITY local_iterator begin(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000693 {return local_iterator(__bucket_list_[__n], __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000694 _LIBCPP_INLINE_VISIBILITY local_iterator end(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000695 {return local_iterator(nullptr, __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000696 _LIBCPP_INLINE_VISIBILITY const_local_iterator cbegin(size_type __n) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000697 {return const_local_iterator(__bucket_list_[__n], __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000698 _LIBCPP_INLINE_VISIBILITY const_local_iterator cend(size_type __n) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000699 {return const_local_iterator(nullptr, __n, bucket_count());}
700private:
701 void __rehash(size_type __n);
702
Howard Hinnant73d21a42010-09-04 23:28:19 +0000703#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
704#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000705 template <class ..._Args>
706 __node_holder __construct_node(_Args&& ...__args);
Howard Hinnantbfd55302010-09-04 23:46:48 +0000707#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000708 __node_holder __construct_node(value_type&& __v, size_t __hash);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000709#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000710 __node_holder __construct_node(const value_type& __v);
711#endif
712 __node_holder __construct_node(const value_type& __v, size_t __hash);
713
Howard Hinnant99acc502010-09-21 17:32:39 +0000714 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000715 void __copy_assign_alloc(const __hash_table& __u)
716 {__copy_assign_alloc(__u, integral_constant<bool,
717 __node_traits::propagate_on_container_copy_assignment::value>());}
718 void __copy_assign_alloc(const __hash_table& __u, true_type);
Howard Hinnant99acc502010-09-21 17:32:39 +0000719 _LIBCPP_INLINE_VISIBILITY
720 void __copy_assign_alloc(const __hash_table& __u, false_type) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000721
722 void __move_assign(__hash_table& __u, false_type);
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000723 void __move_assign(__hash_table& __u, true_type)
724 _NOEXCEPT_(
725 is_nothrow_move_assignable<__node_allocator>::value &&
726 is_nothrow_move_assignable<hasher>::value &&
727 is_nothrow_move_assignable<key_equal>::value);
728 _LIBCPP_INLINE_VISIBILITY
729 void __move_assign_alloc(__hash_table& __u)
730 _NOEXCEPT_(
731 !__node_traits::propagate_on_container_move_assignment::value ||
732 (is_nothrow_move_assignable<__pointer_allocator>::value &&
733 is_nothrow_move_assignable<__node_allocator>::value))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000734 {__move_assign_alloc(__u, integral_constant<bool,
735 __node_traits::propagate_on_container_move_assignment::value>());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000736 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000737 void __move_assign_alloc(__hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000738 _NOEXCEPT_(
739 is_nothrow_move_assignable<__pointer_allocator>::value &&
740 is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000741 {
742 __bucket_list_.get_deleter().__alloc() =
743 _STD::move(__u.__bucket_list_.get_deleter().__alloc());
744 __node_alloc() = _STD::move(__u.__node_alloc());
745 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000746 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000747 void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000748
749 template <class _A>
Howard Hinnant99acc502010-09-21 17:32:39 +0000750 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000751 static
752 void
753 __swap_alloc(_A& __x, _A& __y)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000754 _NOEXCEPT_(
755 !allocator_traits<_A>::propagate_on_container_swap::value ||
756 __is_nothrow_swappable<_A>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000757 {
758 __swap_alloc(__x, __y,
759 integral_constant<bool,
760 allocator_traits<_A>::propagate_on_container_swap::value
761 >());
762 }
763
764 template <class _A>
Howard Hinnant99acc502010-09-21 17:32:39 +0000765 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000766 static
767 void
768 __swap_alloc(_A& __x, _A& __y, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000769 _NOEXCEPT_(__is_nothrow_swappable<_A>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000770 {
771 using _STD::swap;
772 swap(__x, __y);
773 }
774
775 template <class _A>
Howard Hinnant99acc502010-09-21 17:32:39 +0000776 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000777 static
778 void
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000779 __swap_alloc(_A& __x, _A& __y, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000780
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000781 void __deallocate(__node_pointer __np) _NOEXCEPT;
782 __node_pointer __detach() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000783};
784
785template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +0000786inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000787__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table()
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000788 _NOEXCEPT_(
789 is_nothrow_default_constructible<__bucket_list>::value &&
790 is_nothrow_default_constructible<__first_node>::value &&
791 is_nothrow_default_constructible<hasher>::value &&
792 is_nothrow_default_constructible<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000793 : __p2_(0),
794 __p3_(1.0f)
795{
796}
797
798template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +0000799inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000800__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
801 const key_equal& __eql)
802 : __bucket_list_(nullptr, __bucket_list_deleter()),
803 __p1_(),
804 __p2_(0, __hf),
805 __p3_(1.0f, __eql)
806{
807}
808
809template <class _Tp, class _Hash, class _Equal, class _Alloc>
810__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
811 const key_equal& __eql,
812 const allocator_type& __a)
813 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
814 __p1_(__node_allocator(__a)),
815 __p2_(0, __hf),
816 __p3_(1.0f, __eql)
817{
818}
819
820template <class _Tp, class _Hash, class _Equal, class _Alloc>
821__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
822 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
823 __p1_(__node_allocator(__a)),
824 __p2_(0),
825 __p3_(1.0f)
826{
827}
828
829template <class _Tp, class _Hash, class _Equal, class _Alloc>
830__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
831 : __bucket_list_(nullptr,
832 __bucket_list_deleter(allocator_traits<__pointer_allocator>::
833 select_on_container_copy_construction(
834 __u.__bucket_list_.get_deleter().__alloc()), 0)),
835 __p1_(allocator_traits<__node_allocator>::
836 select_on_container_copy_construction(__u.__node_alloc())),
837 __p2_(0, __u.hash_function()),
838 __p3_(__u.__p3_)
839{
840}
841
842template <class _Tp, class _Hash, class _Equal, class _Alloc>
843__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u,
844 const allocator_type& __a)
845 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
846 __p1_(__node_allocator(__a)),
847 __p2_(0, __u.hash_function()),
848 __p3_(__u.__p3_)
849{
850}
851
Howard Hinnant73d21a42010-09-04 23:28:19 +0000852#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000853
854template <class _Tp, class _Hash, class _Equal, class _Alloc>
855__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000856 _NOEXCEPT_(
857 is_nothrow_move_constructible<__bucket_list>::value &&
858 is_nothrow_move_constructible<__first_node>::value &&
859 is_nothrow_move_constructible<hasher>::value &&
860 is_nothrow_move_constructible<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000861 : __bucket_list_(_STD::move(__u.__bucket_list_)),
862 __p1_(_STD::move(__u.__p1_)),
863 __p2_(_STD::move(__u.__p2_)),
864 __p3_(_STD::move(__u.__p3_))
865{
866 if (size() > 0)
867 {
868 __bucket_list_[__p1_.first().__next_->__hash_ % bucket_count()] =
Howard Hinnant2529d022011-02-02 17:36:20 +0000869 static_cast<__node_pointer>(_STD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000870 __u.__p1_.first().__next_ = nullptr;
871 __u.size() = 0;
872 }
873}
874
875template <class _Tp, class _Hash, class _Equal, class _Alloc>
876__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u,
877 const allocator_type& __a)
878 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
879 __p1_(__node_allocator(__a)),
880 __p2_(0, _STD::move(__u.hash_function())),
881 __p3_(_STD::move(__u.__p3_))
882{
883 if (__a == allocator_type(__u.__node_alloc()))
884 {
885 __bucket_list_.reset(__u.__bucket_list_.release());
886 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
887 __u.__bucket_list_.get_deleter().size() = 0;
888 if (__u.size() > 0)
889 {
890 __p1_.first().__next_ = __u.__p1_.first().__next_;
891 __u.__p1_.first().__next_ = nullptr;
892 __bucket_list_[__p1_.first().__next_->__hash_ % bucket_count()] =
Howard Hinnant2529d022011-02-02 17:36:20 +0000893 static_cast<__node_pointer>(_STD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000894 size() = __u.size();
895 __u.size() = 0;
896 }
897 }
898}
899
Howard Hinnant73d21a42010-09-04 23:28:19 +0000900#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000901
902template <class _Tp, class _Hash, class _Equal, class _Alloc>
903__hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table()
904{
905 __deallocate(__p1_.first().__next_);
906}
907
908template <class _Tp, class _Hash, class _Equal, class _Alloc>
909void
910__hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc(
911 const __hash_table& __u, true_type)
912{
913 if (__node_alloc() != __u.__node_alloc())
914 {
915 clear();
916 __bucket_list_.reset();
917 __bucket_list_.get_deleter().size() = 0;
918 }
919 __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc();
920 __node_alloc() = __u.__node_alloc();
921}
922
923template <class _Tp, class _Hash, class _Equal, class _Alloc>
924__hash_table<_Tp, _Hash, _Equal, _Alloc>&
925__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u)
926{
927 if (this != &__u)
928 {
929 __copy_assign_alloc(__u);
930 hash_function() = __u.hash_function();
931 key_eq() = __u.key_eq();
932 max_load_factor() = __u.max_load_factor();
933 __assign_multi(__u.begin(), __u.end());
934 }
935 return *this;
936}
937
938template <class _Tp, class _Hash, class _Equal, class _Alloc>
939void
940__hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate(__node_pointer __np)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000941 _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000942{
943 __node_allocator& __na = __node_alloc();
944 while (__np != nullptr)
945 {
946 __node_pointer __next = __np->__next_;
Howard Hinnant2529d022011-02-02 17:36:20 +0000947 __node_traits::destroy(__na, _STD::addressof(__np->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000948 __node_traits::deallocate(__na, __np, 1);
949 __np = __next;
950 }
951}
952
953template <class _Tp, class _Hash, class _Equal, class _Alloc>
954typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_pointer
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000955__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000956{
957 size_type __bc = bucket_count();
958 for (size_type __i = 0; __i < __bc; ++__i)
959 __bucket_list_[__i] = nullptr;
960 size() = 0;
961 __node_pointer __cache = __p1_.first().__next_;
962 __p1_.first().__next_ = nullptr;
963 return __cache;
964}
965
Howard Hinnant73d21a42010-09-04 23:28:19 +0000966#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000967
968template <class _Tp, class _Hash, class _Equal, class _Alloc>
969void
970__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
971 __hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000972 _NOEXCEPT_(
973 is_nothrow_move_assignable<__node_allocator>::value &&
974 is_nothrow_move_assignable<hasher>::value &&
975 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000976{
977 clear();
978 __bucket_list_.reset(__u.__bucket_list_.release());
979 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
980 __u.__bucket_list_.get_deleter().size() = 0;
981 __move_assign_alloc(__u);
982 size() = __u.size();
983 hash_function() = _STD::move(__u.hash_function());
984 max_load_factor() = __u.max_load_factor();
985 key_eq() = _STD::move(__u.key_eq());
986 __p1_.first().__next_ = __u.__p1_.first().__next_;
987 if (size() > 0)
988 {
989 __bucket_list_[__p1_.first().__next_->__hash_ % bucket_count()] =
Howard Hinnant2529d022011-02-02 17:36:20 +0000990 static_cast<__node_pointer>(_STD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000991 __u.__p1_.first().__next_ = nullptr;
992 __u.size() = 0;
993 }
994}
995
996template <class _Tp, class _Hash, class _Equal, class _Alloc>
997void
998__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
999 __hash_table& __u, false_type)
1000{
1001 if (__node_alloc() == __u.__node_alloc())
1002 __move_assign(__u, true_type());
1003 else
1004 {
1005 hash_function() = _STD::move(__u.hash_function());
1006 key_eq() = _STD::move(__u.key_eq());
1007 max_load_factor() = __u.max_load_factor();
1008 if (bucket_count() != 0)
1009 {
1010 __node_pointer __cache = __detach();
1011#ifndef _LIBCPP_NO_EXCEPTIONS
1012 try
1013 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001014#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001015 const_iterator __i = __u.begin();
1016 while (__cache != nullptr && __u.size() != 0)
1017 {
1018 __cache->__value_ = _STD::move(__u.remove(__i++)->__value_);
1019 __node_pointer __next = __cache->__next_;
1020 __node_insert_multi(__cache);
1021 __cache = __next;
1022 }
1023#ifndef _LIBCPP_NO_EXCEPTIONS
1024 }
1025 catch (...)
1026 {
1027 __deallocate(__cache);
1028 throw;
1029 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001030#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001031 __deallocate(__cache);
1032 }
1033 const_iterator __i = __u.begin();
1034 while (__u.size() != 0)
1035 {
1036 __node_holder __h =
1037 __construct_node(_STD::move(__u.remove(__i++)->__value_));
1038 __node_insert_multi(__h.get());
1039 __h.release();
1040 }
1041 }
1042}
1043
1044template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001045inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001046__hash_table<_Tp, _Hash, _Equal, _Alloc>&
1047__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001048 _NOEXCEPT_(
1049 __node_traits::propagate_on_container_move_assignment::value &&
1050 is_nothrow_move_assignable<__node_allocator>::value &&
1051 is_nothrow_move_assignable<hasher>::value &&
1052 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001053{
1054 __move_assign(__u, integral_constant<bool,
1055 __node_traits::propagate_on_container_move_assignment::value>());
1056 return *this;
1057}
1058
Howard Hinnant73d21a42010-09-04 23:28:19 +00001059#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001060
1061template <class _Tp, class _Hash, class _Equal, class _Alloc>
1062template <class _InputIterator>
1063void
1064__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first,
1065 _InputIterator __last)
1066{
1067 if (bucket_count() != 0)
1068 {
1069 __node_pointer __cache = __detach();
1070#ifndef _LIBCPP_NO_EXCEPTIONS
1071 try
1072 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001073#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001074 for (; __cache != nullptr && __first != __last; ++__first)
1075 {
1076 __cache->__value_ = *__first;
1077 __node_pointer __next = __cache->__next_;
1078 __node_insert_unique(__cache);
1079 __cache = __next;
1080 }
1081#ifndef _LIBCPP_NO_EXCEPTIONS
1082 }
1083 catch (...)
1084 {
1085 __deallocate(__cache);
1086 throw;
1087 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001088#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001089 __deallocate(__cache);
1090 }
1091 for (; __first != __last; ++__first)
1092 __insert_unique(*__first);
1093}
1094
1095template <class _Tp, class _Hash, class _Equal, class _Alloc>
1096template <class _InputIterator>
1097void
1098__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first,
1099 _InputIterator __last)
1100{
1101 if (bucket_count() != 0)
1102 {
1103 __node_pointer __cache = __detach();
1104#ifndef _LIBCPP_NO_EXCEPTIONS
1105 try
1106 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001107#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001108 for (; __cache != nullptr && __first != __last; ++__first)
1109 {
1110 __cache->__value_ = *__first;
1111 __node_pointer __next = __cache->__next_;
1112 __node_insert_multi(__cache);
1113 __cache = __next;
1114 }
1115#ifndef _LIBCPP_NO_EXCEPTIONS
1116 }
1117 catch (...)
1118 {
1119 __deallocate(__cache);
1120 throw;
1121 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001122#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001123 __deallocate(__cache);
1124 }
1125 for (; __first != __last; ++__first)
1126 __insert_multi(*__first);
1127}
1128
1129template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001130inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001131typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001132__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001133{
1134 return iterator(__p1_.first().__next_);
1135}
1136
1137template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001138inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001139typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001140__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001141{
1142 return iterator(nullptr);
1143}
1144
1145template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001146inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001147typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001148__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001149{
1150 return const_iterator(__p1_.first().__next_);
1151}
1152
1153template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001154inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001155typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001156__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001157{
1158 return const_iterator(nullptr);
1159}
1160
1161template <class _Tp, class _Hash, class _Equal, class _Alloc>
1162void
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001163__hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001164{
1165 if (size() > 0)
1166 {
1167 __deallocate(__p1_.first().__next_);
1168 __p1_.first().__next_ = nullptr;
1169 size_type __bc = bucket_count();
1170 for (size_type __i; __i < __bc; ++__i)
1171 __bucket_list_[__i] = nullptr;
1172 size() = 0;
1173 }
1174}
1175
1176template <class _Tp, class _Hash, class _Equal, class _Alloc>
1177pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1178__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd)
1179{
1180 __nd->__hash_ = hash_function()(__nd->__value_);
1181 size_type __bc = bucket_count();
1182 bool __inserted = false;
1183 __node_pointer __ndptr;
1184 size_t __chash;
1185 if (__bc != 0)
1186 {
1187 __chash = __nd->__hash_ % __bc;
1188 __ndptr = __bucket_list_[__chash];
1189 if (__ndptr != nullptr)
1190 {
1191 for (__ndptr = __ndptr->__next_; __ndptr != nullptr &&
1192 __ndptr->__hash_ % __bc == __chash;
1193 __ndptr = __ndptr->__next_)
1194 {
1195 if (key_eq()(__ndptr->__value_, __nd->__value_))
1196 goto __done;
1197 }
1198 }
1199 }
1200 {
1201 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1202 {
1203 rehash(_STD::max<size_type>(2 * __bc + 1,
1204 size_type(ceil(float(size() + 1) / max_load_factor()))));
1205 __bc = bucket_count();
1206 __chash = __nd->__hash_ % __bc;
1207 }
1208 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1209 __node_pointer __pn = __bucket_list_[__chash];
1210 if (__pn == nullptr)
1211 {
Howard Hinnant2529d022011-02-02 17:36:20 +00001212 __pn = static_cast<__node_pointer>(_STD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001213 __nd->__next_ = __pn->__next_;
1214 __pn->__next_ = __nd;
1215 // fix up __bucket_list_
1216 __bucket_list_[__chash] = __pn;
1217 if (__nd->__next_ != nullptr)
1218 __bucket_list_[__nd->__next_->__hash_ % __bc] = __nd;
1219 }
1220 else
1221 {
1222 __nd->__next_ = __pn->__next_;
1223 __pn->__next_ = __nd;
1224 }
1225 __ndptr = __nd;
1226 // increment size
1227 ++size();
1228 __inserted = true;
1229 }
1230__done:
1231 return pair<iterator, bool>(iterator(__ndptr), __inserted);
1232}
1233
1234template <class _Tp, class _Hash, class _Equal, class _Alloc>
1235typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1236__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp)
1237{
1238 __cp->__hash_ = hash_function()(__cp->__value_);
1239 size_type __bc = bucket_count();
1240 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1241 {
1242 rehash(_STD::max<size_type>(2 * __bc + 1,
1243 size_type(ceil(float(size() + 1) / max_load_factor()))));
1244 __bc = bucket_count();
1245 }
1246 size_t __chash = __cp->__hash_ % __bc;
1247 __node_pointer __pn = __bucket_list_[__chash];
1248 if (__pn == nullptr)
1249 {
Howard Hinnant2529d022011-02-02 17:36:20 +00001250 __pn = static_cast<__node_pointer>(_STD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001251 __cp->__next_ = __pn->__next_;
1252 __pn->__next_ = __cp;
1253 // fix up __bucket_list_
1254 __bucket_list_[__chash] = __pn;
1255 if (__cp->__next_ != nullptr)
1256 __bucket_list_[__cp->__next_->__hash_ % __bc] = __cp;
1257 }
1258 else
1259 {
1260 for (bool __found = false; __pn->__next_ != nullptr &&
1261 __pn->__next_->__hash_ % __bc == __chash;
1262 __pn = __pn->__next_)
Howard Hinnant324bb032010-08-22 00:02:43 +00001263 {
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001264 // __found key_eq() action
1265 // false false loop
1266 // true true loop
1267 // false true set __found to true
1268 // true false break
1269 if (__found != (__pn->__next_->__hash_ == __cp->__hash_ &&
1270 key_eq()(__pn->__next_->__value_, __cp->__value_)))
1271 {
1272 if (!__found)
1273 __found = true;
1274 else
1275 break;
1276 }
1277 }
1278 __cp->__next_ = __pn->__next_;
1279 __pn->__next_ = __cp;
1280 if (__cp->__next_ != nullptr)
1281 {
1282 size_t __nhash = __cp->__next_->__hash_ % __bc;
1283 if (__nhash != __chash)
1284 __bucket_list_[__nhash] = __cp;
1285 }
1286 }
1287 ++size();
1288 return iterator(__cp);
1289}
1290
1291template <class _Tp, class _Hash, class _Equal, class _Alloc>
1292typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1293__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(
1294 const_iterator __p, __node_pointer __cp)
1295{
1296 if (__p != end() && key_eq()(*__p, __cp->__value_))
1297 {
1298 __node_pointer __np = const_cast<__node_pointer>(__p.__node_);
1299 __cp->__hash_ = __np->__hash_;
1300 size_type __bc = bucket_count();
1301 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1302 {
1303 rehash(_STD::max<size_type>(2 * __bc + 1,
1304 size_type(ceil(float(size() + 1) / max_load_factor()))));
1305 __bc = bucket_count();
1306 }
1307 size_t __chash = __cp->__hash_ % __bc;
1308 __node_pointer __pp = __bucket_list_[__chash];
1309 while (__pp->__next_ != __np)
1310 __pp = __pp->__next_;
1311 __cp->__next_ = __np;
1312 __pp->__next_ = __cp;
1313 ++size();
1314 return iterator(__cp);
1315 }
1316 return __node_insert_multi(__cp);
1317}
1318
1319template <class _Tp, class _Hash, class _Equal, class _Alloc>
1320pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1321__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(const value_type& __x)
1322{
1323 size_t __hash = hash_function()(__x);
1324 size_type __bc = bucket_count();
1325 bool __inserted = false;
1326 __node_pointer __nd;
1327 size_t __chash;
1328 if (__bc != 0)
1329 {
1330 __chash = __hash % __bc;
1331 __nd = __bucket_list_[__chash];
1332 if (__nd != nullptr)
1333 {
1334 for (__nd = __nd->__next_; __nd != nullptr &&
1335 __nd->__hash_ % __bc == __chash;
1336 __nd = __nd->__next_)
1337 {
1338 if (key_eq()(__nd->__value_, __x))
1339 goto __done;
1340 }
1341 }
1342 }
1343 {
1344 __node_holder __h = __construct_node(__x, __hash);
1345 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1346 {
1347 rehash(_STD::max<size_type>(2 * __bc + 1,
1348 size_type(ceil(float(size() + 1) / max_load_factor()))));
1349 __bc = bucket_count();
1350 __chash = __hash % __bc;
1351 }
1352 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1353 __node_pointer __pn = __bucket_list_[__chash];
1354 if (__pn == nullptr)
1355 {
Howard Hinnant2529d022011-02-02 17:36:20 +00001356 __pn = static_cast<__node_pointer>(_STD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001357 __h->__next_ = __pn->__next_;
1358 __pn->__next_ = __h.get();
1359 // fix up __bucket_list_
1360 __bucket_list_[__chash] = __pn;
1361 if (__h->__next_ != nullptr)
1362 __bucket_list_[__h->__next_->__hash_ % __bc] = __h.get();
1363 }
1364 else
1365 {
1366 __h->__next_ = __pn->__next_;
1367 __pn->__next_ = __h.get();
1368 }
1369 __nd = __h.release();
1370 // increment size
1371 ++size();
1372 __inserted = true;
1373 }
1374__done:
1375 return pair<iterator, bool>(iterator(__nd), __inserted);
1376}
1377
Howard Hinnant73d21a42010-09-04 23:28:19 +00001378#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1379#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001380
1381template <class _Tp, class _Hash, class _Equal, class _Alloc>
1382template <class... _Args>
1383pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1384__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique(_Args&&... __args)
1385{
1386 __node_holder __h = __construct_node(_STD::forward<_Args>(__args)...);
1387 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1388 if (__r.second)
1389 __h.release();
1390 return __r;
1391}
1392
1393template <class _Tp, class _Hash, class _Equal, class _Alloc>
1394template <class... _Args>
1395typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1396__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args)
1397{
1398 __node_holder __h = __construct_node(_STD::forward<_Args>(__args)...);
1399 iterator __r = __node_insert_multi(__h.get());
1400 __h.release();
1401 return __r;
1402}
1403
1404template <class _Tp, class _Hash, class _Equal, class _Alloc>
1405template <class... _Args>
1406typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1407__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi(
1408 const_iterator __p, _Args&&... __args)
1409{
1410 __node_holder __h = __construct_node(_STD::forward<_Args>(__args)...);
1411 iterator __r = __node_insert_multi(__p, __h.get());
1412 __h.release();
1413 return __r;
1414}
1415
Howard Hinnant73d21a42010-09-04 23:28:19 +00001416#endif // _LIBCPP_HAS_NO_VARIADICS
1417
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001418template <class _Tp, class _Hash, class _Equal, class _Alloc>
1419template <class _P>
1420pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1421__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(_P&& __x)
1422{
1423 __node_holder __h = __construct_node(_STD::forward<_P>(__x));
1424 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1425 if (__r.second)
1426 __h.release();
1427 return __r;
1428}
1429
Howard Hinnant73d21a42010-09-04 23:28:19 +00001430#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001431
Howard Hinnant73d21a42010-09-04 23:28:19 +00001432#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001433
1434template <class _Tp, class _Hash, class _Equal, class _Alloc>
1435template <class _P>
1436typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1437__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(_P&& __x)
1438{
1439 __node_holder __h = __construct_node(_STD::forward<_P>(__x));
1440 iterator __r = __node_insert_multi(__h.get());
1441 __h.release();
1442 return __r;
1443}
1444
1445template <class _Tp, class _Hash, class _Equal, class _Alloc>
1446template <class _P>
1447typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1448__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
1449 _P&& __x)
1450{
1451 __node_holder __h = __construct_node(_STD::forward<_P>(__x));
1452 iterator __r = __node_insert_multi(__p, __h.get());
1453 __h.release();
1454 return __r;
1455}
1456
Howard Hinnant73d21a42010-09-04 23:28:19 +00001457#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001458
1459template <class _Tp, class _Hash, class _Equal, class _Alloc>
1460typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1461__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const value_type& __x)
1462{
1463 __node_holder __h = __construct_node(__x);
1464 iterator __r = __node_insert_multi(__h.get());
1465 __h.release();
1466 return __r;
1467}
1468
1469template <class _Tp, class _Hash, class _Equal, class _Alloc>
1470typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1471__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
1472 const value_type& __x)
1473{
1474 __node_holder __h = __construct_node(__x);
1475 iterator __r = __node_insert_multi(__p, __h.get());
1476 __h.release();
1477 return __r;
1478}
1479
Howard Hinnant73d21a42010-09-04 23:28:19 +00001480#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001481
1482template <class _Tp, class _Hash, class _Equal, class _Alloc>
1483void
1484__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n)
1485{
1486 __n = __next_prime(_STD::max<size_type>(__n, size() > 0));
1487 size_type __bc = bucket_count();
1488 if (__n > __bc)
1489 __rehash(__n);
1490 else
1491 {
1492 __n = _STD::max<size_type>
1493 (
1494 __n,
1495 __next_prime(size_t(ceil(float(size()) / max_load_factor())))
1496 );
1497 if (__n < __bc)
1498 __rehash(__n);
1499 }
1500}
1501
1502template <class _Tp, class _Hash, class _Equal, class _Alloc>
1503void
1504__hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc)
1505{
1506 __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc();
1507 __bucket_list_.reset(__nbc > 0 ?
1508 __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr);
1509 __bucket_list_.get_deleter().size() = __nbc;
1510 if (__nbc > 0)
1511 {
1512 for (size_type __i = 0; __i < __nbc; ++__i)
1513 __bucket_list_[__i] = nullptr;
Howard Hinnant2529d022011-02-02 17:36:20 +00001514 __node_pointer __pp(static_cast<__node_pointer>(_STD::addressof(__p1_.first())));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001515 __node_pointer __cp = __pp->__next_;
1516 if (__cp != nullptr)
1517 {
1518 size_type __chash = __cp->__hash_ % __nbc;
1519 __bucket_list_[__chash] = __pp;
1520 size_type __phash = __chash;
1521 for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr;
1522 __cp = __pp->__next_)
1523 {
1524 __chash = __cp->__hash_ % __nbc;
1525 if (__chash == __phash)
1526 __pp = __cp;
1527 else
1528 {
1529 if (__bucket_list_[__chash] == nullptr)
1530 {
1531 __bucket_list_[__chash] = __pp;
1532 __pp = __cp;
1533 __phash = __chash;
1534 }
1535 else
1536 {
1537 __node_pointer __np = __cp;
1538 for (; __np->__next_ != nullptr &&
1539 key_eq()(__cp->__value_, __np->__next_->__value_);
1540 __np = __np->__next_)
1541 ;
1542 __pp->__next_ = __np->__next_;
1543 __np->__next_ = __bucket_list_[__chash]->__next_;
1544 __bucket_list_[__chash]->__next_ = __cp;
Howard Hinnant324bb032010-08-22 00:02:43 +00001545
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001546 }
1547 }
1548 }
1549 }
1550 }
1551}
1552
1553template <class _Tp, class _Hash, class _Equal, class _Alloc>
1554template <class _Key>
1555typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1556__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k)
1557{
1558 size_t __hash = hash_function()(__k);
1559 size_type __bc = bucket_count();
1560 if (__bc != 0)
1561 {
1562 size_t __chash = __hash % __bc;
1563 __node_pointer __nd = __bucket_list_[__chash];
1564 if (__nd != nullptr)
1565 {
1566 for (__nd = __nd->__next_; __nd != nullptr &&
1567 __nd->__hash_ % __bc == __chash;
1568 __nd = __nd->__next_)
1569 {
1570 if (key_eq()(__nd->__value_, __k))
1571 return iterator(__nd);
1572 }
1573 }
1574 }
1575 return end();
1576}
1577
1578template <class _Tp, class _Hash, class _Equal, class _Alloc>
1579template <class _Key>
1580typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1581__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const
1582{
1583 size_t __hash = hash_function()(__k);
1584 size_type __bc = bucket_count();
1585 if (__bc != 0)
1586 {
1587 size_t __chash = __hash % __bc;
1588 __node_const_pointer __nd = __bucket_list_[__chash];
1589 if (__nd != nullptr)
1590 {
1591 for (__nd = __nd->__next_; __nd != nullptr &&
1592 __nd->__hash_ % __bc == __chash;
1593 __nd = __nd->__next_)
1594 {
1595 if (key_eq()(__nd->__value_, __k))
1596 return const_iterator(__nd);
1597 }
1598 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001599
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001600 }
1601 return end();
1602}
1603
Howard Hinnant73d21a42010-09-04 23:28:19 +00001604#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1605#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001606
1607template <class _Tp, class _Hash, class _Equal, class _Alloc>
1608template <class ..._Args>
1609typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1610__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args)
1611{
1612 __node_allocator& __na = __node_alloc();
1613 __node_holder __h(__node_traits::allocate(__na, 1), _D(__na));
Howard Hinnant2529d022011-02-02 17:36:20 +00001614 __node_traits::construct(__na, _STD::addressof(__h->__value_), _STD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001615 __h.get_deleter().__value_constructed = true;
1616 __h->__hash_ = hash_function()(__h->__value_);
1617 __h->__next_ = nullptr;
1618 return __h;
1619}
1620
Howard Hinnant73d21a42010-09-04 23:28:19 +00001621#endif // _LIBCPP_HAS_NO_VARIADICS
1622
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001623template <class _Tp, class _Hash, class _Equal, class _Alloc>
1624typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1625__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(value_type&& __v,
1626 size_t __hash)
1627{
1628 __node_allocator& __na = __node_alloc();
1629 __node_holder __h(__node_traits::allocate(__na, 1), _D(__na));
Howard Hinnant2529d022011-02-02 17:36:20 +00001630 __node_traits::construct(__na, _STD::addressof(__h->__value_), _STD::move(__v));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001631 __h.get_deleter().__value_constructed = true;
1632 __h->__hash_ = __hash;
1633 __h->__next_ = nullptr;
1634 return _STD::move(__h);
1635}
1636
Howard Hinnant73d21a42010-09-04 23:28:19 +00001637#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001638
1639template <class _Tp, class _Hash, class _Equal, class _Alloc>
1640typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1641__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v)
1642{
1643 __node_allocator& __na = __node_alloc();
1644 __node_holder __h(__node_traits::allocate(__na, 1), _D(__na));
Howard Hinnant2529d022011-02-02 17:36:20 +00001645 __node_traits::construct(__na, _STD::addressof(__h->__value_), __v);
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 _STD::move(__h);
1650}
1651
Howard Hinnant73d21a42010-09-04 23:28:19 +00001652#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001653
1654template <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(const value_type& __v,
1657 size_t __hash)
1658{
1659 __node_allocator& __na = __node_alloc();
1660 __node_holder __h(__node_traits::allocate(__na, 1), _D(__na));
Howard Hinnant2529d022011-02-02 17:36:20 +00001661 __node_traits::construct(__na, _STD::addressof(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001662 __h.get_deleter().__value_constructed = true;
1663 __h->__hash_ = __hash;
1664 __h->__next_ = nullptr;
1665 return _STD::move(__h);
1666}
1667
1668template <class _Tp, class _Hash, class _Equal, class _Alloc>
1669typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1670__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p)
1671{
1672 __node_pointer __np = const_cast<__node_pointer>(__p.__node_);
1673 iterator __r(__np);
1674 ++__r;
1675 remove(__p);
1676 return __r;
1677}
1678
1679template <class _Tp, class _Hash, class _Equal, class _Alloc>
1680typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1681__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first,
1682 const_iterator __last)
1683{
1684 for (const_iterator __p = __first; __first != __last; __p = __first)
1685 {
1686 ++__first;
1687 erase(__p);
1688 }
1689 __node_pointer __np = const_cast<__node_pointer>(__last.__node_);
1690 return iterator (__np);
1691}
1692
1693template <class _Tp, class _Hash, class _Equal, class _Alloc>
1694template <class _Key>
1695typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1696__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k)
1697{
1698 iterator __i = find(__k);
1699 if (__i == end())
1700 return 0;
1701 erase(__i);
1702 return 1;
1703}
1704
1705template <class _Tp, class _Hash, class _Equal, class _Alloc>
1706template <class _Key>
1707typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1708__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k)
1709{
1710 size_type __r = 0;
1711 iterator __i = find(__k);
1712 if (__i != end())
1713 {
1714 iterator __e = end();
1715 do
1716 {
1717 erase(__i++);
1718 ++__r;
1719 } while (__i != __e && key_eq()(*__i, __k));
1720 }
1721 return __r;
1722}
1723
1724template <class _Tp, class _Hash, class _Equal, class _Alloc>
1725typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001726__hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001727{
1728 // current node
1729 __node_pointer __cn = const_cast<__node_pointer>(__p.__node_);
1730 size_type __bc = bucket_count();
1731 size_t __chash = __cn->__hash_ % __bc;
1732 // find previous node
1733 __node_pointer __pn = __bucket_list_[__chash];
1734 for (; __pn->__next_ != __cn; __pn = __pn->__next_)
1735 ;
1736 // Fix up __bucket_list_
1737 // if __pn is not in same bucket (before begin is not in same bucket) &&
1738 // if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
Howard Hinnant2529d022011-02-02 17:36:20 +00001739 if (__pn == _STD::addressof(__p1_.first()) || __pn->__hash_ % __bc != __chash)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001740 {
1741 if (__cn->__next_ == nullptr || __cn->__next_->__hash_ % __bc != __chash)
1742 __bucket_list_[__chash] = nullptr;
1743 }
1744 // if __cn->__next_ is not in same bucket (nullptr is in same bucket)
1745 if (__cn->__next_ != nullptr)
1746 {
1747 size_t __nhash = __cn->__next_->__hash_ % __bc;
1748 if (__nhash != __chash)
1749 __bucket_list_[__nhash] = __pn;
1750 }
1751 // remove __cn
1752 __pn->__next_ = __cn->__next_;
1753 __cn->__next_ = nullptr;
1754 --size();
1755 return __node_holder(__cn, _D(__node_alloc()));
1756}
1757
1758template <class _Tp, class _Hash, class _Equal, class _Alloc>
1759template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39 +00001760inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001761typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1762__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const
1763{
1764 return static_cast<size_type>(find(__k) != end());
1765}
1766
1767template <class _Tp, class _Hash, class _Equal, class _Alloc>
1768template <class _Key>
1769typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1770__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const
1771{
1772 size_type __r = 0;
1773 const_iterator __i = find(__k);
1774 if (__i != end())
1775 {
1776 const_iterator __e = end();
1777 do
1778 {
1779 ++__i;
1780 ++__r;
1781 } while (__i != __e && key_eq()(*__i, __k));
1782 }
1783 return __r;
1784}
1785
1786template <class _Tp, class _Hash, class _Equal, class _Alloc>
1787template <class _Key>
1788pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
1789 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1790__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
1791 const _Key& __k)
1792{
1793 iterator __i = find(__k);
1794 iterator __j = __i;
1795 if (__i != end())
1796 ++__j;
1797 return pair<iterator, iterator>(__i, __j);
1798}
1799
1800template <class _Tp, class _Hash, class _Equal, class _Alloc>
1801template <class _Key>
1802pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
1803 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1804__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
1805 const _Key& __k) const
1806{
1807 const_iterator __i = find(__k);
1808 const_iterator __j = __i;
1809 if (__i != end())
1810 ++__j;
1811 return pair<const_iterator, const_iterator>(__i, __j);
1812}
1813
1814template <class _Tp, class _Hash, class _Equal, class _Alloc>
1815template <class _Key>
1816pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
1817 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1818__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
1819 const _Key& __k)
1820{
1821 iterator __i = find(__k);
1822 iterator __j = __i;
1823 if (__i != end())
1824 {
1825 iterator __e = end();
1826 do
1827 {
1828 ++__j;
1829 } while (__j != __e && key_eq()(*__j, __k));
1830 }
1831 return pair<iterator, iterator>(__i, __j);
1832}
1833
1834template <class _Tp, class _Hash, class _Equal, class _Alloc>
1835template <class _Key>
1836pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
1837 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1838__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
1839 const _Key& __k) const
1840{
1841 const_iterator __i = find(__k);
1842 const_iterator __j = __i;
1843 if (__i != end())
1844 {
1845 const_iterator __e = end();
1846 do
1847 {
1848 ++__j;
1849 } while (__j != __e && key_eq()(*__j, __k));
1850 }
1851 return pair<const_iterator, const_iterator>(__i, __j);
1852}
1853
1854template <class _Tp, class _Hash, class _Equal, class _Alloc>
1855void
1856__hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001857 _NOEXCEPT_(
1858 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
1859 __is_nothrow_swappable<__pointer_allocator>::value) &&
1860 (!__node_traits::propagate_on_container_swap::value ||
1861 __is_nothrow_swappable<__node_allocator>::value) &&
1862 __is_nothrow_swappable<hasher>::value &&
1863 __is_nothrow_swappable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001864{
1865 {
1866 __node_pointer_pointer __npp = __bucket_list_.release();
1867 __bucket_list_.reset(__u.__bucket_list_.release());
1868 __u.__bucket_list_.reset(__npp);
1869 }
1870 _STD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
1871 __swap_alloc(__bucket_list_.get_deleter().__alloc(),
1872 __u.__bucket_list_.get_deleter().__alloc());
1873 __swap_alloc(__node_alloc(), __u.__node_alloc());
1874 _STD::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
1875 __p2_.swap(__u.__p2_);
1876 __p3_.swap(__u.__p3_);
1877 if (size() > 0)
1878 __bucket_list_[__p1_.first().__next_->__hash_ % bucket_count()] =
Howard Hinnant2529d022011-02-02 17:36:20 +00001879 static_cast<__node_pointer>(_STD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001880 if (__u.size() > 0)
1881 __u.__bucket_list_[__u.__p1_.first().__next_->__hash_ % __u.bucket_count()] =
Howard Hinnant2529d022011-02-02 17:36:20 +00001882 static_cast<__node_pointer>(_STD::addressof(__u.__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001883}
1884
1885template <class _Tp, class _Hash, class _Equal, class _Alloc>
1886typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1887__hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const
1888{
1889 __node_const_pointer __np = __bucket_list_[__n];
1890 size_type __bc = bucket_count();
1891 size_type __r = 0;
1892 if (__np != nullptr)
1893 {
1894 for (__np = __np->__next_; __np != nullptr &&
1895 __np->__hash_ % __bc == __n;
1896 __np = __np->__next_, ++__r)
1897 ;
1898 }
1899 return __r;
1900}
1901
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001902template <class _Tp, class _Hash, class _Equal, class _Alloc>
1903inline _LIBCPP_INLINE_VISIBILITY
1904void
1905swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x,
1906 __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y)
1907 _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
1908{
1909 __x.swap(__y);
1910}
1911
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001912_LIBCPP_END_NAMESPACE_STD
1913
1914#endif // _LIBCPP__HASH_TABLE