blob: 8efec22478411f79a5e60619911b2c4933057cba [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 Hinnant2b1b2d42011-06-14 19:58:17 +000026size_t __next_prime(size_t __n);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000027
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
Howard Hinnant2b1b2d42011-06-14 19:58:17 +000057template <class _Tp, class _Hash, class _Equal, class _Alloc> class __hash_table;
58template <class _ConstNodePtr> class __hash_const_iterator;
59template <class _HashIterator> class __hash_map_iterator;
60template <class _HashIterator> class __hash_map_const_iterator;
61template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
62 class _LIBCPP_VISIBLE unordered_map;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000063
64template <class _NodePtr>
Howard Hinnant99acc502010-09-21 17:32:39 +000065class _LIBCPP_VISIBLE __hash_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000066{
67 typedef _NodePtr __node_pointer;
68
69 __node_pointer __node_;
70
71public:
72 typedef forward_iterator_tag iterator_category;
73 typedef typename pointer_traits<__node_pointer>::element_type::value_type value_type;
74 typedef typename pointer_traits<__node_pointer>::difference_type difference_type;
75 typedef value_type& reference;
76 typedef typename pointer_traits<__node_pointer>::template
77#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
78 rebind<value_type>
79#else
80 rebind<value_type>::other
81#endif
82 pointer;
83
Howard Hinnant5f2f14c2011-06-04 18:54:24 +000084 _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000085
Howard Hinnant99acc502010-09-21 17:32:39 +000086 _LIBCPP_INLINE_VISIBILITY
87 reference operator*() const {return __node_->__value_;}
88 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant0949eed2011-06-30 21:18:19 +000089 pointer operator->() const {return _VSTD::addressof(__node_->__value_);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000090
Howard Hinnant99acc502010-09-21 17:32:39 +000091 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000092 __hash_iterator& operator++()
93 {
94 __node_ = __node_->__next_;
95 return *this;
96 }
97
Howard Hinnant99acc502010-09-21 17:32:39 +000098 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000099 __hash_iterator operator++(int)
100 {
101 __hash_iterator __t(*this);
102 ++(*this);
103 return __t;
104 }
105
Howard Hinnant99acc502010-09-21 17:32:39 +0000106 friend _LIBCPP_INLINE_VISIBILITY
107 bool operator==(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000108 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000109 friend _LIBCPP_INLINE_VISIBILITY
110 bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000111 {return __x.__node_ != __y.__node_;}
112
113private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000114 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000115 __hash_iterator(__node_pointer __node) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000116 : __node_(__node)
117 {}
118
119 template <class, class, class, class> friend class __hash_table;
Howard Hinnant99acc502010-09-21 17:32:39 +0000120 template <class> friend class _LIBCPP_VISIBLE __hash_const_iterator;
121 template <class> friend class _LIBCPP_VISIBLE __hash_map_iterator;
122 template <class, class, class, class, class> friend class _LIBCPP_VISIBLE unordered_map;
123 template <class, class, class, class, class> friend class _LIBCPP_VISIBLE unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000124};
125
126template <class _ConstNodePtr>
Howard Hinnant99acc502010-09-21 17:32:39 +0000127class _LIBCPP_VISIBLE __hash_const_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000128{
129 typedef _ConstNodePtr __node_pointer;
130
131 __node_pointer __node_;
132
133 typedef typename remove_const<
134 typename pointer_traits<__node_pointer>::element_type
135 >::type __node;
136
137public:
138 typedef forward_iterator_tag iterator_category;
139 typedef typename __node::value_type value_type;
140 typedef typename pointer_traits<__node_pointer>::difference_type difference_type;
141 typedef const value_type& reference;
142 typedef typename pointer_traits<__node_pointer>::template
143#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
144 rebind<const value_type>
145#else
146 rebind<const value_type>::other
147#endif
148 pointer;
149 typedef typename pointer_traits<__node_pointer>::template
150#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
151 rebind<__node>
152#else
153 rebind<__node>::other
154#endif
155 __non_const_node_pointer;
156 typedef __hash_iterator<__non_const_node_pointer> __non_const_iterator;
157
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000158 _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000159 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000160 __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000161 : __node_(__x.__node_)
162 {}
163
Howard Hinnant99acc502010-09-21 17:32:39 +0000164 _LIBCPP_INLINE_VISIBILITY
165 reference operator*() const {return __node_->__value_;}
166 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant0949eed2011-06-30 21:18:19 +0000167 pointer operator->() const {return _VSTD::addressof(__node_->__value_);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000168
Howard Hinnant99acc502010-09-21 17:32:39 +0000169 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000170 __hash_const_iterator& operator++()
171 {
172 __node_ = __node_->__next_;
173 return *this;
174 }
175
Howard Hinnant99acc502010-09-21 17:32:39 +0000176 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000177 __hash_const_iterator operator++(int)
178 {
179 __hash_const_iterator __t(*this);
180 ++(*this);
181 return __t;
182 }
183
Howard Hinnant99acc502010-09-21 17:32:39 +0000184 friend _LIBCPP_INLINE_VISIBILITY
185 bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000186 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000187 friend _LIBCPP_INLINE_VISIBILITY
188 bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000189 {return __x.__node_ != __y.__node_;}
190
191private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000192 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000193 __hash_const_iterator(__node_pointer __node) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000194 : __node_(__node)
195 {}
196
197 template <class, class, class, class> friend class __hash_table;
Howard Hinnant99acc502010-09-21 17:32:39 +0000198 template <class> friend class _LIBCPP_VISIBLE __hash_map_const_iterator;
199 template <class, class, class, class, class> friend class _LIBCPP_VISIBLE unordered_map;
200 template <class, class, class, class, class> friend class _LIBCPP_VISIBLE unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000201};
202
Howard Hinnant2b1b2d42011-06-14 19:58:17 +0000203template <class _ConstNodePtr> class _LIBCPP_VISIBLE __hash_const_local_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000204
205template <class _NodePtr>
Howard Hinnant99acc502010-09-21 17:32:39 +0000206class _LIBCPP_VISIBLE __hash_local_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000207{
208 typedef _NodePtr __node_pointer;
209
210 __node_pointer __node_;
211 size_t __bucket_;
212 size_t __bucket_count_;
213
214 typedef pointer_traits<__node_pointer> __pointer_traits;
215public:
216 typedef forward_iterator_tag iterator_category;
217 typedef typename __pointer_traits::element_type::value_type value_type;
218 typedef typename __pointer_traits::difference_type difference_type;
219 typedef value_type& reference;
220 typedef typename __pointer_traits::template
221#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
222 rebind<value_type>
223#else
224 rebind<value_type>::other
225#endif
226 pointer;
227
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000228 _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000229
Howard Hinnant99acc502010-09-21 17:32:39 +0000230 _LIBCPP_INLINE_VISIBILITY
231 reference operator*() const {return __node_->__value_;}
232 _LIBCPP_INLINE_VISIBILITY
233 pointer operator->() const {return &__node_->__value_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000234
Howard Hinnant99acc502010-09-21 17:32:39 +0000235 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000236 __hash_local_iterator& operator++()
237 {
238 __node_ = __node_->__next_;
239 if (__node_ != nullptr && __node_->__hash_ % __bucket_count_ != __bucket_)
240 __node_ = nullptr;
241 return *this;
242 }
243
Howard Hinnant99acc502010-09-21 17:32:39 +0000244 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000245 __hash_local_iterator operator++(int)
246 {
247 __hash_local_iterator __t(*this);
248 ++(*this);
249 return __t;
250 }
251
Howard Hinnant99acc502010-09-21 17:32:39 +0000252 friend _LIBCPP_INLINE_VISIBILITY
253 bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000254 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000255 friend _LIBCPP_INLINE_VISIBILITY
256 bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000257 {return __x.__node_ != __y.__node_;}
258
259private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000260 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000261 __hash_local_iterator(__node_pointer __node, size_t __bucket,
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000262 size_t __bucket_count) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000263 : __node_(__node),
264 __bucket_(__bucket),
265 __bucket_count_(__bucket_count)
266 {
267 if (__node_ != nullptr)
268 __node_ = __node_->__next_;
269 }
270
271 template <class, class, class, class> friend class __hash_table;
Howard Hinnant99acc502010-09-21 17:32:39 +0000272 template <class> friend class _LIBCPP_VISIBLE __hash_const_local_iterator;
273 template <class> friend class _LIBCPP_VISIBLE __hash_map_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000274};
275
276template <class _ConstNodePtr>
Howard Hinnant99acc502010-09-21 17:32:39 +0000277class _LIBCPP_VISIBLE __hash_const_local_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000278{
279 typedef _ConstNodePtr __node_pointer;
280
281 __node_pointer __node_;
282 size_t __bucket_;
283 size_t __bucket_count_;
284
285 typedef pointer_traits<__node_pointer> __pointer_traits;
286 typedef typename __pointer_traits::element_type __node;
287 typedef typename remove_const<__node>::type __non_const_node;
288 typedef typename pointer_traits<__node_pointer>::template
289#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
290 rebind<__non_const_node>
291#else
292 rebind<__non_const_node>::other
293#endif
294 __non_const_node_pointer;
295 typedef __hash_local_iterator<__non_const_node_pointer>
296 __non_const_iterator;
297public:
298 typedef forward_iterator_tag iterator_category;
299 typedef typename remove_const<
300 typename __pointer_traits::element_type::value_type
301 >::type value_type;
302 typedef typename __pointer_traits::difference_type difference_type;
303 typedef const value_type& reference;
304 typedef typename __pointer_traits::template
305#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
306 rebind<const value_type>
307#else
308 rebind<const value_type>::other
309#endif
310 pointer;
311
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000312 _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000313 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000314 __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000315 : __node_(__x.__node_),
316 __bucket_(__x.__bucket_),
317 __bucket_count_(__x.__bucket_count_)
318 {}
319
Howard Hinnant99acc502010-09-21 17:32:39 +0000320 _LIBCPP_INLINE_VISIBILITY
321 reference operator*() const {return __node_->__value_;}
322 _LIBCPP_INLINE_VISIBILITY
323 pointer operator->() const {return &__node_->__value_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000324
Howard Hinnant99acc502010-09-21 17:32:39 +0000325 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000326 __hash_const_local_iterator& operator++()
327 {
328 __node_ = __node_->__next_;
329 if (__node_ != nullptr && __node_->__hash_ % __bucket_count_ != __bucket_)
330 __node_ = nullptr;
331 return *this;
332 }
333
Howard Hinnant99acc502010-09-21 17:32:39 +0000334 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000335 __hash_const_local_iterator operator++(int)
336 {
337 __hash_const_local_iterator __t(*this);
338 ++(*this);
339 return __t;
340 }
341
Howard Hinnant99acc502010-09-21 17:32:39 +0000342 friend _LIBCPP_INLINE_VISIBILITY
343 bool operator==(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000344 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000345 friend _LIBCPP_INLINE_VISIBILITY
346 bool operator!=(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000347 {return __x.__node_ != __y.__node_;}
348
349private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000350 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000351 __hash_const_local_iterator(__node_pointer __node, size_t __bucket,
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000352 size_t __bucket_count) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000353 : __node_(__node),
354 __bucket_(__bucket),
355 __bucket_count_(__bucket_count)
356 {
357 if (__node_ != nullptr)
358 __node_ = __node_->__next_;
359 }
360
361 template <class, class, class, class> friend class __hash_table;
Howard Hinnant99acc502010-09-21 17:32:39 +0000362 template <class> friend class _LIBCPP_VISIBLE __hash_map_const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000363};
364
365template <class _Alloc>
366class __bucket_list_deallocator
367{
368 typedef _Alloc allocator_type;
369 typedef allocator_traits<allocator_type> __alloc_traits;
370 typedef typename __alloc_traits::size_type size_type;
371
372 __compressed_pair<size_type, allocator_type> __data_;
373public:
374 typedef typename __alloc_traits::pointer pointer;
375
Howard Hinnant99acc502010-09-21 17:32:39 +0000376 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000377 __bucket_list_deallocator()
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000378 _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000379 : __data_(0) {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000380
381 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000382 __bucket_list_deallocator(const allocator_type& __a, size_type __size)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000383 _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000384 : __data_(__size, __a) {}
385
Howard Hinnant73d21a42010-09-04 23:28:19 +0000386#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000387
Howard Hinnant99acc502010-09-21 17:32:39 +0000388 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000389 __bucket_list_deallocator(__bucket_list_deallocator&& __x)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000390 _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000391 : __data_(_VSTD::move(__x.__data_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000392 {
393 __x.size() = 0;
394 }
395
Howard Hinnant73d21a42010-09-04 23:28:19 +0000396#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000397
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000398 _LIBCPP_INLINE_VISIBILITY
399 size_type& size() _NOEXCEPT {return __data_.first();}
400 _LIBCPP_INLINE_VISIBILITY
401 size_type size() const _NOEXCEPT {return __data_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000402
Howard Hinnant99acc502010-09-21 17:32:39 +0000403 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000404 allocator_type& __alloc() _NOEXCEPT {return __data_.second();}
405 _LIBCPP_INLINE_VISIBILITY
406 const allocator_type& __alloc() const _NOEXCEPT {return __data_.second();}
407
408 _LIBCPP_INLINE_VISIBILITY
409 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000410 {
411 __alloc_traits::deallocate(__alloc(), __p, size());
412 }
413};
414
Howard Hinnant2b1b2d42011-06-14 19:58:17 +0000415template <class _Alloc> class __hash_map_node_destructor;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000416
417template <class _Alloc>
418class __hash_node_destructor
419{
420 typedef _Alloc allocator_type;
421 typedef allocator_traits<allocator_type> __alloc_traits;
422 typedef typename __alloc_traits::value_type::value_type value_type;
423public:
424 typedef typename __alloc_traits::pointer pointer;
425private:
426
427 allocator_type& __na_;
428
429 __hash_node_destructor& operator=(const __hash_node_destructor&);
430
431public:
432 bool __value_constructed;
433
Howard Hinnant99acc502010-09-21 17:32:39 +0000434 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000435 explicit __hash_node_destructor(allocator_type& __na) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000436 : __na_(__na),
437 __value_constructed(false)
438 {}
439
Howard Hinnant99acc502010-09-21 17:32:39 +0000440 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000441 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000442 {
443 if (__value_constructed)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000444 __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000445 if (__p)
446 __alloc_traits::deallocate(__na_, __p, 1);
447 }
448
449 template <class> friend class __hash_map_node_destructor;
450};
451
452template <class _Tp, class _Hash, class _Equal, class _Alloc>
453class __hash_table
454{
455public:
456 typedef _Tp value_type;
457 typedef _Hash hasher;
458 typedef _Equal key_equal;
459 typedef _Alloc allocator_type;
460
461private:
462 typedef allocator_traits<allocator_type> __alloc_traits;
463public:
464 typedef value_type& reference;
465 typedef const value_type& const_reference;
466 typedef typename __alloc_traits::pointer pointer;
467 typedef typename __alloc_traits::const_pointer const_pointer;
468 typedef typename __alloc_traits::size_type size_type;
469 typedef typename __alloc_traits::difference_type difference_type;
470public:
471 // Create __node
472 typedef __hash_node<value_type, typename __alloc_traits::void_pointer> __node;
473 typedef typename __node::__first_node __first_node;
474 typedef typename __alloc_traits::template
475#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
476 rebind_alloc<__node>
477#else
478 rebind_alloc<__node>::other
479#endif
480 __node_allocator;
481 typedef allocator_traits<__node_allocator> __node_traits;
482 typedef typename __node_traits::pointer __node_pointer;
483 typedef typename __node_traits::const_pointer __node_const_pointer;
484
485private:
486
487 typedef typename __node_traits::template
488#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
489 rebind_alloc<__node_pointer>
490#else
491 rebind_alloc<__node_pointer>::other
492#endif
493 __pointer_allocator;
494 typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter;
495 typedef unique_ptr<__node_pointer[], __bucket_list_deleter> __bucket_list;
496 typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits;
497 typedef typename __bucket_list_deleter::pointer __node_pointer_pointer;
498
499 // --- Member data begin ---
500 __bucket_list __bucket_list_;
501 __compressed_pair<__first_node, __node_allocator> __p1_;
502 __compressed_pair<size_type, hasher> __p2_;
503 __compressed_pair<float, key_equal> __p3_;
504 // --- Member data end ---
505
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000506 _LIBCPP_INLINE_VISIBILITY
507 size_type& size() _NOEXCEPT {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000508public:
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000509 _LIBCPP_INLINE_VISIBILITY
510 size_type size() const _NOEXCEPT {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000511
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000512 _LIBCPP_INLINE_VISIBILITY
513 hasher& hash_function() _NOEXCEPT {return __p2_.second();}
514 _LIBCPP_INLINE_VISIBILITY
515 const hasher& hash_function() const _NOEXCEPT {return __p2_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000516
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000517 _LIBCPP_INLINE_VISIBILITY
518 float& max_load_factor() _NOEXCEPT {return __p3_.first();}
519 _LIBCPP_INLINE_VISIBILITY
520 float max_load_factor() const _NOEXCEPT {return __p3_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000521
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000522 _LIBCPP_INLINE_VISIBILITY
523 key_equal& key_eq() _NOEXCEPT {return __p3_.second();}
524 _LIBCPP_INLINE_VISIBILITY
525 const key_equal& key_eq() const _NOEXCEPT {return __p3_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000526
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000527 _LIBCPP_INLINE_VISIBILITY
528 __node_allocator& __node_alloc() _NOEXCEPT {return __p1_.second();}
529 _LIBCPP_INLINE_VISIBILITY
530 const __node_allocator& __node_alloc() const _NOEXCEPT
531 {return __p1_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000532
533public:
534 typedef __hash_iterator<__node_pointer> iterator;
535 typedef __hash_const_iterator<__node_const_pointer> const_iterator;
536 typedef __hash_local_iterator<__node_pointer> local_iterator;
537 typedef __hash_const_local_iterator<__node_const_pointer> const_local_iterator;
538
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000539 __hash_table()
540 _NOEXCEPT_(
541 is_nothrow_default_constructible<__bucket_list>::value &&
542 is_nothrow_default_constructible<__first_node>::value &&
543 is_nothrow_default_constructible<__node_allocator>::value &&
544 is_nothrow_default_constructible<hasher>::value &&
545 is_nothrow_default_constructible<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000546 __hash_table(const hasher& __hf, const key_equal& __eql);
547 __hash_table(const hasher& __hf, const key_equal& __eql,
548 const allocator_type& __a);
549 explicit __hash_table(const allocator_type& __a);
550 __hash_table(const __hash_table& __u);
551 __hash_table(const __hash_table& __u, const allocator_type& __a);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000552#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000553 __hash_table(__hash_table&& __u)
554 _NOEXCEPT_(
555 is_nothrow_move_constructible<__bucket_list>::value &&
556 is_nothrow_move_constructible<__first_node>::value &&
557 is_nothrow_move_constructible<__node_allocator>::value &&
558 is_nothrow_move_constructible<hasher>::value &&
559 is_nothrow_move_constructible<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000560 __hash_table(__hash_table&& __u, const allocator_type& __a);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000561#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000562 ~__hash_table();
563
564 __hash_table& operator=(const __hash_table& __u);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000565#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000566 __hash_table& operator=(__hash_table&& __u)
567 _NOEXCEPT_(
568 __node_traits::propagate_on_container_move_assignment::value &&
569 is_nothrow_move_assignable<__node_allocator>::value &&
570 is_nothrow_move_assignable<hasher>::value &&
571 is_nothrow_move_assignable<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000572#endif
573 template <class _InputIterator>
574 void __assign_unique(_InputIterator __first, _InputIterator __last);
575 template <class _InputIterator>
576 void __assign_multi(_InputIterator __first, _InputIterator __last);
577
Howard Hinnant99acc502010-09-21 17:32:39 +0000578 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000579 size_type max_size() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000580 {
581 return allocator_traits<__pointer_allocator>::max_size(
582 __bucket_list_.get_deleter().__alloc());
583 }
584
585 pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
586 iterator __node_insert_multi(__node_pointer __nd);
587 iterator __node_insert_multi(const_iterator __p,
588 __node_pointer __nd);
589
Howard Hinnant73d21a42010-09-04 23:28:19 +0000590#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000591 template <class... _Args>
592 pair<iterator, bool> __emplace_unique(_Args&&... __args);
593 template <class... _Args>
594 iterator __emplace_multi(_Args&&... __args);
595 template <class... _Args>
596 iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000597#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000598
599 pair<iterator, bool> __insert_unique(const value_type& __x);
600
Howard Hinnant73d21a42010-09-04 23:28:19 +0000601#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000602 template <class _P>
603 pair<iterator, bool> __insert_unique(_P&& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000604#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000605
Howard Hinnant73d21a42010-09-04 23:28:19 +0000606#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000607 template <class _P>
608 iterator __insert_multi(_P&& __x);
609 template <class _P>
610 iterator __insert_multi(const_iterator __p, _P&& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000611#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000612 iterator __insert_multi(const value_type& __x);
613 iterator __insert_multi(const_iterator __p, const value_type& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000614#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000615
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000616 void clear() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000617 void rehash(size_type __n);
Howard Hinnant99acc502010-09-21 17:32:39 +0000618 _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000619 {rehash(static_cast<size_type>(ceil(__n / max_load_factor())));}
Howard Hinnant99acc502010-09-21 17:32:39 +0000620
621 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000622 size_type bucket_count() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000623 {
624 return __bucket_list_.get_deleter().size();
625 }
626
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000627 iterator begin() _NOEXCEPT;
628 iterator end() _NOEXCEPT;
629 const_iterator begin() const _NOEXCEPT;
630 const_iterator end() const _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000631
632 template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39 +0000633 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000634 size_type bucket(const _Key& __k) const
635 {return hash_function()(__k) % bucket_count();}
636
637 template <class _Key>
638 iterator find(const _Key& __x);
639 template <class _Key>
640 const_iterator find(const _Key& __x) const;
641
642 typedef __hash_node_destructor<__node_allocator> _D;
643 typedef unique_ptr<__node, _D> __node_holder;
644
645 iterator erase(const_iterator __p);
646 iterator erase(const_iterator __first, const_iterator __last);
647 template <class _Key>
648 size_type __erase_unique(const _Key& __k);
649 template <class _Key>
650 size_type __erase_multi(const _Key& __k);
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000651 __node_holder remove(const_iterator __p) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000652
653 template <class _Key>
654 size_type __count_unique(const _Key& __k) const;
655 template <class _Key>
656 size_type __count_multi(const _Key& __k) const;
657
658 template <class _Key>
659 pair<iterator, iterator>
660 __equal_range_unique(const _Key& __k);
661 template <class _Key>
662 pair<const_iterator, const_iterator>
663 __equal_range_unique(const _Key& __k) const;
664
665 template <class _Key>
666 pair<iterator, iterator>
667 __equal_range_multi(const _Key& __k);
668 template <class _Key>
669 pair<const_iterator, const_iterator>
670 __equal_range_multi(const _Key& __k) const;
671
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000672 void swap(__hash_table& __u)
673 _NOEXCEPT_(
674 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
675 __is_nothrow_swappable<__pointer_allocator>::value) &&
676 (!__node_traits::propagate_on_container_swap::value ||
677 __is_nothrow_swappable<__node_allocator>::value) &&
678 __is_nothrow_swappable<hasher>::value &&
679 __is_nothrow_swappable<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000680
Howard Hinnant99acc502010-09-21 17:32:39 +0000681 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000682 size_type max_bucket_count() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000683 {return __bucket_list_.get_deleter().__alloc().max_size();}
684 size_type bucket_size(size_type __n) const;
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000685 _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000686 {
687 size_type __bc = bucket_count();
688 return __bc != 0 ? (float)size() / __bc : 0.f;
689 }
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000690 _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT
Howard Hinnant0949eed2011-06-30 21:18:19 +0000691 {max_load_factor() = _VSTD::max(__mlf, load_factor());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000692
Howard Hinnant99acc502010-09-21 17:32:39 +0000693 _LIBCPP_INLINE_VISIBILITY local_iterator begin(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000694 {return local_iterator(__bucket_list_[__n], __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000695 _LIBCPP_INLINE_VISIBILITY local_iterator end(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000696 {return local_iterator(nullptr, __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000697 _LIBCPP_INLINE_VISIBILITY const_local_iterator cbegin(size_type __n) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000698 {return const_local_iterator(__bucket_list_[__n], __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000699 _LIBCPP_INLINE_VISIBILITY const_local_iterator cend(size_type __n) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000700 {return const_local_iterator(nullptr, __n, bucket_count());}
701private:
702 void __rehash(size_type __n);
703
Howard Hinnant73d21a42010-09-04 23:28:19 +0000704#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
705#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000706 template <class ..._Args>
707 __node_holder __construct_node(_Args&& ...__args);
Howard Hinnantbfd55302010-09-04 23:46:48 +0000708#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000709 __node_holder __construct_node(value_type&& __v, size_t __hash);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000710#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000711 __node_holder __construct_node(const value_type& __v);
712#endif
713 __node_holder __construct_node(const value_type& __v, size_t __hash);
714
Howard Hinnant99acc502010-09-21 17:32:39 +0000715 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000716 void __copy_assign_alloc(const __hash_table& __u)
717 {__copy_assign_alloc(__u, integral_constant<bool,
718 __node_traits::propagate_on_container_copy_assignment::value>());}
719 void __copy_assign_alloc(const __hash_table& __u, true_type);
Howard Hinnant99acc502010-09-21 17:32:39 +0000720 _LIBCPP_INLINE_VISIBILITY
721 void __copy_assign_alloc(const __hash_table& __u, false_type) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000722
723 void __move_assign(__hash_table& __u, false_type);
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000724 void __move_assign(__hash_table& __u, true_type)
725 _NOEXCEPT_(
726 is_nothrow_move_assignable<__node_allocator>::value &&
727 is_nothrow_move_assignable<hasher>::value &&
728 is_nothrow_move_assignable<key_equal>::value);
729 _LIBCPP_INLINE_VISIBILITY
730 void __move_assign_alloc(__hash_table& __u)
731 _NOEXCEPT_(
732 !__node_traits::propagate_on_container_move_assignment::value ||
733 (is_nothrow_move_assignable<__pointer_allocator>::value &&
734 is_nothrow_move_assignable<__node_allocator>::value))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000735 {__move_assign_alloc(__u, integral_constant<bool,
736 __node_traits::propagate_on_container_move_assignment::value>());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000737 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000738 void __move_assign_alloc(__hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000739 _NOEXCEPT_(
740 is_nothrow_move_assignable<__pointer_allocator>::value &&
741 is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000742 {
743 __bucket_list_.get_deleter().__alloc() =
Howard Hinnant0949eed2011-06-30 21:18:19 +0000744 _VSTD::move(__u.__bucket_list_.get_deleter().__alloc());
745 __node_alloc() = _VSTD::move(__u.__node_alloc());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000746 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000747 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000748 void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000749
750 template <class _A>
Howard Hinnant99acc502010-09-21 17:32:39 +0000751 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000752 static
753 void
754 __swap_alloc(_A& __x, _A& __y)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000755 _NOEXCEPT_(
756 !allocator_traits<_A>::propagate_on_container_swap::value ||
757 __is_nothrow_swappable<_A>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000758 {
759 __swap_alloc(__x, __y,
760 integral_constant<bool,
761 allocator_traits<_A>::propagate_on_container_swap::value
762 >());
763 }
764
765 template <class _A>
Howard Hinnant99acc502010-09-21 17:32:39 +0000766 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000767 static
768 void
769 __swap_alloc(_A& __x, _A& __y, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000770 _NOEXCEPT_(__is_nothrow_swappable<_A>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000771 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000772 using _VSTD::swap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000773 swap(__x, __y);
774 }
775
776 template <class _A>
Howard Hinnant99acc502010-09-21 17:32:39 +0000777 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000778 static
779 void
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000780 __swap_alloc(_A& __x, _A& __y, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000781
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000782 void __deallocate(__node_pointer __np) _NOEXCEPT;
783 __node_pointer __detach() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000784};
785
786template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +0000787inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000788__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table()
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000789 _NOEXCEPT_(
790 is_nothrow_default_constructible<__bucket_list>::value &&
791 is_nothrow_default_constructible<__first_node>::value &&
792 is_nothrow_default_constructible<hasher>::value &&
793 is_nothrow_default_constructible<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000794 : __p2_(0),
795 __p3_(1.0f)
796{
797}
798
799template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +0000800inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000801__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
802 const key_equal& __eql)
803 : __bucket_list_(nullptr, __bucket_list_deleter()),
804 __p1_(),
805 __p2_(0, __hf),
806 __p3_(1.0f, __eql)
807{
808}
809
810template <class _Tp, class _Hash, class _Equal, class _Alloc>
811__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
812 const key_equal& __eql,
813 const allocator_type& __a)
814 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
815 __p1_(__node_allocator(__a)),
816 __p2_(0, __hf),
817 __p3_(1.0f, __eql)
818{
819}
820
821template <class _Tp, class _Hash, class _Equal, class _Alloc>
822__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
823 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
824 __p1_(__node_allocator(__a)),
825 __p2_(0),
826 __p3_(1.0f)
827{
828}
829
830template <class _Tp, class _Hash, class _Equal, class _Alloc>
831__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
832 : __bucket_list_(nullptr,
833 __bucket_list_deleter(allocator_traits<__pointer_allocator>::
834 select_on_container_copy_construction(
835 __u.__bucket_list_.get_deleter().__alloc()), 0)),
836 __p1_(allocator_traits<__node_allocator>::
837 select_on_container_copy_construction(__u.__node_alloc())),
838 __p2_(0, __u.hash_function()),
839 __p3_(__u.__p3_)
840{
841}
842
843template <class _Tp, class _Hash, class _Equal, class _Alloc>
844__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u,
845 const allocator_type& __a)
846 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
847 __p1_(__node_allocator(__a)),
848 __p2_(0, __u.hash_function()),
849 __p3_(__u.__p3_)
850{
851}
852
Howard Hinnant73d21a42010-09-04 23:28:19 +0000853#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000854
855template <class _Tp, class _Hash, class _Equal, class _Alloc>
856__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000857 _NOEXCEPT_(
858 is_nothrow_move_constructible<__bucket_list>::value &&
859 is_nothrow_move_constructible<__first_node>::value &&
860 is_nothrow_move_constructible<hasher>::value &&
861 is_nothrow_move_constructible<key_equal>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000862 : __bucket_list_(_VSTD::move(__u.__bucket_list_)),
863 __p1_(_VSTD::move(__u.__p1_)),
864 __p2_(_VSTD::move(__u.__p2_)),
865 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000866{
867 if (size() > 0)
868 {
869 __bucket_list_[__p1_.first().__next_->__hash_ % bucket_count()] =
Howard Hinnant0949eed2011-06-30 21:18:19 +0000870 static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000871 __u.__p1_.first().__next_ = nullptr;
872 __u.size() = 0;
873 }
874}
875
876template <class _Tp, class _Hash, class _Equal, class _Alloc>
877__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u,
878 const allocator_type& __a)
879 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
880 __p1_(__node_allocator(__a)),
Howard Hinnant0949eed2011-06-30 21:18:19 +0000881 __p2_(0, _VSTD::move(__u.hash_function())),
882 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000883{
884 if (__a == allocator_type(__u.__node_alloc()))
885 {
886 __bucket_list_.reset(__u.__bucket_list_.release());
887 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
888 __u.__bucket_list_.get_deleter().size() = 0;
889 if (__u.size() > 0)
890 {
891 __p1_.first().__next_ = __u.__p1_.first().__next_;
892 __u.__p1_.first().__next_ = nullptr;
893 __bucket_list_[__p1_.first().__next_->__hash_ % bucket_count()] =
Howard Hinnant0949eed2011-06-30 21:18:19 +0000894 static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000895 size() = __u.size();
896 __u.size() = 0;
897 }
898 }
899}
900
Howard Hinnant73d21a42010-09-04 23:28:19 +0000901#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000902
903template <class _Tp, class _Hash, class _Equal, class _Alloc>
904__hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table()
905{
906 __deallocate(__p1_.first().__next_);
907}
908
909template <class _Tp, class _Hash, class _Equal, class _Alloc>
910void
911__hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc(
912 const __hash_table& __u, true_type)
913{
914 if (__node_alloc() != __u.__node_alloc())
915 {
916 clear();
917 __bucket_list_.reset();
918 __bucket_list_.get_deleter().size() = 0;
919 }
920 __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc();
921 __node_alloc() = __u.__node_alloc();
922}
923
924template <class _Tp, class _Hash, class _Equal, class _Alloc>
925__hash_table<_Tp, _Hash, _Equal, _Alloc>&
926__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u)
927{
928 if (this != &__u)
929 {
930 __copy_assign_alloc(__u);
931 hash_function() = __u.hash_function();
932 key_eq() = __u.key_eq();
933 max_load_factor() = __u.max_load_factor();
934 __assign_multi(__u.begin(), __u.end());
935 }
936 return *this;
937}
938
939template <class _Tp, class _Hash, class _Equal, class _Alloc>
940void
941__hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate(__node_pointer __np)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000942 _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000943{
944 __node_allocator& __na = __node_alloc();
945 while (__np != nullptr)
946 {
947 __node_pointer __next = __np->__next_;
Howard Hinnant0949eed2011-06-30 21:18:19 +0000948 __node_traits::destroy(__na, _VSTD::addressof(__np->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000949 __node_traits::deallocate(__na, __np, 1);
950 __np = __next;
951 }
952}
953
954template <class _Tp, class _Hash, class _Equal, class _Alloc>
955typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_pointer
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000956__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000957{
958 size_type __bc = bucket_count();
959 for (size_type __i = 0; __i < __bc; ++__i)
960 __bucket_list_[__i] = nullptr;
961 size() = 0;
962 __node_pointer __cache = __p1_.first().__next_;
963 __p1_.first().__next_ = nullptr;
964 return __cache;
965}
966
Howard Hinnant73d21a42010-09-04 23:28:19 +0000967#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000968
969template <class _Tp, class _Hash, class _Equal, class _Alloc>
970void
971__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
972 __hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000973 _NOEXCEPT_(
974 is_nothrow_move_assignable<__node_allocator>::value &&
975 is_nothrow_move_assignable<hasher>::value &&
976 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000977{
978 clear();
979 __bucket_list_.reset(__u.__bucket_list_.release());
980 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
981 __u.__bucket_list_.get_deleter().size() = 0;
982 __move_assign_alloc(__u);
983 size() = __u.size();
Howard Hinnant0949eed2011-06-30 21:18:19 +0000984 hash_function() = _VSTD::move(__u.hash_function());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000985 max_load_factor() = __u.max_load_factor();
Howard Hinnant0949eed2011-06-30 21:18:19 +0000986 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000987 __p1_.first().__next_ = __u.__p1_.first().__next_;
988 if (size() > 0)
989 {
990 __bucket_list_[__p1_.first().__next_->__hash_ % bucket_count()] =
Howard Hinnant0949eed2011-06-30 21:18:19 +0000991 static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000992 __u.__p1_.first().__next_ = nullptr;
993 __u.size() = 0;
994 }
995}
996
997template <class _Tp, class _Hash, class _Equal, class _Alloc>
998void
999__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
1000 __hash_table& __u, false_type)
1001{
1002 if (__node_alloc() == __u.__node_alloc())
1003 __move_assign(__u, true_type());
1004 else
1005 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001006 hash_function() = _VSTD::move(__u.hash_function());
1007 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001008 max_load_factor() = __u.max_load_factor();
1009 if (bucket_count() != 0)
1010 {
1011 __node_pointer __cache = __detach();
1012#ifndef _LIBCPP_NO_EXCEPTIONS
1013 try
1014 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001015#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001016 const_iterator __i = __u.begin();
1017 while (__cache != nullptr && __u.size() != 0)
1018 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001019 __cache->__value_ = _VSTD::move(__u.remove(__i++)->__value_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001020 __node_pointer __next = __cache->__next_;
1021 __node_insert_multi(__cache);
1022 __cache = __next;
1023 }
1024#ifndef _LIBCPP_NO_EXCEPTIONS
1025 }
1026 catch (...)
1027 {
1028 __deallocate(__cache);
1029 throw;
1030 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001031#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001032 __deallocate(__cache);
1033 }
1034 const_iterator __i = __u.begin();
1035 while (__u.size() != 0)
1036 {
1037 __node_holder __h =
Howard Hinnant0949eed2011-06-30 21:18:19 +00001038 __construct_node(_VSTD::move(__u.remove(__i++)->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001039 __node_insert_multi(__h.get());
1040 __h.release();
1041 }
1042 }
1043}
1044
1045template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001046inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001047__hash_table<_Tp, _Hash, _Equal, _Alloc>&
1048__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001049 _NOEXCEPT_(
1050 __node_traits::propagate_on_container_move_assignment::value &&
1051 is_nothrow_move_assignable<__node_allocator>::value &&
1052 is_nothrow_move_assignable<hasher>::value &&
1053 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001054{
1055 __move_assign(__u, integral_constant<bool,
1056 __node_traits::propagate_on_container_move_assignment::value>());
1057 return *this;
1058}
1059
Howard Hinnant73d21a42010-09-04 23:28:19 +00001060#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001061
1062template <class _Tp, class _Hash, class _Equal, class _Alloc>
1063template <class _InputIterator>
1064void
1065__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first,
1066 _InputIterator __last)
1067{
1068 if (bucket_count() != 0)
1069 {
1070 __node_pointer __cache = __detach();
1071#ifndef _LIBCPP_NO_EXCEPTIONS
1072 try
1073 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001074#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001075 for (; __cache != nullptr && __first != __last; ++__first)
1076 {
1077 __cache->__value_ = *__first;
1078 __node_pointer __next = __cache->__next_;
1079 __node_insert_unique(__cache);
1080 __cache = __next;
1081 }
1082#ifndef _LIBCPP_NO_EXCEPTIONS
1083 }
1084 catch (...)
1085 {
1086 __deallocate(__cache);
1087 throw;
1088 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001089#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001090 __deallocate(__cache);
1091 }
1092 for (; __first != __last; ++__first)
1093 __insert_unique(*__first);
1094}
1095
1096template <class _Tp, class _Hash, class _Equal, class _Alloc>
1097template <class _InputIterator>
1098void
1099__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first,
1100 _InputIterator __last)
1101{
1102 if (bucket_count() != 0)
1103 {
1104 __node_pointer __cache = __detach();
1105#ifndef _LIBCPP_NO_EXCEPTIONS
1106 try
1107 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001108#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001109 for (; __cache != nullptr && __first != __last; ++__first)
1110 {
1111 __cache->__value_ = *__first;
1112 __node_pointer __next = __cache->__next_;
1113 __node_insert_multi(__cache);
1114 __cache = __next;
1115 }
1116#ifndef _LIBCPP_NO_EXCEPTIONS
1117 }
1118 catch (...)
1119 {
1120 __deallocate(__cache);
1121 throw;
1122 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001123#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001124 __deallocate(__cache);
1125 }
1126 for (; __first != __last; ++__first)
1127 __insert_multi(*__first);
1128}
1129
1130template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001131inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001132typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001133__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001134{
1135 return iterator(__p1_.first().__next_);
1136}
1137
1138template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001139inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001140typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001141__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001142{
1143 return iterator(nullptr);
1144}
1145
1146template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001147inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001148typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001149__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001150{
1151 return const_iterator(__p1_.first().__next_);
1152}
1153
1154template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001155inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001156typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001157__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001158{
1159 return const_iterator(nullptr);
1160}
1161
1162template <class _Tp, class _Hash, class _Equal, class _Alloc>
1163void
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001164__hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001165{
1166 if (size() > 0)
1167 {
1168 __deallocate(__p1_.first().__next_);
1169 __p1_.first().__next_ = nullptr;
1170 size_type __bc = bucket_count();
1171 for (size_type __i; __i < __bc; ++__i)
1172 __bucket_list_[__i] = nullptr;
1173 size() = 0;
1174 }
1175}
1176
1177template <class _Tp, class _Hash, class _Equal, class _Alloc>
1178pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1179__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd)
1180{
1181 __nd->__hash_ = hash_function()(__nd->__value_);
1182 size_type __bc = bucket_count();
1183 bool __inserted = false;
1184 __node_pointer __ndptr;
1185 size_t __chash;
1186 if (__bc != 0)
1187 {
1188 __chash = __nd->__hash_ % __bc;
1189 __ndptr = __bucket_list_[__chash];
1190 if (__ndptr != nullptr)
1191 {
1192 for (__ndptr = __ndptr->__next_; __ndptr != nullptr &&
1193 __ndptr->__hash_ % __bc == __chash;
1194 __ndptr = __ndptr->__next_)
1195 {
1196 if (key_eq()(__ndptr->__value_, __nd->__value_))
1197 goto __done;
1198 }
1199 }
1200 }
1201 {
1202 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1203 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001204 rehash(_VSTD::max<size_type>(2 * __bc + 1,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001205 size_type(ceil(float(size() + 1) / max_load_factor()))));
1206 __bc = bucket_count();
1207 __chash = __nd->__hash_ % __bc;
1208 }
1209 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1210 __node_pointer __pn = __bucket_list_[__chash];
1211 if (__pn == nullptr)
1212 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001213 __pn = static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001214 __nd->__next_ = __pn->__next_;
1215 __pn->__next_ = __nd;
1216 // fix up __bucket_list_
1217 __bucket_list_[__chash] = __pn;
1218 if (__nd->__next_ != nullptr)
1219 __bucket_list_[__nd->__next_->__hash_ % __bc] = __nd;
1220 }
1221 else
1222 {
1223 __nd->__next_ = __pn->__next_;
1224 __pn->__next_ = __nd;
1225 }
1226 __ndptr = __nd;
1227 // increment size
1228 ++size();
1229 __inserted = true;
1230 }
1231__done:
1232 return pair<iterator, bool>(iterator(__ndptr), __inserted);
1233}
1234
1235template <class _Tp, class _Hash, class _Equal, class _Alloc>
1236typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1237__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp)
1238{
1239 __cp->__hash_ = hash_function()(__cp->__value_);
1240 size_type __bc = bucket_count();
1241 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1242 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001243 rehash(_VSTD::max<size_type>(2 * __bc + 1,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001244 size_type(ceil(float(size() + 1) / max_load_factor()))));
1245 __bc = bucket_count();
1246 }
1247 size_t __chash = __cp->__hash_ % __bc;
1248 __node_pointer __pn = __bucket_list_[__chash];
1249 if (__pn == nullptr)
1250 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001251 __pn = static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001252 __cp->__next_ = __pn->__next_;
1253 __pn->__next_ = __cp;
1254 // fix up __bucket_list_
1255 __bucket_list_[__chash] = __pn;
1256 if (__cp->__next_ != nullptr)
1257 __bucket_list_[__cp->__next_->__hash_ % __bc] = __cp;
1258 }
1259 else
1260 {
1261 for (bool __found = false; __pn->__next_ != nullptr &&
1262 __pn->__next_->__hash_ % __bc == __chash;
1263 __pn = __pn->__next_)
Howard Hinnant324bb032010-08-22 00:02:43 +00001264 {
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001265 // __found key_eq() action
1266 // false false loop
1267 // true true loop
1268 // false true set __found to true
1269 // true false break
1270 if (__found != (__pn->__next_->__hash_ == __cp->__hash_ &&
1271 key_eq()(__pn->__next_->__value_, __cp->__value_)))
1272 {
1273 if (!__found)
1274 __found = true;
1275 else
1276 break;
1277 }
1278 }
1279 __cp->__next_ = __pn->__next_;
1280 __pn->__next_ = __cp;
1281 if (__cp->__next_ != nullptr)
1282 {
1283 size_t __nhash = __cp->__next_->__hash_ % __bc;
1284 if (__nhash != __chash)
1285 __bucket_list_[__nhash] = __cp;
1286 }
1287 }
1288 ++size();
1289 return iterator(__cp);
1290}
1291
1292template <class _Tp, class _Hash, class _Equal, class _Alloc>
1293typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1294__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(
1295 const_iterator __p, __node_pointer __cp)
1296{
1297 if (__p != end() && key_eq()(*__p, __cp->__value_))
1298 {
1299 __node_pointer __np = const_cast<__node_pointer>(__p.__node_);
1300 __cp->__hash_ = __np->__hash_;
1301 size_type __bc = bucket_count();
1302 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1303 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001304 rehash(_VSTD::max<size_type>(2 * __bc + 1,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001305 size_type(ceil(float(size() + 1) / max_load_factor()))));
1306 __bc = bucket_count();
1307 }
1308 size_t __chash = __cp->__hash_ % __bc;
1309 __node_pointer __pp = __bucket_list_[__chash];
1310 while (__pp->__next_ != __np)
1311 __pp = __pp->__next_;
1312 __cp->__next_ = __np;
1313 __pp->__next_ = __cp;
1314 ++size();
1315 return iterator(__cp);
1316 }
1317 return __node_insert_multi(__cp);
1318}
1319
1320template <class _Tp, class _Hash, class _Equal, class _Alloc>
1321pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1322__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(const value_type& __x)
1323{
1324 size_t __hash = hash_function()(__x);
1325 size_type __bc = bucket_count();
1326 bool __inserted = false;
1327 __node_pointer __nd;
1328 size_t __chash;
1329 if (__bc != 0)
1330 {
1331 __chash = __hash % __bc;
1332 __nd = __bucket_list_[__chash];
1333 if (__nd != nullptr)
1334 {
1335 for (__nd = __nd->__next_; __nd != nullptr &&
1336 __nd->__hash_ % __bc == __chash;
1337 __nd = __nd->__next_)
1338 {
1339 if (key_eq()(__nd->__value_, __x))
1340 goto __done;
1341 }
1342 }
1343 }
1344 {
1345 __node_holder __h = __construct_node(__x, __hash);
1346 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1347 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001348 rehash(_VSTD::max<size_type>(2 * __bc + 1,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001349 size_type(ceil(float(size() + 1) / max_load_factor()))));
1350 __bc = bucket_count();
1351 __chash = __hash % __bc;
1352 }
1353 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1354 __node_pointer __pn = __bucket_list_[__chash];
1355 if (__pn == nullptr)
1356 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001357 __pn = static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001358 __h->__next_ = __pn->__next_;
1359 __pn->__next_ = __h.get();
1360 // fix up __bucket_list_
1361 __bucket_list_[__chash] = __pn;
1362 if (__h->__next_ != nullptr)
1363 __bucket_list_[__h->__next_->__hash_ % __bc] = __h.get();
1364 }
1365 else
1366 {
1367 __h->__next_ = __pn->__next_;
1368 __pn->__next_ = __h.get();
1369 }
1370 __nd = __h.release();
1371 // increment size
1372 ++size();
1373 __inserted = true;
1374 }
1375__done:
1376 return pair<iterator, bool>(iterator(__nd), __inserted);
1377}
1378
Howard Hinnant73d21a42010-09-04 23:28:19 +00001379#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1380#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001381
1382template <class _Tp, class _Hash, class _Equal, class _Alloc>
1383template <class... _Args>
1384pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1385__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique(_Args&&... __args)
1386{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001387 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001388 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1389 if (__r.second)
1390 __h.release();
1391 return __r;
1392}
1393
1394template <class _Tp, class _Hash, class _Equal, class _Alloc>
1395template <class... _Args>
1396typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1397__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args)
1398{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001399 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001400 iterator __r = __node_insert_multi(__h.get());
1401 __h.release();
1402 return __r;
1403}
1404
1405template <class _Tp, class _Hash, class _Equal, class _Alloc>
1406template <class... _Args>
1407typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1408__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi(
1409 const_iterator __p, _Args&&... __args)
1410{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001411 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001412 iterator __r = __node_insert_multi(__p, __h.get());
1413 __h.release();
1414 return __r;
1415}
1416
Howard Hinnant73d21a42010-09-04 23:28:19 +00001417#endif // _LIBCPP_HAS_NO_VARIADICS
1418
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001419template <class _Tp, class _Hash, class _Equal, class _Alloc>
1420template <class _P>
1421pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1422__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(_P&& __x)
1423{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001424 __node_holder __h = __construct_node(_VSTD::forward<_P>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001425 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1426 if (__r.second)
1427 __h.release();
1428 return __r;
1429}
1430
Howard Hinnant73d21a42010-09-04 23:28:19 +00001431#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001432
Howard Hinnant73d21a42010-09-04 23:28:19 +00001433#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001434
1435template <class _Tp, class _Hash, class _Equal, class _Alloc>
1436template <class _P>
1437typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1438__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(_P&& __x)
1439{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001440 __node_holder __h = __construct_node(_VSTD::forward<_P>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001441 iterator __r = __node_insert_multi(__h.get());
1442 __h.release();
1443 return __r;
1444}
1445
1446template <class _Tp, class _Hash, class _Equal, class _Alloc>
1447template <class _P>
1448typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1449__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
1450 _P&& __x)
1451{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001452 __node_holder __h = __construct_node(_VSTD::forward<_P>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001453 iterator __r = __node_insert_multi(__p, __h.get());
1454 __h.release();
1455 return __r;
1456}
1457
Howard Hinnant73d21a42010-09-04 23:28:19 +00001458#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001459
1460template <class _Tp, class _Hash, class _Equal, class _Alloc>
1461typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1462__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const value_type& __x)
1463{
1464 __node_holder __h = __construct_node(__x);
1465 iterator __r = __node_insert_multi(__h.get());
1466 __h.release();
1467 return __r;
1468}
1469
1470template <class _Tp, class _Hash, class _Equal, class _Alloc>
1471typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1472__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
1473 const value_type& __x)
1474{
1475 __node_holder __h = __construct_node(__x);
1476 iterator __r = __node_insert_multi(__p, __h.get());
1477 __h.release();
1478 return __r;
1479}
1480
Howard Hinnant73d21a42010-09-04 23:28:19 +00001481#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001482
1483template <class _Tp, class _Hash, class _Equal, class _Alloc>
1484void
1485__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n)
1486{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001487 __n = __next_prime(_VSTD::max<size_type>(__n, size() > 0));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001488 size_type __bc = bucket_count();
1489 if (__n > __bc)
1490 __rehash(__n);
1491 else
1492 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001493 __n = _VSTD::max<size_type>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001494 (
1495 __n,
1496 __next_prime(size_t(ceil(float(size()) / max_load_factor())))
1497 );
1498 if (__n < __bc)
1499 __rehash(__n);
1500 }
1501}
1502
1503template <class _Tp, class _Hash, class _Equal, class _Alloc>
1504void
1505__hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc)
1506{
1507 __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc();
1508 __bucket_list_.reset(__nbc > 0 ?
1509 __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr);
1510 __bucket_list_.get_deleter().size() = __nbc;
1511 if (__nbc > 0)
1512 {
1513 for (size_type __i = 0; __i < __nbc; ++__i)
1514 __bucket_list_[__i] = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00001515 __node_pointer __pp(static_cast<__node_pointer>(_VSTD::addressof(__p1_.first())));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001516 __node_pointer __cp = __pp->__next_;
1517 if (__cp != nullptr)
1518 {
1519 size_type __chash = __cp->__hash_ % __nbc;
1520 __bucket_list_[__chash] = __pp;
1521 size_type __phash = __chash;
1522 for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr;
1523 __cp = __pp->__next_)
1524 {
1525 __chash = __cp->__hash_ % __nbc;
1526 if (__chash == __phash)
1527 __pp = __cp;
1528 else
1529 {
1530 if (__bucket_list_[__chash] == nullptr)
1531 {
1532 __bucket_list_[__chash] = __pp;
1533 __pp = __cp;
1534 __phash = __chash;
1535 }
1536 else
1537 {
1538 __node_pointer __np = __cp;
1539 for (; __np->__next_ != nullptr &&
1540 key_eq()(__cp->__value_, __np->__next_->__value_);
1541 __np = __np->__next_)
1542 ;
1543 __pp->__next_ = __np->__next_;
1544 __np->__next_ = __bucket_list_[__chash]->__next_;
1545 __bucket_list_[__chash]->__next_ = __cp;
Howard Hinnant324bb032010-08-22 00:02:43 +00001546
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001547 }
1548 }
1549 }
1550 }
1551 }
1552}
1553
1554template <class _Tp, class _Hash, class _Equal, class _Alloc>
1555template <class _Key>
1556typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1557__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k)
1558{
1559 size_t __hash = hash_function()(__k);
1560 size_type __bc = bucket_count();
1561 if (__bc != 0)
1562 {
1563 size_t __chash = __hash % __bc;
1564 __node_pointer __nd = __bucket_list_[__chash];
1565 if (__nd != nullptr)
1566 {
1567 for (__nd = __nd->__next_; __nd != nullptr &&
1568 __nd->__hash_ % __bc == __chash;
1569 __nd = __nd->__next_)
1570 {
1571 if (key_eq()(__nd->__value_, __k))
1572 return iterator(__nd);
1573 }
1574 }
1575 }
1576 return end();
1577}
1578
1579template <class _Tp, class _Hash, class _Equal, class _Alloc>
1580template <class _Key>
1581typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1582__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const
1583{
1584 size_t __hash = hash_function()(__k);
1585 size_type __bc = bucket_count();
1586 if (__bc != 0)
1587 {
1588 size_t __chash = __hash % __bc;
1589 __node_const_pointer __nd = __bucket_list_[__chash];
1590 if (__nd != nullptr)
1591 {
1592 for (__nd = __nd->__next_; __nd != nullptr &&
1593 __nd->__hash_ % __bc == __chash;
1594 __nd = __nd->__next_)
1595 {
1596 if (key_eq()(__nd->__value_, __k))
1597 return const_iterator(__nd);
1598 }
1599 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001600
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001601 }
1602 return end();
1603}
1604
Howard Hinnant73d21a42010-09-04 23:28:19 +00001605#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1606#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001607
1608template <class _Tp, class _Hash, class _Equal, class _Alloc>
1609template <class ..._Args>
1610typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1611__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args)
1612{
1613 __node_allocator& __na = __node_alloc();
1614 __node_holder __h(__node_traits::allocate(__na, 1), _D(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001615 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001616 __h.get_deleter().__value_constructed = true;
1617 __h->__hash_ = hash_function()(__h->__value_);
1618 __h->__next_ = nullptr;
1619 return __h;
1620}
1621
Howard Hinnant73d21a42010-09-04 23:28:19 +00001622#endif // _LIBCPP_HAS_NO_VARIADICS
1623
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001624template <class _Tp, class _Hash, class _Equal, class _Alloc>
1625typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1626__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(value_type&& __v,
1627 size_t __hash)
1628{
1629 __node_allocator& __na = __node_alloc();
1630 __node_holder __h(__node_traits::allocate(__na, 1), _D(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001631 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::move(__v));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001632 __h.get_deleter().__value_constructed = true;
1633 __h->__hash_ = __hash;
1634 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00001635 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001636}
1637
Howard Hinnant73d21a42010-09-04 23:28:19 +00001638#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001639
1640template <class _Tp, class _Hash, class _Equal, class _Alloc>
1641typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1642__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v)
1643{
1644 __node_allocator& __na = __node_alloc();
1645 __node_holder __h(__node_traits::allocate(__na, 1), _D(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001646 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001647 __h.get_deleter().__value_constructed = true;
1648 __h->__hash_ = hash_function()(__h->__value_);
1649 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00001650 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001651}
1652
Howard Hinnant73d21a42010-09-04 23:28:19 +00001653#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001654
1655template <class _Tp, class _Hash, class _Equal, class _Alloc>
1656typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1657__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v,
1658 size_t __hash)
1659{
1660 __node_allocator& __na = __node_alloc();
1661 __node_holder __h(__node_traits::allocate(__na, 1), _D(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001662 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001663 __h.get_deleter().__value_constructed = true;
1664 __h->__hash_ = __hash;
1665 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00001666 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001667}
1668
1669template <class _Tp, class _Hash, class _Equal, class _Alloc>
1670typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1671__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p)
1672{
1673 __node_pointer __np = const_cast<__node_pointer>(__p.__node_);
1674 iterator __r(__np);
1675 ++__r;
1676 remove(__p);
1677 return __r;
1678}
1679
1680template <class _Tp, class _Hash, class _Equal, class _Alloc>
1681typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1682__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first,
1683 const_iterator __last)
1684{
1685 for (const_iterator __p = __first; __first != __last; __p = __first)
1686 {
1687 ++__first;
1688 erase(__p);
1689 }
1690 __node_pointer __np = const_cast<__node_pointer>(__last.__node_);
1691 return iterator (__np);
1692}
1693
1694template <class _Tp, class _Hash, class _Equal, class _Alloc>
1695template <class _Key>
1696typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1697__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k)
1698{
1699 iterator __i = find(__k);
1700 if (__i == end())
1701 return 0;
1702 erase(__i);
1703 return 1;
1704}
1705
1706template <class _Tp, class _Hash, class _Equal, class _Alloc>
1707template <class _Key>
1708typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1709__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k)
1710{
1711 size_type __r = 0;
1712 iterator __i = find(__k);
1713 if (__i != end())
1714 {
1715 iterator __e = end();
1716 do
1717 {
1718 erase(__i++);
1719 ++__r;
1720 } while (__i != __e && key_eq()(*__i, __k));
1721 }
1722 return __r;
1723}
1724
1725template <class _Tp, class _Hash, class _Equal, class _Alloc>
1726typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001727__hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001728{
1729 // current node
1730 __node_pointer __cn = const_cast<__node_pointer>(__p.__node_);
1731 size_type __bc = bucket_count();
1732 size_t __chash = __cn->__hash_ % __bc;
1733 // find previous node
1734 __node_pointer __pn = __bucket_list_[__chash];
1735 for (; __pn->__next_ != __cn; __pn = __pn->__next_)
1736 ;
1737 // Fix up __bucket_list_
1738 // if __pn is not in same bucket (before begin is not in same bucket) &&
1739 // if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
Howard Hinnant0949eed2011-06-30 21:18:19 +00001740 if (__pn == _VSTD::addressof(__p1_.first()) || __pn->__hash_ % __bc != __chash)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001741 {
1742 if (__cn->__next_ == nullptr || __cn->__next_->__hash_ % __bc != __chash)
1743 __bucket_list_[__chash] = nullptr;
1744 }
1745 // if __cn->__next_ is not in same bucket (nullptr is in same bucket)
1746 if (__cn->__next_ != nullptr)
1747 {
1748 size_t __nhash = __cn->__next_->__hash_ % __bc;
1749 if (__nhash != __chash)
1750 __bucket_list_[__nhash] = __pn;
1751 }
1752 // remove __cn
1753 __pn->__next_ = __cn->__next_;
1754 __cn->__next_ = nullptr;
1755 --size();
1756 return __node_holder(__cn, _D(__node_alloc()));
1757}
1758
1759template <class _Tp, class _Hash, class _Equal, class _Alloc>
1760template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39 +00001761inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001762typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1763__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const
1764{
1765 return static_cast<size_type>(find(__k) != end());
1766}
1767
1768template <class _Tp, class _Hash, class _Equal, class _Alloc>
1769template <class _Key>
1770typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1771__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const
1772{
1773 size_type __r = 0;
1774 const_iterator __i = find(__k);
1775 if (__i != end())
1776 {
1777 const_iterator __e = end();
1778 do
1779 {
1780 ++__i;
1781 ++__r;
1782 } while (__i != __e && key_eq()(*__i, __k));
1783 }
1784 return __r;
1785}
1786
1787template <class _Tp, class _Hash, class _Equal, class _Alloc>
1788template <class _Key>
1789pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
1790 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1791__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
1792 const _Key& __k)
1793{
1794 iterator __i = find(__k);
1795 iterator __j = __i;
1796 if (__i != end())
1797 ++__j;
1798 return pair<iterator, iterator>(__i, __j);
1799}
1800
1801template <class _Tp, class _Hash, class _Equal, class _Alloc>
1802template <class _Key>
1803pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
1804 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1805__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
1806 const _Key& __k) const
1807{
1808 const_iterator __i = find(__k);
1809 const_iterator __j = __i;
1810 if (__i != end())
1811 ++__j;
1812 return pair<const_iterator, const_iterator>(__i, __j);
1813}
1814
1815template <class _Tp, class _Hash, class _Equal, class _Alloc>
1816template <class _Key>
1817pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
1818 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1819__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
1820 const _Key& __k)
1821{
1822 iterator __i = find(__k);
1823 iterator __j = __i;
1824 if (__i != end())
1825 {
1826 iterator __e = end();
1827 do
1828 {
1829 ++__j;
1830 } while (__j != __e && key_eq()(*__j, __k));
1831 }
1832 return pair<iterator, iterator>(__i, __j);
1833}
1834
1835template <class _Tp, class _Hash, class _Equal, class _Alloc>
1836template <class _Key>
1837pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
1838 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1839__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
1840 const _Key& __k) const
1841{
1842 const_iterator __i = find(__k);
1843 const_iterator __j = __i;
1844 if (__i != end())
1845 {
1846 const_iterator __e = end();
1847 do
1848 {
1849 ++__j;
1850 } while (__j != __e && key_eq()(*__j, __k));
1851 }
1852 return pair<const_iterator, const_iterator>(__i, __j);
1853}
1854
1855template <class _Tp, class _Hash, class _Equal, class _Alloc>
1856void
1857__hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001858 _NOEXCEPT_(
1859 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
1860 __is_nothrow_swappable<__pointer_allocator>::value) &&
1861 (!__node_traits::propagate_on_container_swap::value ||
1862 __is_nothrow_swappable<__node_allocator>::value) &&
1863 __is_nothrow_swappable<hasher>::value &&
1864 __is_nothrow_swappable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001865{
1866 {
1867 __node_pointer_pointer __npp = __bucket_list_.release();
1868 __bucket_list_.reset(__u.__bucket_list_.release());
1869 __u.__bucket_list_.reset(__npp);
1870 }
Howard Hinnant0949eed2011-06-30 21:18:19 +00001871 _VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001872 __swap_alloc(__bucket_list_.get_deleter().__alloc(),
1873 __u.__bucket_list_.get_deleter().__alloc());
1874 __swap_alloc(__node_alloc(), __u.__node_alloc());
Howard Hinnant0949eed2011-06-30 21:18:19 +00001875 _VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001876 __p2_.swap(__u.__p2_);
1877 __p3_.swap(__u.__p3_);
1878 if (size() > 0)
1879 __bucket_list_[__p1_.first().__next_->__hash_ % bucket_count()] =
Howard Hinnant0949eed2011-06-30 21:18:19 +00001880 static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001881 if (__u.size() > 0)
1882 __u.__bucket_list_[__u.__p1_.first().__next_->__hash_ % __u.bucket_count()] =
Howard Hinnant0949eed2011-06-30 21:18:19 +00001883 static_cast<__node_pointer>(_VSTD::addressof(__u.__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001884}
1885
1886template <class _Tp, class _Hash, class _Equal, class _Alloc>
1887typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1888__hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const
1889{
1890 __node_const_pointer __np = __bucket_list_[__n];
1891 size_type __bc = bucket_count();
1892 size_type __r = 0;
1893 if (__np != nullptr)
1894 {
1895 for (__np = __np->__next_; __np != nullptr &&
1896 __np->__hash_ % __bc == __n;
1897 __np = __np->__next_, ++__r)
1898 ;
1899 }
1900 return __r;
1901}
1902
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001903template <class _Tp, class _Hash, class _Equal, class _Alloc>
1904inline _LIBCPP_INLINE_VISIBILITY
1905void
1906swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x,
1907 __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y)
1908 _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
1909{
1910 __x.swap(__y);
1911}
1912
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001913_LIBCPP_END_NAMESPACE_STD
1914
1915#endif // _LIBCPP__HASH_TABLE