blob: fad4e0e6ad4a983701cb7224894e6f56705118b5 [file] [log] [blame]
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001// -*- C++ -*-
2//===----------------------------------------------------------------------===//
3//
Howard Hinnantf5256e12010-05-11 21:36:01 +00004// The LLVM Compiler Infrastructure
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00005//
Howard Hinnantb64f8b02010-11-16 22:09:02 +00006// This file is dual licensed under the MIT and the University of Illinois Open
7// Source Licenses. See LICENSE.TXT for details.
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00008//
9//===----------------------------------------------------------------------===//
10
11#ifndef _LIBCPP__HASH_TABLE
12#define _LIBCPP__HASH_TABLE
13
14#include <__config>
15#include <initializer_list>
16#include <memory>
17#include <iterator>
18#include <algorithm>
19#include <cmath>
20
Howard Hinnant66c6f972011-11-29 16:45:27 +000021#include <__undef_min_max>
22
Howard Hinnant08e17472011-10-17 20:05:10 +000023#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000024#pragma GCC system_header
Howard Hinnant08e17472011-10-17 20:05:10 +000025#endif
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000026
27_LIBCPP_BEGIN_NAMESPACE_STD
28
Howard Hinnant99acc502010-09-21 17:32:39 +000029_LIBCPP_VISIBLE
Howard Hinnant2b1b2d42011-06-14 19:58:17 +000030size_t __next_prime(size_t __n);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000031
32template <class _NodePtr>
33struct __hash_node_base
34{
35 typedef __hash_node_base __first_node;
Howard Hinnantdf85e572011-02-27 18:02:02 +000036 // typedef _NodePtr pointer;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000037
Howard Hinnantdf85e572011-02-27 18:02:02 +000038 _NodePtr __next_;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000039
Howard Hinnant5f2f14c2011-06-04 18:54:24 +000040 _LIBCPP_INLINE_VISIBILITY __hash_node_base() _NOEXCEPT : __next_(nullptr) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000041};
42
43template <class _Tp, class _VoidPtr>
44struct __hash_node
45 : public __hash_node_base
46 <
47 typename pointer_traits<_VoidPtr>::template
48#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
49 rebind<__hash_node<_Tp, _VoidPtr> >
50#else
51 rebind<__hash_node<_Tp, _VoidPtr> >::other
52#endif
53 >
54{
55 typedef _Tp value_type;
56
57 size_t __hash_;
58 value_type __value_;
59};
60
Howard Hinnant2b1b2d42011-06-14 19:58:17 +000061template <class _Tp, class _Hash, class _Equal, class _Alloc> class __hash_table;
62template <class _ConstNodePtr> class __hash_const_iterator;
63template <class _HashIterator> class __hash_map_iterator;
64template <class _HashIterator> class __hash_map_const_iterator;
65template <class _Key, class _Tp, class _Hash, class _Pred, class _Alloc>
66 class _LIBCPP_VISIBLE unordered_map;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000067
68template <class _NodePtr>
Howard Hinnant99acc502010-09-21 17:32:39 +000069class _LIBCPP_VISIBLE __hash_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000070{
71 typedef _NodePtr __node_pointer;
72
73 __node_pointer __node_;
74
75public:
76 typedef forward_iterator_tag iterator_category;
77 typedef typename pointer_traits<__node_pointer>::element_type::value_type value_type;
78 typedef typename pointer_traits<__node_pointer>::difference_type difference_type;
79 typedef value_type& reference;
80 typedef typename pointer_traits<__node_pointer>::template
81#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
82 rebind<value_type>
83#else
84 rebind<value_type>::other
85#endif
86 pointer;
87
Howard Hinnant5f2f14c2011-06-04 18:54:24 +000088 _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000089
Howard Hinnant99acc502010-09-21 17:32:39 +000090 _LIBCPP_INLINE_VISIBILITY
91 reference operator*() const {return __node_->__value_;}
92 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant0949eed2011-06-30 21:18:19 +000093 pointer operator->() const {return _VSTD::addressof(__node_->__value_);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000094
Howard Hinnant99acc502010-09-21 17:32:39 +000095 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +000096 __hash_iterator& operator++()
97 {
98 __node_ = __node_->__next_;
99 return *this;
100 }
101
Howard Hinnant99acc502010-09-21 17:32:39 +0000102 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000103 __hash_iterator operator++(int)
104 {
105 __hash_iterator __t(*this);
106 ++(*this);
107 return __t;
108 }
109
Howard Hinnant99acc502010-09-21 17:32:39 +0000110 friend _LIBCPP_INLINE_VISIBILITY
111 bool operator==(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000112 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000113 friend _LIBCPP_INLINE_VISIBILITY
114 bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000115 {return __x.__node_ != __y.__node_;}
116
117private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000118 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000119 __hash_iterator(__node_pointer __node) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000120 : __node_(__node)
121 {}
122
123 template <class, class, class, class> friend class __hash_table;
Howard Hinnant99acc502010-09-21 17:32:39 +0000124 template <class> friend class _LIBCPP_VISIBLE __hash_const_iterator;
125 template <class> friend class _LIBCPP_VISIBLE __hash_map_iterator;
126 template <class, class, class, class, class> friend class _LIBCPP_VISIBLE unordered_map;
127 template <class, class, class, class, class> friend class _LIBCPP_VISIBLE unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000128};
129
130template <class _ConstNodePtr>
Howard Hinnant99acc502010-09-21 17:32:39 +0000131class _LIBCPP_VISIBLE __hash_const_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000132{
133 typedef _ConstNodePtr __node_pointer;
134
135 __node_pointer __node_;
136
137 typedef typename remove_const<
138 typename pointer_traits<__node_pointer>::element_type
139 >::type __node;
140
141public:
142 typedef forward_iterator_tag iterator_category;
143 typedef typename __node::value_type value_type;
144 typedef typename pointer_traits<__node_pointer>::difference_type difference_type;
145 typedef const value_type& reference;
146 typedef typename pointer_traits<__node_pointer>::template
147#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
148 rebind<const value_type>
149#else
150 rebind<const value_type>::other
151#endif
152 pointer;
153 typedef typename pointer_traits<__node_pointer>::template
154#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
155 rebind<__node>
156#else
157 rebind<__node>::other
158#endif
159 __non_const_node_pointer;
160 typedef __hash_iterator<__non_const_node_pointer> __non_const_iterator;
161
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000162 _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000163 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000164 __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000165 : __node_(__x.__node_)
166 {}
167
Howard Hinnant99acc502010-09-21 17:32:39 +0000168 _LIBCPP_INLINE_VISIBILITY
169 reference operator*() const {return __node_->__value_;}
170 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant0949eed2011-06-30 21:18:19 +0000171 pointer operator->() const {return _VSTD::addressof(__node_->__value_);}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000172
Howard Hinnant99acc502010-09-21 17:32:39 +0000173 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000174 __hash_const_iterator& operator++()
175 {
176 __node_ = __node_->__next_;
177 return *this;
178 }
179
Howard Hinnant99acc502010-09-21 17:32:39 +0000180 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000181 __hash_const_iterator operator++(int)
182 {
183 __hash_const_iterator __t(*this);
184 ++(*this);
185 return __t;
186 }
187
Howard Hinnant99acc502010-09-21 17:32:39 +0000188 friend _LIBCPP_INLINE_VISIBILITY
189 bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000190 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000191 friend _LIBCPP_INLINE_VISIBILITY
192 bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000193 {return __x.__node_ != __y.__node_;}
194
195private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000196 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000197 __hash_const_iterator(__node_pointer __node) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000198 : __node_(__node)
199 {}
200
201 template <class, class, class, class> friend class __hash_table;
Howard Hinnant99acc502010-09-21 17:32:39 +0000202 template <class> friend class _LIBCPP_VISIBLE __hash_map_const_iterator;
203 template <class, class, class, class, class> friend class _LIBCPP_VISIBLE unordered_map;
204 template <class, class, class, class, class> friend class _LIBCPP_VISIBLE unordered_multimap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000205};
206
Howard Hinnant2b1b2d42011-06-14 19:58:17 +0000207template <class _ConstNodePtr> class _LIBCPP_VISIBLE __hash_const_local_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000208
209template <class _NodePtr>
Howard Hinnant99acc502010-09-21 17:32:39 +0000210class _LIBCPP_VISIBLE __hash_local_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000211{
212 typedef _NodePtr __node_pointer;
213
214 __node_pointer __node_;
215 size_t __bucket_;
216 size_t __bucket_count_;
217
218 typedef pointer_traits<__node_pointer> __pointer_traits;
219public:
220 typedef forward_iterator_tag iterator_category;
221 typedef typename __pointer_traits::element_type::value_type value_type;
222 typedef typename __pointer_traits::difference_type difference_type;
223 typedef value_type& reference;
224 typedef typename __pointer_traits::template
225#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
226 rebind<value_type>
227#else
228 rebind<value_type>::other
229#endif
230 pointer;
231
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000232 _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000233
Howard Hinnant99acc502010-09-21 17:32:39 +0000234 _LIBCPP_INLINE_VISIBILITY
235 reference operator*() const {return __node_->__value_;}
236 _LIBCPP_INLINE_VISIBILITY
237 pointer operator->() const {return &__node_->__value_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000238
Howard Hinnant99acc502010-09-21 17:32:39 +0000239 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000240 __hash_local_iterator& operator++()
241 {
242 __node_ = __node_->__next_;
243 if (__node_ != nullptr && __node_->__hash_ % __bucket_count_ != __bucket_)
244 __node_ = nullptr;
245 return *this;
246 }
247
Howard Hinnant99acc502010-09-21 17:32:39 +0000248 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000249 __hash_local_iterator operator++(int)
250 {
251 __hash_local_iterator __t(*this);
252 ++(*this);
253 return __t;
254 }
255
Howard Hinnant99acc502010-09-21 17:32:39 +0000256 friend _LIBCPP_INLINE_VISIBILITY
257 bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000258 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000259 friend _LIBCPP_INLINE_VISIBILITY
260 bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000261 {return __x.__node_ != __y.__node_;}
262
263private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000264 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000265 __hash_local_iterator(__node_pointer __node, size_t __bucket,
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000266 size_t __bucket_count) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000267 : __node_(__node),
268 __bucket_(__bucket),
269 __bucket_count_(__bucket_count)
270 {
271 if (__node_ != nullptr)
272 __node_ = __node_->__next_;
273 }
274
275 template <class, class, class, class> friend class __hash_table;
Howard Hinnant99acc502010-09-21 17:32:39 +0000276 template <class> friend class _LIBCPP_VISIBLE __hash_const_local_iterator;
277 template <class> friend class _LIBCPP_VISIBLE __hash_map_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000278};
279
280template <class _ConstNodePtr>
Howard Hinnant99acc502010-09-21 17:32:39 +0000281class _LIBCPP_VISIBLE __hash_const_local_iterator
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000282{
283 typedef _ConstNodePtr __node_pointer;
284
285 __node_pointer __node_;
286 size_t __bucket_;
287 size_t __bucket_count_;
288
289 typedef pointer_traits<__node_pointer> __pointer_traits;
290 typedef typename __pointer_traits::element_type __node;
291 typedef typename remove_const<__node>::type __non_const_node;
292 typedef typename pointer_traits<__node_pointer>::template
293#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
294 rebind<__non_const_node>
295#else
296 rebind<__non_const_node>::other
297#endif
298 __non_const_node_pointer;
299 typedef __hash_local_iterator<__non_const_node_pointer>
300 __non_const_iterator;
301public:
302 typedef forward_iterator_tag iterator_category;
303 typedef typename remove_const<
304 typename __pointer_traits::element_type::value_type
305 >::type value_type;
306 typedef typename __pointer_traits::difference_type difference_type;
307 typedef const value_type& reference;
308 typedef typename __pointer_traits::template
309#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
310 rebind<const value_type>
311#else
312 rebind<const value_type>::other
313#endif
314 pointer;
315
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000316 _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000317 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000318 __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000319 : __node_(__x.__node_),
320 __bucket_(__x.__bucket_),
321 __bucket_count_(__x.__bucket_count_)
322 {}
323
Howard Hinnant99acc502010-09-21 17:32:39 +0000324 _LIBCPP_INLINE_VISIBILITY
325 reference operator*() const {return __node_->__value_;}
326 _LIBCPP_INLINE_VISIBILITY
327 pointer operator->() const {return &__node_->__value_;}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000328
Howard Hinnant99acc502010-09-21 17:32:39 +0000329 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000330 __hash_const_local_iterator& operator++()
331 {
332 __node_ = __node_->__next_;
333 if (__node_ != nullptr && __node_->__hash_ % __bucket_count_ != __bucket_)
334 __node_ = nullptr;
335 return *this;
336 }
337
Howard Hinnant99acc502010-09-21 17:32:39 +0000338 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000339 __hash_const_local_iterator operator++(int)
340 {
341 __hash_const_local_iterator __t(*this);
342 ++(*this);
343 return __t;
344 }
345
Howard Hinnant99acc502010-09-21 17:32:39 +0000346 friend _LIBCPP_INLINE_VISIBILITY
347 bool operator==(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000348 {return __x.__node_ == __y.__node_;}
Howard Hinnant99acc502010-09-21 17:32:39 +0000349 friend _LIBCPP_INLINE_VISIBILITY
350 bool operator!=(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000351 {return __x.__node_ != __y.__node_;}
352
353private:
Howard Hinnant99acc502010-09-21 17:32:39 +0000354 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000355 __hash_const_local_iterator(__node_pointer __node, size_t __bucket,
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000356 size_t __bucket_count) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000357 : __node_(__node),
358 __bucket_(__bucket),
359 __bucket_count_(__bucket_count)
360 {
361 if (__node_ != nullptr)
362 __node_ = __node_->__next_;
363 }
364
365 template <class, class, class, class> friend class __hash_table;
Howard Hinnant99acc502010-09-21 17:32:39 +0000366 template <class> friend class _LIBCPP_VISIBLE __hash_map_const_iterator;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000367};
368
369template <class _Alloc>
370class __bucket_list_deallocator
371{
372 typedef _Alloc allocator_type;
373 typedef allocator_traits<allocator_type> __alloc_traits;
374 typedef typename __alloc_traits::size_type size_type;
375
376 __compressed_pair<size_type, allocator_type> __data_;
377public:
378 typedef typename __alloc_traits::pointer pointer;
379
Howard Hinnant99acc502010-09-21 17:32:39 +0000380 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000381 __bucket_list_deallocator()
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000382 _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000383 : __data_(0) {}
Howard Hinnant99acc502010-09-21 17:32:39 +0000384
385 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000386 __bucket_list_deallocator(const allocator_type& __a, size_type __size)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000387 _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000388 : __data_(__size, __a) {}
389
Howard Hinnant73d21a42010-09-04 23:28:19 +0000390#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000391
Howard Hinnant99acc502010-09-21 17:32:39 +0000392 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000393 __bucket_list_deallocator(__bucket_list_deallocator&& __x)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000394 _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000395 : __data_(_VSTD::move(__x.__data_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000396 {
397 __x.size() = 0;
398 }
399
Howard Hinnant73d21a42010-09-04 23:28:19 +0000400#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000401
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000402 _LIBCPP_INLINE_VISIBILITY
403 size_type& size() _NOEXCEPT {return __data_.first();}
404 _LIBCPP_INLINE_VISIBILITY
405 size_type size() const _NOEXCEPT {return __data_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000406
Howard Hinnant99acc502010-09-21 17:32:39 +0000407 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000408 allocator_type& __alloc() _NOEXCEPT {return __data_.second();}
409 _LIBCPP_INLINE_VISIBILITY
410 const allocator_type& __alloc() const _NOEXCEPT {return __data_.second();}
411
412 _LIBCPP_INLINE_VISIBILITY
413 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000414 {
415 __alloc_traits::deallocate(__alloc(), __p, size());
416 }
417};
418
Howard Hinnant2b1b2d42011-06-14 19:58:17 +0000419template <class _Alloc> class __hash_map_node_destructor;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000420
421template <class _Alloc>
422class __hash_node_destructor
423{
424 typedef _Alloc allocator_type;
425 typedef allocator_traits<allocator_type> __alloc_traits;
426 typedef typename __alloc_traits::value_type::value_type value_type;
427public:
428 typedef typename __alloc_traits::pointer pointer;
429private:
430
431 allocator_type& __na_;
432
433 __hash_node_destructor& operator=(const __hash_node_destructor&);
434
435public:
436 bool __value_constructed;
437
Howard Hinnant99acc502010-09-21 17:32:39 +0000438 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant199d0ae2011-07-31 17:04:30 +0000439 explicit __hash_node_destructor(allocator_type& __na,
440 bool __constructed = false) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000441 : __na_(__na),
Howard Hinnant199d0ae2011-07-31 17:04:30 +0000442 __value_constructed(__constructed)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000443 {}
444
Howard Hinnant99acc502010-09-21 17:32:39 +0000445 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000446 void operator()(pointer __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000447 {
448 if (__value_constructed)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000449 __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000450 if (__p)
451 __alloc_traits::deallocate(__na_, __p, 1);
452 }
453
454 template <class> friend class __hash_map_node_destructor;
455};
456
457template <class _Tp, class _Hash, class _Equal, class _Alloc>
458class __hash_table
459{
460public:
461 typedef _Tp value_type;
462 typedef _Hash hasher;
463 typedef _Equal key_equal;
464 typedef _Alloc allocator_type;
465
466private:
467 typedef allocator_traits<allocator_type> __alloc_traits;
468public:
469 typedef value_type& reference;
470 typedef const value_type& const_reference;
471 typedef typename __alloc_traits::pointer pointer;
472 typedef typename __alloc_traits::const_pointer const_pointer;
473 typedef typename __alloc_traits::size_type size_type;
474 typedef typename __alloc_traits::difference_type difference_type;
475public:
476 // Create __node
477 typedef __hash_node<value_type, typename __alloc_traits::void_pointer> __node;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000478 typedef typename __alloc_traits::template
479#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
480 rebind_alloc<__node>
481#else
482 rebind_alloc<__node>::other
483#endif
484 __node_allocator;
485 typedef allocator_traits<__node_allocator> __node_traits;
486 typedef typename __node_traits::pointer __node_pointer;
487 typedef typename __node_traits::const_pointer __node_const_pointer;
Howard Hinnantf8880d02011-12-12 17:26:24 +0000488 typedef __hash_node_base<__node_pointer> __first_node;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000489
490private:
491
492 typedef typename __node_traits::template
493#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES
494 rebind_alloc<__node_pointer>
495#else
496 rebind_alloc<__node_pointer>::other
497#endif
498 __pointer_allocator;
499 typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter;
500 typedef unique_ptr<__node_pointer[], __bucket_list_deleter> __bucket_list;
501 typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits;
502 typedef typename __bucket_list_deleter::pointer __node_pointer_pointer;
503
504 // --- Member data begin ---
505 __bucket_list __bucket_list_;
506 __compressed_pair<__first_node, __node_allocator> __p1_;
507 __compressed_pair<size_type, hasher> __p2_;
508 __compressed_pair<float, key_equal> __p3_;
509 // --- Member data end ---
510
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000511 _LIBCPP_INLINE_VISIBILITY
512 size_type& size() _NOEXCEPT {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000513public:
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000514 _LIBCPP_INLINE_VISIBILITY
515 size_type size() const _NOEXCEPT {return __p2_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000516
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000517 _LIBCPP_INLINE_VISIBILITY
518 hasher& hash_function() _NOEXCEPT {return __p2_.second();}
519 _LIBCPP_INLINE_VISIBILITY
520 const hasher& hash_function() const _NOEXCEPT {return __p2_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000521
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000522 _LIBCPP_INLINE_VISIBILITY
523 float& max_load_factor() _NOEXCEPT {return __p3_.first();}
524 _LIBCPP_INLINE_VISIBILITY
525 float max_load_factor() const _NOEXCEPT {return __p3_.first();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000526
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000527 _LIBCPP_INLINE_VISIBILITY
528 key_equal& key_eq() _NOEXCEPT {return __p3_.second();}
529 _LIBCPP_INLINE_VISIBILITY
530 const key_equal& key_eq() const _NOEXCEPT {return __p3_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000531
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000532 _LIBCPP_INLINE_VISIBILITY
533 __node_allocator& __node_alloc() _NOEXCEPT {return __p1_.second();}
534 _LIBCPP_INLINE_VISIBILITY
535 const __node_allocator& __node_alloc() const _NOEXCEPT
536 {return __p1_.second();}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000537
538public:
539 typedef __hash_iterator<__node_pointer> iterator;
540 typedef __hash_const_iterator<__node_const_pointer> const_iterator;
541 typedef __hash_local_iterator<__node_pointer> local_iterator;
542 typedef __hash_const_local_iterator<__node_const_pointer> const_local_iterator;
543
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000544 __hash_table()
545 _NOEXCEPT_(
546 is_nothrow_default_constructible<__bucket_list>::value &&
547 is_nothrow_default_constructible<__first_node>::value &&
548 is_nothrow_default_constructible<__node_allocator>::value &&
549 is_nothrow_default_constructible<hasher>::value &&
550 is_nothrow_default_constructible<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000551 __hash_table(const hasher& __hf, const key_equal& __eql);
552 __hash_table(const hasher& __hf, const key_equal& __eql,
553 const allocator_type& __a);
554 explicit __hash_table(const allocator_type& __a);
555 __hash_table(const __hash_table& __u);
556 __hash_table(const __hash_table& __u, const allocator_type& __a);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000557#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000558 __hash_table(__hash_table&& __u)
559 _NOEXCEPT_(
560 is_nothrow_move_constructible<__bucket_list>::value &&
561 is_nothrow_move_constructible<__first_node>::value &&
562 is_nothrow_move_constructible<__node_allocator>::value &&
563 is_nothrow_move_constructible<hasher>::value &&
564 is_nothrow_move_constructible<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000565 __hash_table(__hash_table&& __u, const allocator_type& __a);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000566#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000567 ~__hash_table();
568
569 __hash_table& operator=(const __hash_table& __u);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000570#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000571 __hash_table& operator=(__hash_table&& __u)
572 _NOEXCEPT_(
573 __node_traits::propagate_on_container_move_assignment::value &&
574 is_nothrow_move_assignable<__node_allocator>::value &&
575 is_nothrow_move_assignable<hasher>::value &&
576 is_nothrow_move_assignable<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000577#endif
578 template <class _InputIterator>
579 void __assign_unique(_InputIterator __first, _InputIterator __last);
580 template <class _InputIterator>
581 void __assign_multi(_InputIterator __first, _InputIterator __last);
582
Howard Hinnant99acc502010-09-21 17:32:39 +0000583 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000584 size_type max_size() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000585 {
586 return allocator_traits<__pointer_allocator>::max_size(
587 __bucket_list_.get_deleter().__alloc());
588 }
589
590 pair<iterator, bool> __node_insert_unique(__node_pointer __nd);
591 iterator __node_insert_multi(__node_pointer __nd);
592 iterator __node_insert_multi(const_iterator __p,
593 __node_pointer __nd);
594
Howard Hinnant73d21a42010-09-04 23:28:19 +0000595#if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000596 template <class... _Args>
597 pair<iterator, bool> __emplace_unique(_Args&&... __args);
598 template <class... _Args>
599 iterator __emplace_multi(_Args&&... __args);
600 template <class... _Args>
601 iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000602#endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000603
604 pair<iterator, bool> __insert_unique(const value_type& __x);
605
Howard Hinnant73d21a42010-09-04 23:28:19 +0000606#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant99968442011-11-29 18:15:50 +0000607 template <class _Pp>
608 pair<iterator, bool> __insert_unique(_Pp&& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000609#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000610
Howard Hinnant73d21a42010-09-04 23:28:19 +0000611#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnant99968442011-11-29 18:15:50 +0000612 template <class _Pp>
613 iterator __insert_multi(_Pp&& __x);
614 template <class _Pp>
615 iterator __insert_multi(const_iterator __p, _Pp&& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000616#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000617 iterator __insert_multi(const value_type& __x);
618 iterator __insert_multi(const_iterator __p, const value_type& __x);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000619#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000620
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000621 void clear() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000622 void rehash(size_type __n);
Howard Hinnant99acc502010-09-21 17:32:39 +0000623 _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000624 {rehash(static_cast<size_type>(ceil(__n / max_load_factor())));}
Howard Hinnant99acc502010-09-21 17:32:39 +0000625
626 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000627 size_type bucket_count() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000628 {
629 return __bucket_list_.get_deleter().size();
630 }
631
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000632 iterator begin() _NOEXCEPT;
633 iterator end() _NOEXCEPT;
634 const_iterator begin() const _NOEXCEPT;
635 const_iterator end() const _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000636
637 template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39 +0000638 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000639 size_type bucket(const _Key& __k) const
640 {return hash_function()(__k) % bucket_count();}
641
642 template <class _Key>
643 iterator find(const _Key& __x);
644 template <class _Key>
645 const_iterator find(const _Key& __x) const;
646
Howard Hinnant99968442011-11-29 18:15:50 +0000647 typedef __hash_node_destructor<__node_allocator> _Dp;
648 typedef unique_ptr<__node, _Dp> __node_holder;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000649
650 iterator erase(const_iterator __p);
651 iterator erase(const_iterator __first, const_iterator __last);
652 template <class _Key>
653 size_type __erase_unique(const _Key& __k);
654 template <class _Key>
655 size_type __erase_multi(const _Key& __k);
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000656 __node_holder remove(const_iterator __p) _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000657
658 template <class _Key>
659 size_type __count_unique(const _Key& __k) const;
660 template <class _Key>
661 size_type __count_multi(const _Key& __k) const;
662
663 template <class _Key>
664 pair<iterator, iterator>
665 __equal_range_unique(const _Key& __k);
666 template <class _Key>
667 pair<const_iterator, const_iterator>
668 __equal_range_unique(const _Key& __k) const;
669
670 template <class _Key>
671 pair<iterator, iterator>
672 __equal_range_multi(const _Key& __k);
673 template <class _Key>
674 pair<const_iterator, const_iterator>
675 __equal_range_multi(const _Key& __k) const;
676
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000677 void swap(__hash_table& __u)
678 _NOEXCEPT_(
679 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
680 __is_nothrow_swappable<__pointer_allocator>::value) &&
681 (!__node_traits::propagate_on_container_swap::value ||
682 __is_nothrow_swappable<__node_allocator>::value) &&
683 __is_nothrow_swappable<hasher>::value &&
684 __is_nothrow_swappable<key_equal>::value);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000685
Howard Hinnant99acc502010-09-21 17:32:39 +0000686 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000687 size_type max_bucket_count() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000688 {return __bucket_list_.get_deleter().__alloc().max_size();}
689 size_type bucket_size(size_type __n) const;
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000690 _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000691 {
692 size_type __bc = bucket_count();
693 return __bc != 0 ? (float)size() / __bc : 0.f;
694 }
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000695 _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT
Howard Hinnant0949eed2011-06-30 21:18:19 +0000696 {max_load_factor() = _VSTD::max(__mlf, load_factor());}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000697
Howard Hinnant99acc502010-09-21 17:32:39 +0000698 _LIBCPP_INLINE_VISIBILITY local_iterator begin(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000699 {return local_iterator(__bucket_list_[__n], __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000700 _LIBCPP_INLINE_VISIBILITY local_iterator end(size_type __n)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000701 {return local_iterator(nullptr, __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000702 _LIBCPP_INLINE_VISIBILITY const_local_iterator cbegin(size_type __n) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000703 {return const_local_iterator(__bucket_list_[__n], __n, bucket_count());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000704 _LIBCPP_INLINE_VISIBILITY const_local_iterator cend(size_type __n) const
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000705 {return const_local_iterator(nullptr, __n, bucket_count());}
706private:
707 void __rehash(size_type __n);
708
Howard Hinnant73d21a42010-09-04 23:28:19 +0000709#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
710#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000711 template <class ..._Args>
712 __node_holder __construct_node(_Args&& ...__args);
Howard Hinnantbfd55302010-09-04 23:46:48 +0000713#endif // _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000714 __node_holder __construct_node(value_type&& __v, size_t __hash);
Howard Hinnant73d21a42010-09-04 23:28:19 +0000715#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000716 __node_holder __construct_node(const value_type& __v);
717#endif
718 __node_holder __construct_node(const value_type& __v, size_t __hash);
719
Howard Hinnant99acc502010-09-21 17:32:39 +0000720 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000721 void __copy_assign_alloc(const __hash_table& __u)
722 {__copy_assign_alloc(__u, integral_constant<bool,
723 __node_traits::propagate_on_container_copy_assignment::value>());}
724 void __copy_assign_alloc(const __hash_table& __u, true_type);
Howard Hinnant99acc502010-09-21 17:32:39 +0000725 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantec3773c2011-12-01 20:21:04 +0000726 void __copy_assign_alloc(const __hash_table&, false_type) {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000727
728 void __move_assign(__hash_table& __u, false_type);
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000729 void __move_assign(__hash_table& __u, true_type)
730 _NOEXCEPT_(
731 is_nothrow_move_assignable<__node_allocator>::value &&
732 is_nothrow_move_assignable<hasher>::value &&
733 is_nothrow_move_assignable<key_equal>::value);
734 _LIBCPP_INLINE_VISIBILITY
735 void __move_assign_alloc(__hash_table& __u)
736 _NOEXCEPT_(
737 !__node_traits::propagate_on_container_move_assignment::value ||
738 (is_nothrow_move_assignable<__pointer_allocator>::value &&
739 is_nothrow_move_assignable<__node_allocator>::value))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000740 {__move_assign_alloc(__u, integral_constant<bool,
741 __node_traits::propagate_on_container_move_assignment::value>());}
Howard Hinnant99acc502010-09-21 17:32:39 +0000742 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000743 void __move_assign_alloc(__hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000744 _NOEXCEPT_(
745 is_nothrow_move_assignable<__pointer_allocator>::value &&
746 is_nothrow_move_assignable<__node_allocator>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000747 {
748 __bucket_list_.get_deleter().__alloc() =
Howard Hinnant0949eed2011-06-30 21:18:19 +0000749 _VSTD::move(__u.__bucket_list_.get_deleter().__alloc());
750 __node_alloc() = _VSTD::move(__u.__node_alloc());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000751 }
Howard Hinnant99acc502010-09-21 17:32:39 +0000752 _LIBCPP_INLINE_VISIBILITY
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000753 void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000754
Howard Hinnant99968442011-11-29 18:15:50 +0000755 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:39 +0000756 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000757 static
758 void
Howard Hinnant99968442011-11-29 18:15:50 +0000759 __swap_alloc(_Ap& __x, _Ap& __y)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000760 _NOEXCEPT_(
Howard Hinnant99968442011-11-29 18:15:50 +0000761 !allocator_traits<_Ap>::propagate_on_container_swap::value ||
762 __is_nothrow_swappable<_Ap>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000763 {
764 __swap_alloc(__x, __y,
765 integral_constant<bool,
Howard Hinnant99968442011-11-29 18:15:50 +0000766 allocator_traits<_Ap>::propagate_on_container_swap::value
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000767 >());
768 }
769
Howard Hinnant99968442011-11-29 18:15:50 +0000770 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:39 +0000771 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000772 static
773 void
Howard Hinnant99968442011-11-29 18:15:50 +0000774 __swap_alloc(_Ap& __x, _Ap& __y, true_type)
775 _NOEXCEPT_(__is_nothrow_swappable<_Ap>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000776 {
Howard Hinnant0949eed2011-06-30 21:18:19 +0000777 using _VSTD::swap;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000778 swap(__x, __y);
779 }
780
Howard Hinnant99968442011-11-29 18:15:50 +0000781 template <class _Ap>
Howard Hinnant99acc502010-09-21 17:32:39 +0000782 _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000783 static
784 void
Howard Hinnantec3773c2011-12-01 20:21:04 +0000785 __swap_alloc(_Ap&, _Ap&, false_type) _NOEXCEPT {}
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000786
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000787 void __deallocate(__node_pointer __np) _NOEXCEPT;
788 __node_pointer __detach() _NOEXCEPT;
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000789};
790
791template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +0000792inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000793__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table()
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000794 _NOEXCEPT_(
795 is_nothrow_default_constructible<__bucket_list>::value &&
796 is_nothrow_default_constructible<__first_node>::value &&
797 is_nothrow_default_constructible<hasher>::value &&
798 is_nothrow_default_constructible<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000799 : __p2_(0),
800 __p3_(1.0f)
801{
802}
803
804template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +0000805inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000806__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
807 const key_equal& __eql)
808 : __bucket_list_(nullptr, __bucket_list_deleter()),
809 __p1_(),
810 __p2_(0, __hf),
811 __p3_(1.0f, __eql)
812{
813}
814
815template <class _Tp, class _Hash, class _Equal, class _Alloc>
816__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf,
817 const key_equal& __eql,
818 const allocator_type& __a)
819 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
820 __p1_(__node_allocator(__a)),
821 __p2_(0, __hf),
822 __p3_(1.0f, __eql)
823{
824}
825
826template <class _Tp, class _Hash, class _Equal, class _Alloc>
827__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a)
828 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
829 __p1_(__node_allocator(__a)),
830 __p2_(0),
831 __p3_(1.0f)
832{
833}
834
835template <class _Tp, class _Hash, class _Equal, class _Alloc>
836__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u)
837 : __bucket_list_(nullptr,
838 __bucket_list_deleter(allocator_traits<__pointer_allocator>::
839 select_on_container_copy_construction(
840 __u.__bucket_list_.get_deleter().__alloc()), 0)),
841 __p1_(allocator_traits<__node_allocator>::
842 select_on_container_copy_construction(__u.__node_alloc())),
843 __p2_(0, __u.hash_function()),
844 __p3_(__u.__p3_)
845{
846}
847
848template <class _Tp, class _Hash, class _Equal, class _Alloc>
849__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u,
850 const allocator_type& __a)
851 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
852 __p1_(__node_allocator(__a)),
853 __p2_(0, __u.hash_function()),
854 __p3_(__u.__p3_)
855{
856}
857
Howard Hinnant73d21a42010-09-04 23:28:19 +0000858#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000859
860template <class _Tp, class _Hash, class _Equal, class _Alloc>
861__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000862 _NOEXCEPT_(
863 is_nothrow_move_constructible<__bucket_list>::value &&
864 is_nothrow_move_constructible<__first_node>::value &&
865 is_nothrow_move_constructible<hasher>::value &&
866 is_nothrow_move_constructible<key_equal>::value)
Howard Hinnant0949eed2011-06-30 21:18:19 +0000867 : __bucket_list_(_VSTD::move(__u.__bucket_list_)),
868 __p1_(_VSTD::move(__u.__p1_)),
869 __p2_(_VSTD::move(__u.__p2_)),
870 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000871{
872 if (size() > 0)
873 {
874 __bucket_list_[__p1_.first().__next_->__hash_ % bucket_count()] =
Howard Hinnant0949eed2011-06-30 21:18:19 +0000875 static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000876 __u.__p1_.first().__next_ = nullptr;
877 __u.size() = 0;
878 }
879}
880
881template <class _Tp, class _Hash, class _Equal, class _Alloc>
882__hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u,
883 const allocator_type& __a)
884 : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)),
885 __p1_(__node_allocator(__a)),
Howard Hinnant0949eed2011-06-30 21:18:19 +0000886 __p2_(0, _VSTD::move(__u.hash_function())),
887 __p3_(_VSTD::move(__u.__p3_))
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000888{
889 if (__a == allocator_type(__u.__node_alloc()))
890 {
891 __bucket_list_.reset(__u.__bucket_list_.release());
892 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
893 __u.__bucket_list_.get_deleter().size() = 0;
894 if (__u.size() > 0)
895 {
896 __p1_.first().__next_ = __u.__p1_.first().__next_;
897 __u.__p1_.first().__next_ = nullptr;
898 __bucket_list_[__p1_.first().__next_->__hash_ % bucket_count()] =
Howard Hinnant0949eed2011-06-30 21:18:19 +0000899 static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000900 size() = __u.size();
901 __u.size() = 0;
902 }
903 }
904}
905
Howard Hinnant73d21a42010-09-04 23:28:19 +0000906#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000907
908template <class _Tp, class _Hash, class _Equal, class _Alloc>
909__hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table()
910{
911 __deallocate(__p1_.first().__next_);
912}
913
914template <class _Tp, class _Hash, class _Equal, class _Alloc>
915void
916__hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc(
917 const __hash_table& __u, true_type)
918{
919 if (__node_alloc() != __u.__node_alloc())
920 {
921 clear();
922 __bucket_list_.reset();
923 __bucket_list_.get_deleter().size() = 0;
924 }
925 __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc();
926 __node_alloc() = __u.__node_alloc();
927}
928
929template <class _Tp, class _Hash, class _Equal, class _Alloc>
930__hash_table<_Tp, _Hash, _Equal, _Alloc>&
931__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u)
932{
933 if (this != &__u)
934 {
935 __copy_assign_alloc(__u);
936 hash_function() = __u.hash_function();
937 key_eq() = __u.key_eq();
938 max_load_factor() = __u.max_load_factor();
939 __assign_multi(__u.begin(), __u.end());
940 }
941 return *this;
942}
943
944template <class _Tp, class _Hash, class _Equal, class _Alloc>
945void
946__hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate(__node_pointer __np)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000947 _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000948{
949 __node_allocator& __na = __node_alloc();
950 while (__np != nullptr)
951 {
952 __node_pointer __next = __np->__next_;
Howard Hinnant0949eed2011-06-30 21:18:19 +0000953 __node_traits::destroy(__na, _VSTD::addressof(__np->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000954 __node_traits::deallocate(__na, __np, 1);
955 __np = __next;
956 }
957}
958
959template <class _Tp, class _Hash, class _Equal, class _Alloc>
960typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_pointer
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000961__hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000962{
963 size_type __bc = bucket_count();
964 for (size_type __i = 0; __i < __bc; ++__i)
965 __bucket_list_[__i] = nullptr;
966 size() = 0;
967 __node_pointer __cache = __p1_.first().__next_;
968 __p1_.first().__next_ = nullptr;
969 return __cache;
970}
971
Howard Hinnant73d21a42010-09-04 23:28:19 +0000972#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000973
974template <class _Tp, class _Hash, class _Equal, class _Alloc>
975void
976__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
977 __hash_table& __u, true_type)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +0000978 _NOEXCEPT_(
979 is_nothrow_move_assignable<__node_allocator>::value &&
980 is_nothrow_move_assignable<hasher>::value &&
981 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000982{
983 clear();
984 __bucket_list_.reset(__u.__bucket_list_.release());
985 __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size();
986 __u.__bucket_list_.get_deleter().size() = 0;
987 __move_assign_alloc(__u);
988 size() = __u.size();
Howard Hinnant0949eed2011-06-30 21:18:19 +0000989 hash_function() = _VSTD::move(__u.hash_function());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000990 max_load_factor() = __u.max_load_factor();
Howard Hinnant0949eed2011-06-30 21:18:19 +0000991 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000992 __p1_.first().__next_ = __u.__p1_.first().__next_;
993 if (size() > 0)
994 {
995 __bucket_list_[__p1_.first().__next_->__hash_ % bucket_count()] =
Howard Hinnant0949eed2011-06-30 21:18:19 +0000996 static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +0000997 __u.__p1_.first().__next_ = nullptr;
998 __u.size() = 0;
999 }
1000}
1001
1002template <class _Tp, class _Hash, class _Equal, class _Alloc>
1003void
1004__hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign(
1005 __hash_table& __u, false_type)
1006{
1007 if (__node_alloc() == __u.__node_alloc())
1008 __move_assign(__u, true_type());
1009 else
1010 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001011 hash_function() = _VSTD::move(__u.hash_function());
1012 key_eq() = _VSTD::move(__u.key_eq());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001013 max_load_factor() = __u.max_load_factor();
1014 if (bucket_count() != 0)
1015 {
1016 __node_pointer __cache = __detach();
1017#ifndef _LIBCPP_NO_EXCEPTIONS
1018 try
1019 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001020#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001021 const_iterator __i = __u.begin();
1022 while (__cache != nullptr && __u.size() != 0)
1023 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001024 __cache->__value_ = _VSTD::move(__u.remove(__i++)->__value_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001025 __node_pointer __next = __cache->__next_;
1026 __node_insert_multi(__cache);
1027 __cache = __next;
1028 }
1029#ifndef _LIBCPP_NO_EXCEPTIONS
1030 }
1031 catch (...)
1032 {
1033 __deallocate(__cache);
1034 throw;
1035 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001036#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001037 __deallocate(__cache);
1038 }
1039 const_iterator __i = __u.begin();
1040 while (__u.size() != 0)
1041 {
1042 __node_holder __h =
Howard Hinnant0949eed2011-06-30 21:18:19 +00001043 __construct_node(_VSTD::move(__u.remove(__i++)->__value_));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001044 __node_insert_multi(__h.get());
1045 __h.release();
1046 }
1047 }
1048}
1049
1050template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001051inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001052__hash_table<_Tp, _Hash, _Equal, _Alloc>&
1053__hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001054 _NOEXCEPT_(
1055 __node_traits::propagate_on_container_move_assignment::value &&
1056 is_nothrow_move_assignable<__node_allocator>::value &&
1057 is_nothrow_move_assignable<hasher>::value &&
1058 is_nothrow_move_assignable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001059{
1060 __move_assign(__u, integral_constant<bool,
1061 __node_traits::propagate_on_container_move_assignment::value>());
1062 return *this;
1063}
1064
Howard Hinnant73d21a42010-09-04 23:28:19 +00001065#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001066
1067template <class _Tp, class _Hash, class _Equal, class _Alloc>
1068template <class _InputIterator>
1069void
1070__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first,
1071 _InputIterator __last)
1072{
1073 if (bucket_count() != 0)
1074 {
1075 __node_pointer __cache = __detach();
1076#ifndef _LIBCPP_NO_EXCEPTIONS
1077 try
1078 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001079#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001080 for (; __cache != nullptr && __first != __last; ++__first)
1081 {
1082 __cache->__value_ = *__first;
1083 __node_pointer __next = __cache->__next_;
1084 __node_insert_unique(__cache);
1085 __cache = __next;
1086 }
1087#ifndef _LIBCPP_NO_EXCEPTIONS
1088 }
1089 catch (...)
1090 {
1091 __deallocate(__cache);
1092 throw;
1093 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001094#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001095 __deallocate(__cache);
1096 }
1097 for (; __first != __last; ++__first)
1098 __insert_unique(*__first);
1099}
1100
1101template <class _Tp, class _Hash, class _Equal, class _Alloc>
1102template <class _InputIterator>
1103void
1104__hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first,
1105 _InputIterator __last)
1106{
1107 if (bucket_count() != 0)
1108 {
1109 __node_pointer __cache = __detach();
1110#ifndef _LIBCPP_NO_EXCEPTIONS
1111 try
1112 {
Howard Hinnant324bb032010-08-22 00:02:43 +00001113#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001114 for (; __cache != nullptr && __first != __last; ++__first)
1115 {
1116 __cache->__value_ = *__first;
1117 __node_pointer __next = __cache->__next_;
1118 __node_insert_multi(__cache);
1119 __cache = __next;
1120 }
1121#ifndef _LIBCPP_NO_EXCEPTIONS
1122 }
1123 catch (...)
1124 {
1125 __deallocate(__cache);
1126 throw;
1127 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001128#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001129 __deallocate(__cache);
1130 }
1131 for (; __first != __last; ++__first)
1132 __insert_multi(*__first);
1133}
1134
1135template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001136inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001137typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001138__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001139{
1140 return iterator(__p1_.first().__next_);
1141}
1142
1143template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001144inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001145typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001146__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001147{
1148 return iterator(nullptr);
1149}
1150
1151template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001152inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001153typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001154__hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001155{
1156 return const_iterator(__p1_.first().__next_);
1157}
1158
1159template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99acc502010-09-21 17:32:39 +00001160inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001161typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001162__hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001163{
1164 return const_iterator(nullptr);
1165}
1166
1167template <class _Tp, class _Hash, class _Equal, class _Alloc>
1168void
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001169__hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001170{
1171 if (size() > 0)
1172 {
1173 __deallocate(__p1_.first().__next_);
1174 __p1_.first().__next_ = nullptr;
1175 size_type __bc = bucket_count();
Howard Hinnant9f66bff2011-07-05 14:14:17 +00001176 for (size_type __i = 0; __i < __bc; ++__i)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001177 __bucket_list_[__i] = nullptr;
1178 size() = 0;
1179 }
1180}
1181
1182template <class _Tp, class _Hash, class _Equal, class _Alloc>
1183pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1184__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd)
1185{
1186 __nd->__hash_ = hash_function()(__nd->__value_);
1187 size_type __bc = bucket_count();
1188 bool __inserted = false;
1189 __node_pointer __ndptr;
1190 size_t __chash;
1191 if (__bc != 0)
1192 {
1193 __chash = __nd->__hash_ % __bc;
1194 __ndptr = __bucket_list_[__chash];
1195 if (__ndptr != nullptr)
1196 {
1197 for (__ndptr = __ndptr->__next_; __ndptr != nullptr &&
1198 __ndptr->__hash_ % __bc == __chash;
1199 __ndptr = __ndptr->__next_)
1200 {
1201 if (key_eq()(__ndptr->__value_, __nd->__value_))
1202 goto __done;
1203 }
1204 }
1205 }
1206 {
1207 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1208 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001209 rehash(_VSTD::max<size_type>(2 * __bc + 1,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001210 size_type(ceil(float(size() + 1) / max_load_factor()))));
1211 __bc = bucket_count();
1212 __chash = __nd->__hash_ % __bc;
1213 }
1214 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1215 __node_pointer __pn = __bucket_list_[__chash];
1216 if (__pn == nullptr)
1217 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001218 __pn = static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001219 __nd->__next_ = __pn->__next_;
1220 __pn->__next_ = __nd;
1221 // fix up __bucket_list_
1222 __bucket_list_[__chash] = __pn;
1223 if (__nd->__next_ != nullptr)
1224 __bucket_list_[__nd->__next_->__hash_ % __bc] = __nd;
1225 }
1226 else
1227 {
1228 __nd->__next_ = __pn->__next_;
1229 __pn->__next_ = __nd;
1230 }
1231 __ndptr = __nd;
1232 // increment size
1233 ++size();
1234 __inserted = true;
1235 }
1236__done:
1237 return pair<iterator, bool>(iterator(__ndptr), __inserted);
1238}
1239
1240template <class _Tp, class _Hash, class _Equal, class _Alloc>
1241typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1242__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp)
1243{
1244 __cp->__hash_ = hash_function()(__cp->__value_);
1245 size_type __bc = bucket_count();
1246 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1247 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001248 rehash(_VSTD::max<size_type>(2 * __bc + 1,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001249 size_type(ceil(float(size() + 1) / max_load_factor()))));
1250 __bc = bucket_count();
1251 }
1252 size_t __chash = __cp->__hash_ % __bc;
1253 __node_pointer __pn = __bucket_list_[__chash];
1254 if (__pn == nullptr)
1255 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001256 __pn = static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001257 __cp->__next_ = __pn->__next_;
1258 __pn->__next_ = __cp;
1259 // fix up __bucket_list_
1260 __bucket_list_[__chash] = __pn;
1261 if (__cp->__next_ != nullptr)
1262 __bucket_list_[__cp->__next_->__hash_ % __bc] = __cp;
1263 }
1264 else
1265 {
1266 for (bool __found = false; __pn->__next_ != nullptr &&
1267 __pn->__next_->__hash_ % __bc == __chash;
1268 __pn = __pn->__next_)
Howard Hinnant324bb032010-08-22 00:02:43 +00001269 {
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001270 // __found key_eq() action
1271 // false false loop
1272 // true true loop
1273 // false true set __found to true
1274 // true false break
1275 if (__found != (__pn->__next_->__hash_ == __cp->__hash_ &&
1276 key_eq()(__pn->__next_->__value_, __cp->__value_)))
1277 {
1278 if (!__found)
1279 __found = true;
1280 else
1281 break;
1282 }
1283 }
1284 __cp->__next_ = __pn->__next_;
1285 __pn->__next_ = __cp;
1286 if (__cp->__next_ != nullptr)
1287 {
1288 size_t __nhash = __cp->__next_->__hash_ % __bc;
1289 if (__nhash != __chash)
1290 __bucket_list_[__nhash] = __cp;
1291 }
1292 }
1293 ++size();
1294 return iterator(__cp);
1295}
1296
1297template <class _Tp, class _Hash, class _Equal, class _Alloc>
1298typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1299__hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(
1300 const_iterator __p, __node_pointer __cp)
1301{
1302 if (__p != end() && key_eq()(*__p, __cp->__value_))
1303 {
1304 __node_pointer __np = const_cast<__node_pointer>(__p.__node_);
1305 __cp->__hash_ = __np->__hash_;
1306 size_type __bc = bucket_count();
1307 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1308 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001309 rehash(_VSTD::max<size_type>(2 * __bc + 1,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001310 size_type(ceil(float(size() + 1) / max_load_factor()))));
1311 __bc = bucket_count();
1312 }
1313 size_t __chash = __cp->__hash_ % __bc;
1314 __node_pointer __pp = __bucket_list_[__chash];
1315 while (__pp->__next_ != __np)
1316 __pp = __pp->__next_;
1317 __cp->__next_ = __np;
1318 __pp->__next_ = __cp;
1319 ++size();
1320 return iterator(__cp);
1321 }
1322 return __node_insert_multi(__cp);
1323}
1324
1325template <class _Tp, class _Hash, class _Equal, class _Alloc>
1326pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1327__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(const value_type& __x)
1328{
1329 size_t __hash = hash_function()(__x);
1330 size_type __bc = bucket_count();
1331 bool __inserted = false;
1332 __node_pointer __nd;
1333 size_t __chash;
1334 if (__bc != 0)
1335 {
1336 __chash = __hash % __bc;
1337 __nd = __bucket_list_[__chash];
1338 if (__nd != nullptr)
1339 {
1340 for (__nd = __nd->__next_; __nd != nullptr &&
1341 __nd->__hash_ % __bc == __chash;
1342 __nd = __nd->__next_)
1343 {
1344 if (key_eq()(__nd->__value_, __x))
1345 goto __done;
1346 }
1347 }
1348 }
1349 {
1350 __node_holder __h = __construct_node(__x, __hash);
1351 if (size()+1 > __bc * max_load_factor() || __bc == 0)
1352 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001353 rehash(_VSTD::max<size_type>(2 * __bc + 1,
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001354 size_type(ceil(float(size() + 1) / max_load_factor()))));
1355 __bc = bucket_count();
1356 __chash = __hash % __bc;
1357 }
1358 // insert_after __bucket_list_[__chash], or __first_node if bucket is null
1359 __node_pointer __pn = __bucket_list_[__chash];
1360 if (__pn == nullptr)
1361 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001362 __pn = static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001363 __h->__next_ = __pn->__next_;
1364 __pn->__next_ = __h.get();
1365 // fix up __bucket_list_
1366 __bucket_list_[__chash] = __pn;
1367 if (__h->__next_ != nullptr)
1368 __bucket_list_[__h->__next_->__hash_ % __bc] = __h.get();
1369 }
1370 else
1371 {
1372 __h->__next_ = __pn->__next_;
1373 __pn->__next_ = __h.get();
1374 }
1375 __nd = __h.release();
1376 // increment size
1377 ++size();
1378 __inserted = true;
1379 }
1380__done:
1381 return pair<iterator, bool>(iterator(__nd), __inserted);
1382}
1383
Howard Hinnant73d21a42010-09-04 23:28:19 +00001384#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1385#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001386
1387template <class _Tp, class _Hash, class _Equal, class _Alloc>
1388template <class... _Args>
1389pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
1390__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique(_Args&&... __args)
1391{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001392 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001393 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1394 if (__r.second)
1395 __h.release();
1396 return __r;
1397}
1398
1399template <class _Tp, class _Hash, class _Equal, class _Alloc>
1400template <class... _Args>
1401typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1402__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args)
1403{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001404 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001405 iterator __r = __node_insert_multi(__h.get());
1406 __h.release();
1407 return __r;
1408}
1409
1410template <class _Tp, class _Hash, class _Equal, class _Alloc>
1411template <class... _Args>
1412typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1413__hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi(
1414 const_iterator __p, _Args&&... __args)
1415{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001416 __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001417 iterator __r = __node_insert_multi(__p, __h.get());
1418 __h.release();
1419 return __r;
1420}
1421
Howard Hinnant73d21a42010-09-04 23:28:19 +00001422#endif // _LIBCPP_HAS_NO_VARIADICS
1423
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001424template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:50 +00001425template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001426pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool>
Howard Hinnant99968442011-11-29 18:15:50 +00001427__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(_Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001428{
Howard Hinnant99968442011-11-29 18:15:50 +00001429 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001430 pair<iterator, bool> __r = __node_insert_unique(__h.get());
1431 if (__r.second)
1432 __h.release();
1433 return __r;
1434}
1435
Howard Hinnant73d21a42010-09-04 23:28:19 +00001436#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001437
Howard Hinnant73d21a42010-09-04 23:28:19 +00001438#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001439
1440template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:50 +00001441template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001442typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
Howard Hinnant99968442011-11-29 18:15:50 +00001443__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(_Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001444{
Howard Hinnant99968442011-11-29 18:15:50 +00001445 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001446 iterator __r = __node_insert_multi(__h.get());
1447 __h.release();
1448 return __r;
1449}
1450
1451template <class _Tp, class _Hash, class _Equal, class _Alloc>
Howard Hinnant99968442011-11-29 18:15:50 +00001452template <class _Pp>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001453typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1454__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
Howard Hinnant99968442011-11-29 18:15:50 +00001455 _Pp&& __x)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001456{
Howard Hinnant99968442011-11-29 18:15:50 +00001457 __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001458 iterator __r = __node_insert_multi(__p, __h.get());
1459 __h.release();
1460 return __r;
1461}
1462
Howard Hinnant73d21a42010-09-04 23:28:19 +00001463#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001464
1465template <class _Tp, class _Hash, class _Equal, class _Alloc>
1466typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1467__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const value_type& __x)
1468{
1469 __node_holder __h = __construct_node(__x);
1470 iterator __r = __node_insert_multi(__h.get());
1471 __h.release();
1472 return __r;
1473}
1474
1475template <class _Tp, class _Hash, class _Equal, class _Alloc>
1476typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1477__hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p,
1478 const value_type& __x)
1479{
1480 __node_holder __h = __construct_node(__x);
1481 iterator __r = __node_insert_multi(__p, __h.get());
1482 __h.release();
1483 return __r;
1484}
1485
Howard Hinnant73d21a42010-09-04 23:28:19 +00001486#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001487
1488template <class _Tp, class _Hash, class _Equal, class _Alloc>
1489void
1490__hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n)
1491{
Howard Hinnant0949eed2011-06-30 21:18:19 +00001492 __n = __next_prime(_VSTD::max<size_type>(__n, size() > 0));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001493 size_type __bc = bucket_count();
1494 if (__n > __bc)
1495 __rehash(__n);
1496 else
1497 {
Howard Hinnant0949eed2011-06-30 21:18:19 +00001498 __n = _VSTD::max<size_type>
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001499 (
1500 __n,
1501 __next_prime(size_t(ceil(float(size()) / max_load_factor())))
1502 );
1503 if (__n < __bc)
1504 __rehash(__n);
1505 }
1506}
1507
1508template <class _Tp, class _Hash, class _Equal, class _Alloc>
1509void
1510__hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc)
1511{
1512 __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc();
1513 __bucket_list_.reset(__nbc > 0 ?
1514 __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr);
1515 __bucket_list_.get_deleter().size() = __nbc;
1516 if (__nbc > 0)
1517 {
1518 for (size_type __i = 0; __i < __nbc; ++__i)
1519 __bucket_list_[__i] = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00001520 __node_pointer __pp(static_cast<__node_pointer>(_VSTD::addressof(__p1_.first())));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001521 __node_pointer __cp = __pp->__next_;
1522 if (__cp != nullptr)
1523 {
1524 size_type __chash = __cp->__hash_ % __nbc;
1525 __bucket_list_[__chash] = __pp;
1526 size_type __phash = __chash;
1527 for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr;
1528 __cp = __pp->__next_)
1529 {
1530 __chash = __cp->__hash_ % __nbc;
1531 if (__chash == __phash)
1532 __pp = __cp;
1533 else
1534 {
1535 if (__bucket_list_[__chash] == nullptr)
1536 {
1537 __bucket_list_[__chash] = __pp;
1538 __pp = __cp;
1539 __phash = __chash;
1540 }
1541 else
1542 {
1543 __node_pointer __np = __cp;
1544 for (; __np->__next_ != nullptr &&
1545 key_eq()(__cp->__value_, __np->__next_->__value_);
1546 __np = __np->__next_)
1547 ;
1548 __pp->__next_ = __np->__next_;
1549 __np->__next_ = __bucket_list_[__chash]->__next_;
1550 __bucket_list_[__chash]->__next_ = __cp;
Howard Hinnant324bb032010-08-22 00:02:43 +00001551
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001552 }
1553 }
1554 }
1555 }
1556 }
1557}
1558
1559template <class _Tp, class _Hash, class _Equal, class _Alloc>
1560template <class _Key>
1561typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1562__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k)
1563{
1564 size_t __hash = hash_function()(__k);
1565 size_type __bc = bucket_count();
1566 if (__bc != 0)
1567 {
1568 size_t __chash = __hash % __bc;
1569 __node_pointer __nd = __bucket_list_[__chash];
1570 if (__nd != nullptr)
1571 {
1572 for (__nd = __nd->__next_; __nd != nullptr &&
1573 __nd->__hash_ % __bc == __chash;
1574 __nd = __nd->__next_)
1575 {
1576 if (key_eq()(__nd->__value_, __k))
1577 return iterator(__nd);
1578 }
1579 }
1580 }
1581 return end();
1582}
1583
1584template <class _Tp, class _Hash, class _Equal, class _Alloc>
1585template <class _Key>
1586typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator
1587__hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const
1588{
1589 size_t __hash = hash_function()(__k);
1590 size_type __bc = bucket_count();
1591 if (__bc != 0)
1592 {
1593 size_t __chash = __hash % __bc;
1594 __node_const_pointer __nd = __bucket_list_[__chash];
1595 if (__nd != nullptr)
1596 {
1597 for (__nd = __nd->__next_; __nd != nullptr &&
1598 __nd->__hash_ % __bc == __chash;
1599 __nd = __nd->__next_)
1600 {
1601 if (key_eq()(__nd->__value_, __k))
1602 return const_iterator(__nd);
1603 }
1604 }
Howard Hinnant324bb032010-08-22 00:02:43 +00001605
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001606 }
1607 return end();
1608}
1609
Howard Hinnant73d21a42010-09-04 23:28:19 +00001610#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
1611#ifndef _LIBCPP_HAS_NO_VARIADICS
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001612
1613template <class _Tp, class _Hash, class _Equal, class _Alloc>
1614template <class ..._Args>
1615typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1616__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args)
1617{
1618 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00001619 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001620 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001621 __h.get_deleter().__value_constructed = true;
1622 __h->__hash_ = hash_function()(__h->__value_);
1623 __h->__next_ = nullptr;
1624 return __h;
1625}
1626
Howard Hinnant73d21a42010-09-04 23:28:19 +00001627#endif // _LIBCPP_HAS_NO_VARIADICS
1628
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001629template <class _Tp, class _Hash, class _Equal, class _Alloc>
1630typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1631__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(value_type&& __v,
1632 size_t __hash)
1633{
1634 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00001635 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001636 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::move(__v));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001637 __h.get_deleter().__value_constructed = true;
1638 __h->__hash_ = __hash;
1639 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00001640 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001641}
1642
Howard Hinnant73d21a42010-09-04 23:28:19 +00001643#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001644
1645template <class _Tp, class _Hash, class _Equal, class _Alloc>
1646typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1647__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v)
1648{
1649 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00001650 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001651 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001652 __h.get_deleter().__value_constructed = true;
1653 __h->__hash_ = hash_function()(__h->__value_);
1654 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00001655 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001656}
1657
Howard Hinnant73d21a42010-09-04 23:28:19 +00001658#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001659
1660template <class _Tp, class _Hash, class _Equal, class _Alloc>
1661typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
1662__hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v,
1663 size_t __hash)
1664{
1665 __node_allocator& __na = __node_alloc();
Howard Hinnant99968442011-11-29 18:15:50 +00001666 __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na));
Howard Hinnant0949eed2011-06-30 21:18:19 +00001667 __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001668 __h.get_deleter().__value_constructed = true;
1669 __h->__hash_ = __hash;
1670 __h->__next_ = nullptr;
Howard Hinnant0949eed2011-06-30 21:18:19 +00001671 return _VSTD::move(__h);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001672}
1673
1674template <class _Tp, class _Hash, class _Equal, class _Alloc>
1675typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1676__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p)
1677{
1678 __node_pointer __np = const_cast<__node_pointer>(__p.__node_);
1679 iterator __r(__np);
1680 ++__r;
1681 remove(__p);
1682 return __r;
1683}
1684
1685template <class _Tp, class _Hash, class _Equal, class _Alloc>
1686typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator
1687__hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first,
1688 const_iterator __last)
1689{
1690 for (const_iterator __p = __first; __first != __last; __p = __first)
1691 {
1692 ++__first;
1693 erase(__p);
1694 }
1695 __node_pointer __np = const_cast<__node_pointer>(__last.__node_);
1696 return iterator (__np);
1697}
1698
1699template <class _Tp, class _Hash, class _Equal, class _Alloc>
1700template <class _Key>
1701typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1702__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k)
1703{
1704 iterator __i = find(__k);
1705 if (__i == end())
1706 return 0;
1707 erase(__i);
1708 return 1;
1709}
1710
1711template <class _Tp, class _Hash, class _Equal, class _Alloc>
1712template <class _Key>
1713typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1714__hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k)
1715{
1716 size_type __r = 0;
1717 iterator __i = find(__k);
1718 if (__i != end())
1719 {
1720 iterator __e = end();
1721 do
1722 {
1723 erase(__i++);
1724 ++__r;
1725 } while (__i != __e && key_eq()(*__i, __k));
1726 }
1727 return __r;
1728}
1729
1730template <class _Tp, class _Hash, class _Equal, class _Alloc>
1731typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001732__hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001733{
1734 // current node
1735 __node_pointer __cn = const_cast<__node_pointer>(__p.__node_);
1736 size_type __bc = bucket_count();
1737 size_t __chash = __cn->__hash_ % __bc;
1738 // find previous node
1739 __node_pointer __pn = __bucket_list_[__chash];
1740 for (; __pn->__next_ != __cn; __pn = __pn->__next_)
1741 ;
1742 // Fix up __bucket_list_
1743 // if __pn is not in same bucket (before begin is not in same bucket) &&
1744 // if __cn->__next_ is not in same bucket (nullptr is not in same bucket)
Howard Hinnant0949eed2011-06-30 21:18:19 +00001745 if (__pn == _VSTD::addressof(__p1_.first()) || __pn->__hash_ % __bc != __chash)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001746 {
1747 if (__cn->__next_ == nullptr || __cn->__next_->__hash_ % __bc != __chash)
1748 __bucket_list_[__chash] = nullptr;
1749 }
1750 // if __cn->__next_ is not in same bucket (nullptr is in same bucket)
1751 if (__cn->__next_ != nullptr)
1752 {
1753 size_t __nhash = __cn->__next_->__hash_ % __bc;
1754 if (__nhash != __chash)
1755 __bucket_list_[__nhash] = __pn;
1756 }
1757 // remove __cn
1758 __pn->__next_ = __cn->__next_;
1759 __cn->__next_ = nullptr;
1760 --size();
Howard Hinnant99968442011-11-29 18:15:50 +00001761 return __node_holder(__cn, _Dp(__node_alloc(), true));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001762}
1763
1764template <class _Tp, class _Hash, class _Equal, class _Alloc>
1765template <class _Key>
Howard Hinnant99acc502010-09-21 17:32:39 +00001766inline _LIBCPP_INLINE_VISIBILITY
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001767typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1768__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const
1769{
1770 return static_cast<size_type>(find(__k) != end());
1771}
1772
1773template <class _Tp, class _Hash, class _Equal, class _Alloc>
1774template <class _Key>
1775typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1776__hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const
1777{
1778 size_type __r = 0;
1779 const_iterator __i = find(__k);
1780 if (__i != end())
1781 {
1782 const_iterator __e = end();
1783 do
1784 {
1785 ++__i;
1786 ++__r;
1787 } while (__i != __e && key_eq()(*__i, __k));
1788 }
1789 return __r;
1790}
1791
1792template <class _Tp, class _Hash, class _Equal, class _Alloc>
1793template <class _Key>
1794pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
1795 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1796__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
1797 const _Key& __k)
1798{
1799 iterator __i = find(__k);
1800 iterator __j = __i;
1801 if (__i != end())
1802 ++__j;
1803 return pair<iterator, iterator>(__i, __j);
1804}
1805
1806template <class _Tp, class _Hash, class _Equal, class _Alloc>
1807template <class _Key>
1808pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
1809 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1810__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique(
1811 const _Key& __k) const
1812{
1813 const_iterator __i = find(__k);
1814 const_iterator __j = __i;
1815 if (__i != end())
1816 ++__j;
1817 return pair<const_iterator, const_iterator>(__i, __j);
1818}
1819
1820template <class _Tp, class _Hash, class _Equal, class _Alloc>
1821template <class _Key>
1822pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator,
1823 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator>
1824__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
1825 const _Key& __k)
1826{
1827 iterator __i = find(__k);
1828 iterator __j = __i;
1829 if (__i != end())
1830 {
1831 iterator __e = end();
1832 do
1833 {
1834 ++__j;
1835 } while (__j != __e && key_eq()(*__j, __k));
1836 }
1837 return pair<iterator, iterator>(__i, __j);
1838}
1839
1840template <class _Tp, class _Hash, class _Equal, class _Alloc>
1841template <class _Key>
1842pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator,
1843 typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator>
1844__hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi(
1845 const _Key& __k) const
1846{
1847 const_iterator __i = find(__k);
1848 const_iterator __j = __i;
1849 if (__i != end())
1850 {
1851 const_iterator __e = end();
1852 do
1853 {
1854 ++__j;
1855 } while (__j != __e && key_eq()(*__j, __k));
1856 }
1857 return pair<const_iterator, const_iterator>(__i, __j);
1858}
1859
1860template <class _Tp, class _Hash, class _Equal, class _Alloc>
1861void
1862__hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u)
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001863 _NOEXCEPT_(
1864 (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value ||
1865 __is_nothrow_swappable<__pointer_allocator>::value) &&
1866 (!__node_traits::propagate_on_container_swap::value ||
1867 __is_nothrow_swappable<__node_allocator>::value) &&
1868 __is_nothrow_swappable<hasher>::value &&
1869 __is_nothrow_swappable<key_equal>::value)
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001870{
1871 {
1872 __node_pointer_pointer __npp = __bucket_list_.release();
1873 __bucket_list_.reset(__u.__bucket_list_.release());
1874 __u.__bucket_list_.reset(__npp);
1875 }
Howard Hinnant0949eed2011-06-30 21:18:19 +00001876 _VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size());
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001877 __swap_alloc(__bucket_list_.get_deleter().__alloc(),
1878 __u.__bucket_list_.get_deleter().__alloc());
1879 __swap_alloc(__node_alloc(), __u.__node_alloc());
Howard Hinnant0949eed2011-06-30 21:18:19 +00001880 _VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_);
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001881 __p2_.swap(__u.__p2_);
1882 __p3_.swap(__u.__p3_);
1883 if (size() > 0)
1884 __bucket_list_[__p1_.first().__next_->__hash_ % bucket_count()] =
Howard Hinnant0949eed2011-06-30 21:18:19 +00001885 static_cast<__node_pointer>(_VSTD::addressof(__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001886 if (__u.size() > 0)
1887 __u.__bucket_list_[__u.__p1_.first().__next_->__hash_ % __u.bucket_count()] =
Howard Hinnant0949eed2011-06-30 21:18:19 +00001888 static_cast<__node_pointer>(_VSTD::addressof(__u.__p1_.first()));
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001889}
1890
1891template <class _Tp, class _Hash, class _Equal, class _Alloc>
1892typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type
1893__hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const
1894{
1895 __node_const_pointer __np = __bucket_list_[__n];
1896 size_type __bc = bucket_count();
1897 size_type __r = 0;
1898 if (__np != nullptr)
1899 {
1900 for (__np = __np->__next_; __np != nullptr &&
1901 __np->__hash_ % __bc == __n;
1902 __np = __np->__next_, ++__r)
1903 ;
1904 }
1905 return __r;
1906}
1907
Howard Hinnant5f2f14c2011-06-04 18:54:24 +00001908template <class _Tp, class _Hash, class _Equal, class _Alloc>
1909inline _LIBCPP_INLINE_VISIBILITY
1910void
1911swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x,
1912 __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y)
1913 _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y)))
1914{
1915 __x.swap(__y);
1916}
1917
Howard Hinnantbc8d3f92010-05-11 19:42:16 +00001918_LIBCPP_END_NAMESPACE_STD
1919
1920#endif // _LIBCPP__HASH_TABLE