root / lab4 / .minix-src / include / c++ / __hash_table
History | View | Annotate | Download (83.1 KB)
1 | 13 | up20180614 | // -*- C++ -*- |
---|---|---|---|
2 | //===----------------------------------------------------------------------===// |
||
3 | // |
||
4 | // The LLVM Compiler Infrastructure |
||
5 | // |
||
6 | // This file is dual licensed under the MIT and the University of Illinois Open |
||
7 | // Source Licenses. See LICENSE.TXT for details. |
||
8 | // |
||
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 | #include <__undef_min_max> |
||
22 | #include <__undef___deallocate> |
||
23 | |||
24 | #include <__debug> |
||
25 | |||
26 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
||
27 | #pragma GCC system_header |
||
28 | #endif |
||
29 | |||
30 | _LIBCPP_BEGIN_NAMESPACE_STD |
||
31 | |||
32 | _LIBCPP_FUNC_VIS |
||
33 | size_t __next_prime(size_t __n); |
||
34 | |||
35 | template <class _NodePtr> |
||
36 | struct __hash_node_base |
||
37 | { |
||
38 | typedef __hash_node_base __first_node; |
||
39 | |||
40 | _NodePtr __next_; |
||
41 | |||
42 | _LIBCPP_INLINE_VISIBILITY __hash_node_base() _NOEXCEPT : __next_(nullptr) {} |
||
43 | }; |
||
44 | |||
45 | template <class _Tp, class _VoidPtr> |
||
46 | struct __hash_node |
||
47 | : public __hash_node_base |
||
48 | < |
||
49 | typename pointer_traits<_VoidPtr>::template |
||
50 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
51 | rebind<__hash_node<_Tp, _VoidPtr> > |
||
52 | #else |
||
53 | rebind<__hash_node<_Tp, _VoidPtr> >::other |
||
54 | #endif |
||
55 | > |
||
56 | { |
||
57 | typedef _Tp value_type; |
||
58 | |||
59 | size_t __hash_; |
||
60 | value_type __value_; |
||
61 | }; |
||
62 | |||
63 | inline _LIBCPP_INLINE_VISIBILITY |
||
64 | bool |
||
65 | __is_hash_power2(size_t __bc) |
||
66 | { |
||
67 | return __bc > 2 && !(__bc & (__bc - 1)); |
||
68 | } |
||
69 | |||
70 | inline _LIBCPP_INLINE_VISIBILITY |
||
71 | size_t |
||
72 | __constrain_hash(size_t __h, size_t __bc) |
||
73 | { |
||
74 | return !(__bc & (__bc - 1)) ? __h & (__bc - 1) : __h % __bc; |
||
75 | } |
||
76 | |||
77 | inline _LIBCPP_INLINE_VISIBILITY |
||
78 | size_t |
||
79 | __next_hash_pow2(size_t __n) |
||
80 | { |
||
81 | return size_t(1) << (std::numeric_limits<size_t>::digits - __clz(__n-1)); |
||
82 | } |
||
83 | |||
84 | template <class _Tp, class _Hash, class _Equal, class _Alloc> class __hash_table; |
||
85 | template <class _ConstNodePtr> class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator; |
||
86 | template <class _HashIterator> class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator; |
||
87 | template <class _HashIterator> class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator; |
||
88 | |||
89 | template <class _NodePtr> |
||
90 | class _LIBCPP_TYPE_VIS_ONLY __hash_iterator |
||
91 | { |
||
92 | typedef _NodePtr __node_pointer; |
||
93 | |||
94 | __node_pointer __node_; |
||
95 | |||
96 | public: |
||
97 | typedef forward_iterator_tag iterator_category; |
||
98 | typedef typename pointer_traits<__node_pointer>::element_type::value_type value_type; |
||
99 | typedef typename pointer_traits<__node_pointer>::difference_type difference_type; |
||
100 | typedef value_type& reference; |
||
101 | typedef typename pointer_traits<__node_pointer>::template |
||
102 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
103 | rebind<value_type> |
||
104 | #else |
||
105 | rebind<value_type>::other |
||
106 | #endif |
||
107 | pointer; |
||
108 | |||
109 | _LIBCPP_INLINE_VISIBILITY __hash_iterator() _NOEXCEPT |
||
110 | #if _LIBCPP_STD_VER > 11 |
||
111 | : __node_(nullptr) |
||
112 | #endif |
||
113 | { |
||
114 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
115 | __get_db()->__insert_i(this); |
||
116 | #endif |
||
117 | } |
||
118 | |||
119 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
120 | |||
121 | _LIBCPP_INLINE_VISIBILITY |
||
122 | __hash_iterator(const __hash_iterator& __i) |
||
123 | : __node_(__i.__node_) |
||
124 | { |
||
125 | __get_db()->__iterator_copy(this, &__i); |
||
126 | } |
||
127 | |||
128 | _LIBCPP_INLINE_VISIBILITY |
||
129 | ~__hash_iterator() |
||
130 | { |
||
131 | __get_db()->__erase_i(this); |
||
132 | } |
||
133 | |||
134 | _LIBCPP_INLINE_VISIBILITY |
||
135 | __hash_iterator& operator=(const __hash_iterator& __i) |
||
136 | { |
||
137 | if (this != &__i) |
||
138 | { |
||
139 | __get_db()->__iterator_copy(this, &__i); |
||
140 | __node_ = __i.__node_; |
||
141 | } |
||
142 | return *this; |
||
143 | } |
||
144 | |||
145 | #endif // _LIBCPP_DEBUG_LEVEL >= 2 |
||
146 | |||
147 | _LIBCPP_INLINE_VISIBILITY |
||
148 | reference operator*() const |
||
149 | { |
||
150 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
151 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), |
||
152 | "Attempted to dereference a non-dereferenceable unordered container iterator"); |
||
153 | #endif |
||
154 | return __node_->__value_; |
||
155 | } |
||
156 | _LIBCPP_INLINE_VISIBILITY |
||
157 | pointer operator->() const |
||
158 | { |
||
159 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
160 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), |
||
161 | "Attempted to dereference a non-dereferenceable unordered container iterator"); |
||
162 | #endif |
||
163 | return pointer_traits<pointer>::pointer_to(__node_->__value_); |
||
164 | } |
||
165 | |||
166 | _LIBCPP_INLINE_VISIBILITY |
||
167 | __hash_iterator& operator++() |
||
168 | { |
||
169 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
170 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), |
||
171 | "Attempted to increment non-incrementable unordered container iterator"); |
||
172 | #endif |
||
173 | __node_ = __node_->__next_; |
||
174 | return *this; |
||
175 | } |
||
176 | |||
177 | _LIBCPP_INLINE_VISIBILITY |
||
178 | __hash_iterator operator++(int) |
||
179 | { |
||
180 | __hash_iterator __t(*this); |
||
181 | ++(*this); |
||
182 | return __t; |
||
183 | } |
||
184 | |||
185 | friend _LIBCPP_INLINE_VISIBILITY |
||
186 | bool operator==(const __hash_iterator& __x, const __hash_iterator& __y) |
||
187 | { |
||
188 | return __x.__node_ == __y.__node_; |
||
189 | } |
||
190 | friend _LIBCPP_INLINE_VISIBILITY |
||
191 | bool operator!=(const __hash_iterator& __x, const __hash_iterator& __y) |
||
192 | {return !(__x == __y);} |
||
193 | |||
194 | private: |
||
195 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
196 | _LIBCPP_INLINE_VISIBILITY |
||
197 | __hash_iterator(__node_pointer __node, const void* __c) _NOEXCEPT |
||
198 | : __node_(__node) |
||
199 | { |
||
200 | __get_db()->__insert_ic(this, __c); |
||
201 | } |
||
202 | #else |
||
203 | _LIBCPP_INLINE_VISIBILITY |
||
204 | __hash_iterator(__node_pointer __node) _NOEXCEPT |
||
205 | : __node_(__node) |
||
206 | {} |
||
207 | #endif |
||
208 | |||
209 | template <class, class, class, class> friend class __hash_table; |
||
210 | template <class> friend class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator; |
||
211 | template <class> friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator; |
||
212 | template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY unordered_map; |
||
213 | template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap; |
||
214 | }; |
||
215 | |||
216 | template <class _ConstNodePtr> |
||
217 | class _LIBCPP_TYPE_VIS_ONLY __hash_const_iterator |
||
218 | { |
||
219 | typedef _ConstNodePtr __node_pointer; |
||
220 | |||
221 | __node_pointer __node_; |
||
222 | |||
223 | typedef typename remove_const< |
||
224 | typename pointer_traits<__node_pointer>::element_type |
||
225 | >::type __node; |
||
226 | |||
227 | public: |
||
228 | typedef forward_iterator_tag iterator_category; |
||
229 | typedef typename __node::value_type value_type; |
||
230 | typedef typename pointer_traits<__node_pointer>::difference_type difference_type; |
||
231 | typedef const value_type& reference; |
||
232 | typedef typename pointer_traits<__node_pointer>::template |
||
233 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
234 | rebind<const value_type> |
||
235 | #else |
||
236 | rebind<const value_type>::other |
||
237 | #endif |
||
238 | pointer; |
||
239 | typedef typename pointer_traits<__node_pointer>::template |
||
240 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
241 | rebind<__node> |
||
242 | #else |
||
243 | rebind<__node>::other |
||
244 | #endif |
||
245 | __non_const_node_pointer; |
||
246 | typedef __hash_iterator<__non_const_node_pointer> __non_const_iterator; |
||
247 | |||
248 | _LIBCPP_INLINE_VISIBILITY __hash_const_iterator() _NOEXCEPT |
||
249 | #if _LIBCPP_STD_VER > 11 |
||
250 | : __node_(nullptr) |
||
251 | #endif |
||
252 | { |
||
253 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
254 | __get_db()->__insert_i(this); |
||
255 | #endif |
||
256 | } |
||
257 | _LIBCPP_INLINE_VISIBILITY |
||
258 | __hash_const_iterator(const __non_const_iterator& __x) _NOEXCEPT |
||
259 | : __node_(__x.__node_) |
||
260 | { |
||
261 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
262 | __get_db()->__iterator_copy(this, &__x); |
||
263 | #endif |
||
264 | } |
||
265 | |||
266 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
267 | |||
268 | _LIBCPP_INLINE_VISIBILITY |
||
269 | __hash_const_iterator(const __hash_const_iterator& __i) |
||
270 | : __node_(__i.__node_) |
||
271 | { |
||
272 | __get_db()->__iterator_copy(this, &__i); |
||
273 | } |
||
274 | |||
275 | _LIBCPP_INLINE_VISIBILITY |
||
276 | ~__hash_const_iterator() |
||
277 | { |
||
278 | __get_db()->__erase_i(this); |
||
279 | } |
||
280 | |||
281 | _LIBCPP_INLINE_VISIBILITY |
||
282 | __hash_const_iterator& operator=(const __hash_const_iterator& __i) |
||
283 | { |
||
284 | if (this != &__i) |
||
285 | { |
||
286 | __get_db()->__iterator_copy(this, &__i); |
||
287 | __node_ = __i.__node_; |
||
288 | } |
||
289 | return *this; |
||
290 | } |
||
291 | |||
292 | #endif // _LIBCPP_DEBUG_LEVEL >= 2 |
||
293 | |||
294 | _LIBCPP_INLINE_VISIBILITY |
||
295 | reference operator*() const |
||
296 | { |
||
297 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
298 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), |
||
299 | "Attempted to dereference a non-dereferenceable unordered container const_iterator"); |
||
300 | #endif |
||
301 | return __node_->__value_; |
||
302 | } |
||
303 | _LIBCPP_INLINE_VISIBILITY |
||
304 | pointer operator->() const |
||
305 | { |
||
306 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
307 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), |
||
308 | "Attempted to dereference a non-dereferenceable unordered container const_iterator"); |
||
309 | #endif |
||
310 | return pointer_traits<pointer>::pointer_to(__node_->__value_); |
||
311 | } |
||
312 | |||
313 | _LIBCPP_INLINE_VISIBILITY |
||
314 | __hash_const_iterator& operator++() |
||
315 | { |
||
316 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
317 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), |
||
318 | "Attempted to increment non-incrementable unordered container const_iterator"); |
||
319 | #endif |
||
320 | __node_ = __node_->__next_; |
||
321 | return *this; |
||
322 | } |
||
323 | |||
324 | _LIBCPP_INLINE_VISIBILITY |
||
325 | __hash_const_iterator operator++(int) |
||
326 | { |
||
327 | __hash_const_iterator __t(*this); |
||
328 | ++(*this); |
||
329 | return __t; |
||
330 | } |
||
331 | |||
332 | friend _LIBCPP_INLINE_VISIBILITY |
||
333 | bool operator==(const __hash_const_iterator& __x, const __hash_const_iterator& __y) |
||
334 | { |
||
335 | return __x.__node_ == __y.__node_; |
||
336 | } |
||
337 | friend _LIBCPP_INLINE_VISIBILITY |
||
338 | bool operator!=(const __hash_const_iterator& __x, const __hash_const_iterator& __y) |
||
339 | {return !(__x == __y);} |
||
340 | |||
341 | private: |
||
342 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
343 | _LIBCPP_INLINE_VISIBILITY |
||
344 | __hash_const_iterator(__node_pointer __node, const void* __c) _NOEXCEPT |
||
345 | : __node_(__node) |
||
346 | { |
||
347 | __get_db()->__insert_ic(this, __c); |
||
348 | } |
||
349 | #else |
||
350 | _LIBCPP_INLINE_VISIBILITY |
||
351 | __hash_const_iterator(__node_pointer __node) _NOEXCEPT |
||
352 | : __node_(__node) |
||
353 | {} |
||
354 | #endif |
||
355 | |||
356 | template <class, class, class, class> friend class __hash_table; |
||
357 | template <class> friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator; |
||
358 | template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY unordered_map; |
||
359 | template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap; |
||
360 | }; |
||
361 | |||
362 | template <class _ConstNodePtr> class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator; |
||
363 | |||
364 | template <class _NodePtr> |
||
365 | class _LIBCPP_TYPE_VIS_ONLY __hash_local_iterator |
||
366 | { |
||
367 | typedef _NodePtr __node_pointer; |
||
368 | |||
369 | __node_pointer __node_; |
||
370 | size_t __bucket_; |
||
371 | size_t __bucket_count_; |
||
372 | |||
373 | typedef pointer_traits<__node_pointer> __pointer_traits; |
||
374 | public: |
||
375 | typedef forward_iterator_tag iterator_category; |
||
376 | typedef typename __pointer_traits::element_type::value_type value_type; |
||
377 | typedef typename __pointer_traits::difference_type difference_type; |
||
378 | typedef value_type& reference; |
||
379 | typedef typename __pointer_traits::template |
||
380 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
381 | rebind<value_type> |
||
382 | #else |
||
383 | rebind<value_type>::other |
||
384 | #endif |
||
385 | pointer; |
||
386 | |||
387 | _LIBCPP_INLINE_VISIBILITY __hash_local_iterator() _NOEXCEPT |
||
388 | { |
||
389 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
390 | __get_db()->__insert_i(this); |
||
391 | #endif |
||
392 | } |
||
393 | |||
394 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
395 | |||
396 | _LIBCPP_INLINE_VISIBILITY |
||
397 | __hash_local_iterator(const __hash_local_iterator& __i) |
||
398 | : __node_(__i.__node_), |
||
399 | __bucket_(__i.__bucket_), |
||
400 | __bucket_count_(__i.__bucket_count_) |
||
401 | { |
||
402 | __get_db()->__iterator_copy(this, &__i); |
||
403 | } |
||
404 | |||
405 | _LIBCPP_INLINE_VISIBILITY |
||
406 | ~__hash_local_iterator() |
||
407 | { |
||
408 | __get_db()->__erase_i(this); |
||
409 | } |
||
410 | |||
411 | _LIBCPP_INLINE_VISIBILITY |
||
412 | __hash_local_iterator& operator=(const __hash_local_iterator& __i) |
||
413 | { |
||
414 | if (this != &__i) |
||
415 | { |
||
416 | __get_db()->__iterator_copy(this, &__i); |
||
417 | __node_ = __i.__node_; |
||
418 | __bucket_ = __i.__bucket_; |
||
419 | __bucket_count_ = __i.__bucket_count_; |
||
420 | } |
||
421 | return *this; |
||
422 | } |
||
423 | |||
424 | #endif // _LIBCPP_DEBUG_LEVEL >= 2 |
||
425 | |||
426 | _LIBCPP_INLINE_VISIBILITY |
||
427 | reference operator*() const |
||
428 | { |
||
429 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
430 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), |
||
431 | "Attempted to dereference a non-dereferenceable unordered container local_iterator"); |
||
432 | #endif |
||
433 | return __node_->__value_; |
||
434 | } |
||
435 | _LIBCPP_INLINE_VISIBILITY |
||
436 | pointer operator->() const |
||
437 | { |
||
438 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
439 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), |
||
440 | "Attempted to dereference a non-dereferenceable unordered container local_iterator"); |
||
441 | #endif |
||
442 | return pointer_traits<pointer>::pointer_to(__node_->__value_); |
||
443 | } |
||
444 | |||
445 | _LIBCPP_INLINE_VISIBILITY |
||
446 | __hash_local_iterator& operator++() |
||
447 | { |
||
448 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
449 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), |
||
450 | "Attempted to increment non-incrementable unordered container local_iterator"); |
||
451 | #endif |
||
452 | __node_ = __node_->__next_; |
||
453 | if (__node_ != nullptr && __constrain_hash(__node_->__hash_, __bucket_count_) != __bucket_) |
||
454 | __node_ = nullptr; |
||
455 | return *this; |
||
456 | } |
||
457 | |||
458 | _LIBCPP_INLINE_VISIBILITY |
||
459 | __hash_local_iterator operator++(int) |
||
460 | { |
||
461 | __hash_local_iterator __t(*this); |
||
462 | ++(*this); |
||
463 | return __t; |
||
464 | } |
||
465 | |||
466 | friend _LIBCPP_INLINE_VISIBILITY |
||
467 | bool operator==(const __hash_local_iterator& __x, const __hash_local_iterator& __y) |
||
468 | { |
||
469 | return __x.__node_ == __y.__node_; |
||
470 | } |
||
471 | friend _LIBCPP_INLINE_VISIBILITY |
||
472 | bool operator!=(const __hash_local_iterator& __x, const __hash_local_iterator& __y) |
||
473 | {return !(__x == __y);} |
||
474 | |||
475 | private: |
||
476 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
477 | _LIBCPP_INLINE_VISIBILITY |
||
478 | __hash_local_iterator(__node_pointer __node, size_t __bucket, |
||
479 | size_t __bucket_count, const void* __c) _NOEXCEPT |
||
480 | : __node_(__node), |
||
481 | __bucket_(__bucket), |
||
482 | __bucket_count_(__bucket_count) |
||
483 | { |
||
484 | __get_db()->__insert_ic(this, __c); |
||
485 | if (__node_ != nullptr) |
||
486 | __node_ = __node_->__next_; |
||
487 | } |
||
488 | #else |
||
489 | _LIBCPP_INLINE_VISIBILITY |
||
490 | __hash_local_iterator(__node_pointer __node, size_t __bucket, |
||
491 | size_t __bucket_count) _NOEXCEPT |
||
492 | : __node_(__node), |
||
493 | __bucket_(__bucket), |
||
494 | __bucket_count_(__bucket_count) |
||
495 | { |
||
496 | if (__node_ != nullptr) |
||
497 | __node_ = __node_->__next_; |
||
498 | } |
||
499 | #endif |
||
500 | template <class, class, class, class> friend class __hash_table; |
||
501 | template <class> friend class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator; |
||
502 | template <class> friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_iterator; |
||
503 | }; |
||
504 | |||
505 | template <class _ConstNodePtr> |
||
506 | class _LIBCPP_TYPE_VIS_ONLY __hash_const_local_iterator |
||
507 | { |
||
508 | typedef _ConstNodePtr __node_pointer; |
||
509 | |||
510 | __node_pointer __node_; |
||
511 | size_t __bucket_; |
||
512 | size_t __bucket_count_; |
||
513 | |||
514 | typedef pointer_traits<__node_pointer> __pointer_traits; |
||
515 | typedef typename __pointer_traits::element_type __node; |
||
516 | typedef typename remove_const<__node>::type __non_const_node; |
||
517 | typedef typename pointer_traits<__node_pointer>::template |
||
518 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
519 | rebind<__non_const_node> |
||
520 | #else |
||
521 | rebind<__non_const_node>::other |
||
522 | #endif |
||
523 | __non_const_node_pointer; |
||
524 | typedef __hash_local_iterator<__non_const_node_pointer> |
||
525 | __non_const_iterator; |
||
526 | public: |
||
527 | typedef forward_iterator_tag iterator_category; |
||
528 | typedef typename remove_const< |
||
529 | typename __pointer_traits::element_type::value_type |
||
530 | >::type value_type; |
||
531 | typedef typename __pointer_traits::difference_type difference_type; |
||
532 | typedef const value_type& reference; |
||
533 | typedef typename __pointer_traits::template |
||
534 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
535 | rebind<const value_type> |
||
536 | #else |
||
537 | rebind<const value_type>::other |
||
538 | #endif |
||
539 | pointer; |
||
540 | |||
541 | _LIBCPP_INLINE_VISIBILITY __hash_const_local_iterator() _NOEXCEPT |
||
542 | { |
||
543 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
544 | __get_db()->__insert_i(this); |
||
545 | #endif |
||
546 | } |
||
547 | |||
548 | _LIBCPP_INLINE_VISIBILITY |
||
549 | __hash_const_local_iterator(const __non_const_iterator& __x) _NOEXCEPT |
||
550 | : __node_(__x.__node_), |
||
551 | __bucket_(__x.__bucket_), |
||
552 | __bucket_count_(__x.__bucket_count_) |
||
553 | { |
||
554 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
555 | __get_db()->__iterator_copy(this, &__x); |
||
556 | #endif |
||
557 | } |
||
558 | |||
559 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
560 | |||
561 | _LIBCPP_INLINE_VISIBILITY |
||
562 | __hash_const_local_iterator(const __hash_const_local_iterator& __i) |
||
563 | : __node_(__i.__node_), |
||
564 | __bucket_(__i.__bucket_), |
||
565 | __bucket_count_(__i.__bucket_count_) |
||
566 | { |
||
567 | __get_db()->__iterator_copy(this, &__i); |
||
568 | } |
||
569 | |||
570 | _LIBCPP_INLINE_VISIBILITY |
||
571 | ~__hash_const_local_iterator() |
||
572 | { |
||
573 | __get_db()->__erase_i(this); |
||
574 | } |
||
575 | |||
576 | _LIBCPP_INLINE_VISIBILITY |
||
577 | __hash_const_local_iterator& operator=(const __hash_const_local_iterator& __i) |
||
578 | { |
||
579 | if (this != &__i) |
||
580 | { |
||
581 | __get_db()->__iterator_copy(this, &__i); |
||
582 | __node_ = __i.__node_; |
||
583 | __bucket_ = __i.__bucket_; |
||
584 | __bucket_count_ = __i.__bucket_count_; |
||
585 | } |
||
586 | return *this; |
||
587 | } |
||
588 | |||
589 | #endif // _LIBCPP_DEBUG_LEVEL >= 2 |
||
590 | |||
591 | _LIBCPP_INLINE_VISIBILITY |
||
592 | reference operator*() const |
||
593 | { |
||
594 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
595 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), |
||
596 | "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); |
||
597 | #endif |
||
598 | return __node_->__value_; |
||
599 | } |
||
600 | _LIBCPP_INLINE_VISIBILITY |
||
601 | pointer operator->() const |
||
602 | { |
||
603 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
604 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), |
||
605 | "Attempted to dereference a non-dereferenceable unordered container const_local_iterator"); |
||
606 | #endif |
||
607 | return pointer_traits<pointer>::pointer_to(__node_->__value_); |
||
608 | } |
||
609 | |||
610 | _LIBCPP_INLINE_VISIBILITY |
||
611 | __hash_const_local_iterator& operator++() |
||
612 | { |
||
613 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
614 | _LIBCPP_ASSERT(__get_const_db()->__dereferenceable(this), |
||
615 | "Attempted to increment non-incrementable unordered container const_local_iterator"); |
||
616 | #endif |
||
617 | __node_ = __node_->__next_; |
||
618 | if (__node_ != nullptr && __constrain_hash(__node_->__hash_, __bucket_count_) != __bucket_) |
||
619 | __node_ = nullptr; |
||
620 | return *this; |
||
621 | } |
||
622 | |||
623 | _LIBCPP_INLINE_VISIBILITY |
||
624 | __hash_const_local_iterator operator++(int) |
||
625 | { |
||
626 | __hash_const_local_iterator __t(*this); |
||
627 | ++(*this); |
||
628 | return __t; |
||
629 | } |
||
630 | |||
631 | friend _LIBCPP_INLINE_VISIBILITY |
||
632 | bool operator==(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y) |
||
633 | { |
||
634 | return __x.__node_ == __y.__node_; |
||
635 | } |
||
636 | friend _LIBCPP_INLINE_VISIBILITY |
||
637 | bool operator!=(const __hash_const_local_iterator& __x, const __hash_const_local_iterator& __y) |
||
638 | {return !(__x == __y);} |
||
639 | |||
640 | private: |
||
641 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
642 | _LIBCPP_INLINE_VISIBILITY |
||
643 | __hash_const_local_iterator(__node_pointer __node, size_t __bucket, |
||
644 | size_t __bucket_count, const void* __c) _NOEXCEPT |
||
645 | : __node_(__node), |
||
646 | __bucket_(__bucket), |
||
647 | __bucket_count_(__bucket_count) |
||
648 | { |
||
649 | __get_db()->__insert_ic(this, __c); |
||
650 | if (__node_ != nullptr) |
||
651 | __node_ = __node_->__next_; |
||
652 | } |
||
653 | #else |
||
654 | _LIBCPP_INLINE_VISIBILITY |
||
655 | __hash_const_local_iterator(__node_pointer __node, size_t __bucket, |
||
656 | size_t __bucket_count) _NOEXCEPT |
||
657 | : __node_(__node), |
||
658 | __bucket_(__bucket), |
||
659 | __bucket_count_(__bucket_count) |
||
660 | { |
||
661 | if (__node_ != nullptr) |
||
662 | __node_ = __node_->__next_; |
||
663 | } |
||
664 | #endif |
||
665 | template <class, class, class, class> friend class __hash_table; |
||
666 | template <class> friend class _LIBCPP_TYPE_VIS_ONLY __hash_map_const_iterator; |
||
667 | }; |
||
668 | |||
669 | template <class _Alloc> |
||
670 | class __bucket_list_deallocator |
||
671 | { |
||
672 | typedef _Alloc allocator_type; |
||
673 | typedef allocator_traits<allocator_type> __alloc_traits; |
||
674 | typedef typename __alloc_traits::size_type size_type; |
||
675 | |||
676 | __compressed_pair<size_type, allocator_type> __data_; |
||
677 | public: |
||
678 | typedef typename __alloc_traits::pointer pointer; |
||
679 | |||
680 | _LIBCPP_INLINE_VISIBILITY |
||
681 | __bucket_list_deallocator() |
||
682 | _NOEXCEPT_(is_nothrow_default_constructible<allocator_type>::value) |
||
683 | : __data_(0) {} |
||
684 | |||
685 | _LIBCPP_INLINE_VISIBILITY |
||
686 | __bucket_list_deallocator(const allocator_type& __a, size_type __size) |
||
687 | _NOEXCEPT_(is_nothrow_copy_constructible<allocator_type>::value) |
||
688 | : __data_(__size, __a) {} |
||
689 | |||
690 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
691 | |||
692 | _LIBCPP_INLINE_VISIBILITY |
||
693 | __bucket_list_deallocator(__bucket_list_deallocator&& __x) |
||
694 | _NOEXCEPT_(is_nothrow_move_constructible<allocator_type>::value) |
||
695 | : __data_(_VSTD::move(__x.__data_)) |
||
696 | { |
||
697 | __x.size() = 0; |
||
698 | } |
||
699 | |||
700 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
701 | |||
702 | _LIBCPP_INLINE_VISIBILITY |
||
703 | size_type& size() _NOEXCEPT {return __data_.first();} |
||
704 | _LIBCPP_INLINE_VISIBILITY |
||
705 | size_type size() const _NOEXCEPT {return __data_.first();} |
||
706 | |||
707 | _LIBCPP_INLINE_VISIBILITY |
||
708 | allocator_type& __alloc() _NOEXCEPT {return __data_.second();} |
||
709 | _LIBCPP_INLINE_VISIBILITY |
||
710 | const allocator_type& __alloc() const _NOEXCEPT {return __data_.second();} |
||
711 | |||
712 | _LIBCPP_INLINE_VISIBILITY |
||
713 | void operator()(pointer __p) _NOEXCEPT |
||
714 | { |
||
715 | __alloc_traits::deallocate(__alloc(), __p, size()); |
||
716 | } |
||
717 | }; |
||
718 | |||
719 | template <class _Alloc> class __hash_map_node_destructor; |
||
720 | |||
721 | template <class _Alloc> |
||
722 | class __hash_node_destructor |
||
723 | { |
||
724 | typedef _Alloc allocator_type; |
||
725 | typedef allocator_traits<allocator_type> __alloc_traits; |
||
726 | typedef typename __alloc_traits::value_type::value_type value_type; |
||
727 | public: |
||
728 | typedef typename __alloc_traits::pointer pointer; |
||
729 | private: |
||
730 | |||
731 | allocator_type& __na_; |
||
732 | |||
733 | __hash_node_destructor& operator=(const __hash_node_destructor&); |
||
734 | |||
735 | public: |
||
736 | bool __value_constructed; |
||
737 | |||
738 | _LIBCPP_INLINE_VISIBILITY |
||
739 | explicit __hash_node_destructor(allocator_type& __na, |
||
740 | bool __constructed = false) _NOEXCEPT |
||
741 | : __na_(__na), |
||
742 | __value_constructed(__constructed) |
||
743 | {} |
||
744 | |||
745 | _LIBCPP_INLINE_VISIBILITY |
||
746 | void operator()(pointer __p) _NOEXCEPT |
||
747 | { |
||
748 | if (__value_constructed) |
||
749 | __alloc_traits::destroy(__na_, _VSTD::addressof(__p->__value_)); |
||
750 | if (__p) |
||
751 | __alloc_traits::deallocate(__na_, __p, 1); |
||
752 | } |
||
753 | |||
754 | template <class> friend class __hash_map_node_destructor; |
||
755 | }; |
||
756 | |||
757 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
758 | class __hash_table |
||
759 | { |
||
760 | public: |
||
761 | typedef _Tp value_type; |
||
762 | typedef _Hash hasher; |
||
763 | typedef _Equal key_equal; |
||
764 | typedef _Alloc allocator_type; |
||
765 | |||
766 | private: |
||
767 | typedef allocator_traits<allocator_type> __alloc_traits; |
||
768 | public: |
||
769 | typedef value_type& reference; |
||
770 | typedef const value_type& const_reference; |
||
771 | typedef typename __alloc_traits::pointer pointer; |
||
772 | typedef typename __alloc_traits::const_pointer const_pointer; |
||
773 | typedef typename __alloc_traits::size_type size_type; |
||
774 | typedef typename __alloc_traits::difference_type difference_type; |
||
775 | public: |
||
776 | // Create __node |
||
777 | typedef __hash_node<value_type, typename __alloc_traits::void_pointer> __node; |
||
778 | typedef typename __rebind_alloc_helper<__alloc_traits, __node>::type __node_allocator; |
||
779 | typedef allocator_traits<__node_allocator> __node_traits; |
||
780 | typedef typename __node_traits::pointer __node_pointer; |
||
781 | typedef typename __node_traits::pointer __node_const_pointer; |
||
782 | typedef __hash_node_base<__node_pointer> __first_node; |
||
783 | typedef typename pointer_traits<__node_pointer>::template |
||
784 | #ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES |
||
785 | rebind<__first_node> |
||
786 | #else |
||
787 | rebind<__first_node>::other |
||
788 | #endif |
||
789 | __node_base_pointer; |
||
790 | |||
791 | private: |
||
792 | |||
793 | typedef typename __rebind_alloc_helper<__node_traits, __node_pointer>::type __pointer_allocator; |
||
794 | typedef __bucket_list_deallocator<__pointer_allocator> __bucket_list_deleter; |
||
795 | typedef unique_ptr<__node_pointer[], __bucket_list_deleter> __bucket_list; |
||
796 | typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits; |
||
797 | typedef typename __bucket_list_deleter::pointer __node_pointer_pointer; |
||
798 | |||
799 | // --- Member data begin --- |
||
800 | __bucket_list __bucket_list_; |
||
801 | __compressed_pair<__first_node, __node_allocator> __p1_; |
||
802 | __compressed_pair<size_type, hasher> __p2_; |
||
803 | __compressed_pair<float, key_equal> __p3_; |
||
804 | // --- Member data end --- |
||
805 | |||
806 | _LIBCPP_INLINE_VISIBILITY |
||
807 | size_type& size() _NOEXCEPT {return __p2_.first();} |
||
808 | public: |
||
809 | _LIBCPP_INLINE_VISIBILITY |
||
810 | size_type size() const _NOEXCEPT {return __p2_.first();} |
||
811 | |||
812 | _LIBCPP_INLINE_VISIBILITY |
||
813 | hasher& hash_function() _NOEXCEPT {return __p2_.second();} |
||
814 | _LIBCPP_INLINE_VISIBILITY |
||
815 | const hasher& hash_function() const _NOEXCEPT {return __p2_.second();} |
||
816 | |||
817 | _LIBCPP_INLINE_VISIBILITY |
||
818 | float& max_load_factor() _NOEXCEPT {return __p3_.first();} |
||
819 | _LIBCPP_INLINE_VISIBILITY |
||
820 | float max_load_factor() const _NOEXCEPT {return __p3_.first();} |
||
821 | |||
822 | _LIBCPP_INLINE_VISIBILITY |
||
823 | key_equal& key_eq() _NOEXCEPT {return __p3_.second();} |
||
824 | _LIBCPP_INLINE_VISIBILITY |
||
825 | const key_equal& key_eq() const _NOEXCEPT {return __p3_.second();} |
||
826 | |||
827 | _LIBCPP_INLINE_VISIBILITY |
||
828 | __node_allocator& __node_alloc() _NOEXCEPT {return __p1_.second();} |
||
829 | _LIBCPP_INLINE_VISIBILITY |
||
830 | const __node_allocator& __node_alloc() const _NOEXCEPT |
||
831 | {return __p1_.second();} |
||
832 | |||
833 | public: |
||
834 | typedef __hash_iterator<__node_pointer> iterator; |
||
835 | typedef __hash_const_iterator<__node_pointer> const_iterator; |
||
836 | typedef __hash_local_iterator<__node_pointer> local_iterator; |
||
837 | typedef __hash_const_local_iterator<__node_pointer> const_local_iterator; |
||
838 | |||
839 | __hash_table() |
||
840 | _NOEXCEPT_( |
||
841 | is_nothrow_default_constructible<__bucket_list>::value && |
||
842 | is_nothrow_default_constructible<__first_node>::value && |
||
843 | is_nothrow_default_constructible<__node_allocator>::value && |
||
844 | is_nothrow_default_constructible<hasher>::value && |
||
845 | is_nothrow_default_constructible<key_equal>::value); |
||
846 | __hash_table(const hasher& __hf, const key_equal& __eql); |
||
847 | __hash_table(const hasher& __hf, const key_equal& __eql, |
||
848 | const allocator_type& __a); |
||
849 | explicit __hash_table(const allocator_type& __a); |
||
850 | __hash_table(const __hash_table& __u); |
||
851 | __hash_table(const __hash_table& __u, const allocator_type& __a); |
||
852 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
853 | __hash_table(__hash_table&& __u) |
||
854 | _NOEXCEPT_( |
||
855 | is_nothrow_move_constructible<__bucket_list>::value && |
||
856 | is_nothrow_move_constructible<__first_node>::value && |
||
857 | is_nothrow_move_constructible<__node_allocator>::value && |
||
858 | is_nothrow_move_constructible<hasher>::value && |
||
859 | is_nothrow_move_constructible<key_equal>::value); |
||
860 | __hash_table(__hash_table&& __u, const allocator_type& __a); |
||
861 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
862 | ~__hash_table(); |
||
863 | |||
864 | __hash_table& operator=(const __hash_table& __u); |
||
865 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
866 | __hash_table& operator=(__hash_table&& __u) |
||
867 | _NOEXCEPT_( |
||
868 | __node_traits::propagate_on_container_move_assignment::value && |
||
869 | is_nothrow_move_assignable<__node_allocator>::value && |
||
870 | is_nothrow_move_assignable<hasher>::value && |
||
871 | is_nothrow_move_assignable<key_equal>::value); |
||
872 | #endif |
||
873 | template <class _InputIterator> |
||
874 | void __assign_unique(_InputIterator __first, _InputIterator __last); |
||
875 | template <class _InputIterator> |
||
876 | void __assign_multi(_InputIterator __first, _InputIterator __last); |
||
877 | |||
878 | _LIBCPP_INLINE_VISIBILITY |
||
879 | size_type max_size() const _NOEXCEPT |
||
880 | { |
||
881 | return allocator_traits<__pointer_allocator>::max_size( |
||
882 | __bucket_list_.get_deleter().__alloc()); |
||
883 | } |
||
884 | |||
885 | pair<iterator, bool> __node_insert_unique(__node_pointer __nd); |
||
886 | iterator __node_insert_multi(__node_pointer __nd); |
||
887 | iterator __node_insert_multi(const_iterator __p, |
||
888 | __node_pointer __nd); |
||
889 | |||
890 | #if !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) |
||
891 | template <class... _Args> |
||
892 | pair<iterator, bool> __emplace_unique(_Args&&... __args); |
||
893 | template <class... _Args> |
||
894 | iterator __emplace_multi(_Args&&... __args); |
||
895 | template <class... _Args> |
||
896 | iterator __emplace_hint_multi(const_iterator __p, _Args&&... __args); |
||
897 | #endif // !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) && !defined(_LIBCPP_HAS_NO_VARIADICS) |
||
898 | |||
899 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
900 | template <class _ValueTp> |
||
901 | _LIBCPP_INLINE_VISIBILITY |
||
902 | pair<iterator, bool> __insert_unique_value(_ValueTp&& __x); |
||
903 | #else |
||
904 | _LIBCPP_INLINE_VISIBILITY |
||
905 | pair<iterator, bool> __insert_unique_value(const value_type& __x); |
||
906 | #endif |
||
907 | |||
908 | pair<iterator, bool> __insert_unique(const value_type& __x); |
||
909 | |||
910 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
911 | pair<iterator, bool> __insert_unique(value_type&& __x); |
||
912 | template <class _Pp> |
||
913 | pair<iterator, bool> __insert_unique(_Pp&& __x); |
||
914 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
915 | |||
916 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
917 | template <class _Pp> |
||
918 | iterator __insert_multi(_Pp&& __x); |
||
919 | template <class _Pp> |
||
920 | iterator __insert_multi(const_iterator __p, _Pp&& __x); |
||
921 | #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
922 | iterator __insert_multi(const value_type& __x); |
||
923 | iterator __insert_multi(const_iterator __p, const value_type& __x); |
||
924 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
925 | |||
926 | void clear() _NOEXCEPT; |
||
927 | void rehash(size_type __n); |
||
928 | _LIBCPP_INLINE_VISIBILITY void reserve(size_type __n) |
||
929 | {rehash(static_cast<size_type>(ceil(__n / max_load_factor())));} |
||
930 | |||
931 | _LIBCPP_INLINE_VISIBILITY |
||
932 | size_type bucket_count() const _NOEXCEPT |
||
933 | { |
||
934 | return __bucket_list_.get_deleter().size(); |
||
935 | } |
||
936 | |||
937 | iterator begin() _NOEXCEPT; |
||
938 | iterator end() _NOEXCEPT; |
||
939 | const_iterator begin() const _NOEXCEPT; |
||
940 | const_iterator end() const _NOEXCEPT; |
||
941 | |||
942 | template <class _Key> |
||
943 | _LIBCPP_INLINE_VISIBILITY |
||
944 | size_type bucket(const _Key& __k) const |
||
945 | { |
||
946 | _LIBCPP_ASSERT(bucket_count() > 0, |
||
947 | "unordered container::bucket(key) called when bucket_count() == 0"); |
||
948 | return __constrain_hash(hash_function()(__k), bucket_count()); |
||
949 | } |
||
950 | |||
951 | template <class _Key> |
||
952 | iterator find(const _Key& __x); |
||
953 | template <class _Key> |
||
954 | const_iterator find(const _Key& __x) const; |
||
955 | |||
956 | typedef __hash_node_destructor<__node_allocator> _Dp; |
||
957 | typedef unique_ptr<__node, _Dp> __node_holder; |
||
958 | |||
959 | iterator erase(const_iterator __p); |
||
960 | iterator erase(const_iterator __first, const_iterator __last); |
||
961 | template <class _Key> |
||
962 | size_type __erase_unique(const _Key& __k); |
||
963 | template <class _Key> |
||
964 | size_type __erase_multi(const _Key& __k); |
||
965 | __node_holder remove(const_iterator __p) _NOEXCEPT; |
||
966 | |||
967 | template <class _Key> |
||
968 | size_type __count_unique(const _Key& __k) const; |
||
969 | template <class _Key> |
||
970 | size_type __count_multi(const _Key& __k) const; |
||
971 | |||
972 | template <class _Key> |
||
973 | pair<iterator, iterator> |
||
974 | __equal_range_unique(const _Key& __k); |
||
975 | template <class _Key> |
||
976 | pair<const_iterator, const_iterator> |
||
977 | __equal_range_unique(const _Key& __k) const; |
||
978 | |||
979 | template <class _Key> |
||
980 | pair<iterator, iterator> |
||
981 | __equal_range_multi(const _Key& __k); |
||
982 | template <class _Key> |
||
983 | pair<const_iterator, const_iterator> |
||
984 | __equal_range_multi(const _Key& __k) const; |
||
985 | |||
986 | void swap(__hash_table& __u) |
||
987 | #if _LIBCPP_STD_VER <= 11 |
||
988 | _NOEXCEPT_( |
||
989 | __is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value |
||
990 | && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value |
||
991 | || __is_nothrow_swappable<__pointer_allocator>::value) |
||
992 | && (!__node_traits::propagate_on_container_swap::value |
||
993 | || __is_nothrow_swappable<__node_allocator>::value) |
||
994 | ); |
||
995 | #else |
||
996 | _NOEXCEPT_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value); |
||
997 | #endif |
||
998 | |||
999 | _LIBCPP_INLINE_VISIBILITY |
||
1000 | size_type max_bucket_count() const _NOEXCEPT |
||
1001 | {return __pointer_alloc_traits::max_size(__bucket_list_.get_deleter().__alloc());} |
||
1002 | size_type bucket_size(size_type __n) const; |
||
1003 | _LIBCPP_INLINE_VISIBILITY float load_factor() const _NOEXCEPT |
||
1004 | { |
||
1005 | size_type __bc = bucket_count(); |
||
1006 | return __bc != 0 ? (float)size() / __bc : 0.f; |
||
1007 | } |
||
1008 | _LIBCPP_INLINE_VISIBILITY void max_load_factor(float __mlf) _NOEXCEPT |
||
1009 | { |
||
1010 | _LIBCPP_ASSERT(__mlf > 0, |
||
1011 | "unordered container::max_load_factor(lf) called with lf <= 0"); |
||
1012 | max_load_factor() = _VSTD::max(__mlf, load_factor()); |
||
1013 | } |
||
1014 | |||
1015 | _LIBCPP_INLINE_VISIBILITY |
||
1016 | local_iterator |
||
1017 | begin(size_type __n) |
||
1018 | { |
||
1019 | _LIBCPP_ASSERT(__n < bucket_count(), |
||
1020 | "unordered container::begin(n) called with n >= bucket_count()"); |
||
1021 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1022 | return local_iterator(__bucket_list_[__n], __n, bucket_count(), this); |
||
1023 | #else |
||
1024 | return local_iterator(__bucket_list_[__n], __n, bucket_count()); |
||
1025 | #endif |
||
1026 | } |
||
1027 | |||
1028 | _LIBCPP_INLINE_VISIBILITY |
||
1029 | local_iterator |
||
1030 | end(size_type __n) |
||
1031 | { |
||
1032 | _LIBCPP_ASSERT(__n < bucket_count(), |
||
1033 | "unordered container::end(n) called with n >= bucket_count()"); |
||
1034 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1035 | return local_iterator(nullptr, __n, bucket_count(), this); |
||
1036 | #else |
||
1037 | return local_iterator(nullptr, __n, bucket_count()); |
||
1038 | #endif |
||
1039 | } |
||
1040 | |||
1041 | _LIBCPP_INLINE_VISIBILITY |
||
1042 | const_local_iterator |
||
1043 | cbegin(size_type __n) const |
||
1044 | { |
||
1045 | _LIBCPP_ASSERT(__n < bucket_count(), |
||
1046 | "unordered container::cbegin(n) called with n >= bucket_count()"); |
||
1047 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1048 | return const_local_iterator(__bucket_list_[__n], __n, bucket_count(), this); |
||
1049 | #else |
||
1050 | return const_local_iterator(__bucket_list_[__n], __n, bucket_count()); |
||
1051 | #endif |
||
1052 | } |
||
1053 | |||
1054 | _LIBCPP_INLINE_VISIBILITY |
||
1055 | const_local_iterator |
||
1056 | cend(size_type __n) const |
||
1057 | { |
||
1058 | _LIBCPP_ASSERT(__n < bucket_count(), |
||
1059 | "unordered container::cend(n) called with n >= bucket_count()"); |
||
1060 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1061 | return const_local_iterator(nullptr, __n, bucket_count(), this); |
||
1062 | #else |
||
1063 | return const_local_iterator(nullptr, __n, bucket_count()); |
||
1064 | #endif |
||
1065 | } |
||
1066 | |||
1067 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1068 | |||
1069 | bool __dereferenceable(const const_iterator* __i) const; |
||
1070 | bool __decrementable(const const_iterator* __i) const; |
||
1071 | bool __addable(const const_iterator* __i, ptrdiff_t __n) const; |
||
1072 | bool __subscriptable(const const_iterator* __i, ptrdiff_t __n) const; |
||
1073 | |||
1074 | #endif // _LIBCPP_DEBUG_LEVEL >= 2 |
||
1075 | |||
1076 | private: |
||
1077 | void __rehash(size_type __n); |
||
1078 | |||
1079 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1080 | #ifndef _LIBCPP_HAS_NO_VARIADICS |
||
1081 | template <class ..._Args> |
||
1082 | __node_holder __construct_node(_Args&& ...__args); |
||
1083 | #endif // _LIBCPP_HAS_NO_VARIADICS |
||
1084 | __node_holder __construct_node(value_type&& __v, size_t __hash); |
||
1085 | #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1086 | __node_holder __construct_node(const value_type& __v); |
||
1087 | #endif |
||
1088 | __node_holder __construct_node(const value_type& __v, size_t __hash); |
||
1089 | |||
1090 | _LIBCPP_INLINE_VISIBILITY |
||
1091 | void __copy_assign_alloc(const __hash_table& __u) |
||
1092 | {__copy_assign_alloc(__u, integral_constant<bool, |
||
1093 | __node_traits::propagate_on_container_copy_assignment::value>());} |
||
1094 | void __copy_assign_alloc(const __hash_table& __u, true_type); |
||
1095 | _LIBCPP_INLINE_VISIBILITY |
||
1096 | void __copy_assign_alloc(const __hash_table&, false_type) {} |
||
1097 | |||
1098 | void __move_assign(__hash_table& __u, false_type); |
||
1099 | void __move_assign(__hash_table& __u, true_type) |
||
1100 | _NOEXCEPT_( |
||
1101 | is_nothrow_move_assignable<__node_allocator>::value && |
||
1102 | is_nothrow_move_assignable<hasher>::value && |
||
1103 | is_nothrow_move_assignable<key_equal>::value); |
||
1104 | _LIBCPP_INLINE_VISIBILITY |
||
1105 | void __move_assign_alloc(__hash_table& __u) |
||
1106 | _NOEXCEPT_( |
||
1107 | !__node_traits::propagate_on_container_move_assignment::value || |
||
1108 | (is_nothrow_move_assignable<__pointer_allocator>::value && |
||
1109 | is_nothrow_move_assignable<__node_allocator>::value)) |
||
1110 | {__move_assign_alloc(__u, integral_constant<bool, |
||
1111 | __node_traits::propagate_on_container_move_assignment::value>());} |
||
1112 | _LIBCPP_INLINE_VISIBILITY |
||
1113 | void __move_assign_alloc(__hash_table& __u, true_type) |
||
1114 | _NOEXCEPT_( |
||
1115 | is_nothrow_move_assignable<__pointer_allocator>::value && |
||
1116 | is_nothrow_move_assignable<__node_allocator>::value) |
||
1117 | { |
||
1118 | __bucket_list_.get_deleter().__alloc() = |
||
1119 | _VSTD::move(__u.__bucket_list_.get_deleter().__alloc()); |
||
1120 | __node_alloc() = _VSTD::move(__u.__node_alloc()); |
||
1121 | } |
||
1122 | _LIBCPP_INLINE_VISIBILITY |
||
1123 | void __move_assign_alloc(__hash_table&, false_type) _NOEXCEPT {} |
||
1124 | |||
1125 | void __deallocate(__node_pointer __np) _NOEXCEPT; |
||
1126 | __node_pointer __detach() _NOEXCEPT; |
||
1127 | |||
1128 | template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY unordered_map; |
||
1129 | template <class, class, class, class, class> friend class _LIBCPP_TYPE_VIS_ONLY unordered_multimap; |
||
1130 | }; |
||
1131 | |||
1132 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1133 | inline _LIBCPP_INLINE_VISIBILITY |
||
1134 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table() |
||
1135 | _NOEXCEPT_( |
||
1136 | is_nothrow_default_constructible<__bucket_list>::value && |
||
1137 | is_nothrow_default_constructible<__first_node>::value && |
||
1138 | is_nothrow_default_constructible<hasher>::value && |
||
1139 | is_nothrow_default_constructible<key_equal>::value) |
||
1140 | : __p2_(0), |
||
1141 | __p3_(1.0f) |
||
1142 | { |
||
1143 | } |
||
1144 | |||
1145 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1146 | inline _LIBCPP_INLINE_VISIBILITY |
||
1147 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf, |
||
1148 | const key_equal& __eql) |
||
1149 | : __bucket_list_(nullptr, __bucket_list_deleter()), |
||
1150 | __p1_(), |
||
1151 | __p2_(0, __hf), |
||
1152 | __p3_(1.0f, __eql) |
||
1153 | { |
||
1154 | } |
||
1155 | |||
1156 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1157 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const hasher& __hf, |
||
1158 | const key_equal& __eql, |
||
1159 | const allocator_type& __a) |
||
1160 | : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)), |
||
1161 | __p1_(__node_allocator(__a)), |
||
1162 | __p2_(0, __hf), |
||
1163 | __p3_(1.0f, __eql) |
||
1164 | { |
||
1165 | } |
||
1166 | |||
1167 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1168 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const allocator_type& __a) |
||
1169 | : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)), |
||
1170 | __p1_(__node_allocator(__a)), |
||
1171 | __p2_(0), |
||
1172 | __p3_(1.0f) |
||
1173 | { |
||
1174 | } |
||
1175 | |||
1176 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1177 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u) |
||
1178 | : __bucket_list_(nullptr, |
||
1179 | __bucket_list_deleter(allocator_traits<__pointer_allocator>:: |
||
1180 | select_on_container_copy_construction( |
||
1181 | __u.__bucket_list_.get_deleter().__alloc()), 0)), |
||
1182 | __p1_(allocator_traits<__node_allocator>:: |
||
1183 | select_on_container_copy_construction(__u.__node_alloc())), |
||
1184 | __p2_(0, __u.hash_function()), |
||
1185 | __p3_(__u.__p3_) |
||
1186 | { |
||
1187 | } |
||
1188 | |||
1189 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1190 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(const __hash_table& __u, |
||
1191 | const allocator_type& __a) |
||
1192 | : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)), |
||
1193 | __p1_(__node_allocator(__a)), |
||
1194 | __p2_(0, __u.hash_function()), |
||
1195 | __p3_(__u.__p3_) |
||
1196 | { |
||
1197 | } |
||
1198 | |||
1199 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1200 | |||
1201 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1202 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u) |
||
1203 | _NOEXCEPT_( |
||
1204 | is_nothrow_move_constructible<__bucket_list>::value && |
||
1205 | is_nothrow_move_constructible<__first_node>::value && |
||
1206 | is_nothrow_move_constructible<hasher>::value && |
||
1207 | is_nothrow_move_constructible<key_equal>::value) |
||
1208 | : __bucket_list_(_VSTD::move(__u.__bucket_list_)), |
||
1209 | __p1_(_VSTD::move(__u.__p1_)), |
||
1210 | __p2_(_VSTD::move(__u.__p2_)), |
||
1211 | __p3_(_VSTD::move(__u.__p3_)) |
||
1212 | { |
||
1213 | if (size() > 0) |
||
1214 | { |
||
1215 | __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] = |
||
1216 | static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); |
||
1217 | __u.__p1_.first().__next_ = nullptr; |
||
1218 | __u.size() = 0; |
||
1219 | } |
||
1220 | } |
||
1221 | |||
1222 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1223 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u, |
||
1224 | const allocator_type& __a) |
||
1225 | : __bucket_list_(nullptr, __bucket_list_deleter(__pointer_allocator(__a), 0)), |
||
1226 | __p1_(__node_allocator(__a)), |
||
1227 | __p2_(0, _VSTD::move(__u.hash_function())), |
||
1228 | __p3_(_VSTD::move(__u.__p3_)) |
||
1229 | { |
||
1230 | if (__a == allocator_type(__u.__node_alloc())) |
||
1231 | { |
||
1232 | __bucket_list_.reset(__u.__bucket_list_.release()); |
||
1233 | __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size(); |
||
1234 | __u.__bucket_list_.get_deleter().size() = 0; |
||
1235 | if (__u.size() > 0) |
||
1236 | { |
||
1237 | __p1_.first().__next_ = __u.__p1_.first().__next_; |
||
1238 | __u.__p1_.first().__next_ = nullptr; |
||
1239 | __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] = |
||
1240 | static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); |
||
1241 | size() = __u.size(); |
||
1242 | __u.size() = 0; |
||
1243 | } |
||
1244 | } |
||
1245 | } |
||
1246 | |||
1247 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1248 | |||
1249 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1250 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table() |
||
1251 | { |
||
1252 | __deallocate(__p1_.first().__next_); |
||
1253 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1254 | __get_db()->__erase_c(this); |
||
1255 | #endif |
||
1256 | } |
||
1257 | |||
1258 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1259 | void |
||
1260 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__copy_assign_alloc( |
||
1261 | const __hash_table& __u, true_type) |
||
1262 | { |
||
1263 | if (__node_alloc() != __u.__node_alloc()) |
||
1264 | { |
||
1265 | clear(); |
||
1266 | __bucket_list_.reset(); |
||
1267 | __bucket_list_.get_deleter().size() = 0; |
||
1268 | } |
||
1269 | __bucket_list_.get_deleter().__alloc() = __u.__bucket_list_.get_deleter().__alloc(); |
||
1270 | __node_alloc() = __u.__node_alloc(); |
||
1271 | } |
||
1272 | |||
1273 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1274 | __hash_table<_Tp, _Hash, _Equal, _Alloc>& |
||
1275 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(const __hash_table& __u) |
||
1276 | { |
||
1277 | if (this != &__u) |
||
1278 | { |
||
1279 | __copy_assign_alloc(__u); |
||
1280 | hash_function() = __u.hash_function(); |
||
1281 | key_eq() = __u.key_eq(); |
||
1282 | max_load_factor() = __u.max_load_factor(); |
||
1283 | __assign_multi(__u.begin(), __u.end()); |
||
1284 | } |
||
1285 | return *this; |
||
1286 | } |
||
1287 | |||
1288 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1289 | void |
||
1290 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__deallocate(__node_pointer __np) |
||
1291 | _NOEXCEPT |
||
1292 | { |
||
1293 | __node_allocator& __na = __node_alloc(); |
||
1294 | while (__np != nullptr) |
||
1295 | { |
||
1296 | __node_pointer __next = __np->__next_; |
||
1297 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1298 | __c_node* __c = __get_db()->__find_c_and_lock(this); |
||
1299 | for (__i_node** __p = __c->end_; __p != __c->beg_; ) |
||
1300 | { |
||
1301 | --__p; |
||
1302 | iterator* __i = static_cast<iterator*>((*__p)->__i_); |
||
1303 | if (__i->__node_ == __np) |
||
1304 | { |
||
1305 | (*__p)->__c_ = nullptr; |
||
1306 | if (--__c->end_ != __p) |
||
1307 | memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); |
||
1308 | } |
||
1309 | } |
||
1310 | __get_db()->unlock(); |
||
1311 | #endif |
||
1312 | __node_traits::destroy(__na, _VSTD::addressof(__np->__value_)); |
||
1313 | __node_traits::deallocate(__na, __np, 1); |
||
1314 | __np = __next; |
||
1315 | } |
||
1316 | } |
||
1317 | |||
1318 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1319 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_pointer |
||
1320 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__detach() _NOEXCEPT |
||
1321 | { |
||
1322 | size_type __bc = bucket_count(); |
||
1323 | for (size_type __i = 0; __i < __bc; ++__i) |
||
1324 | __bucket_list_[__i] = nullptr; |
||
1325 | size() = 0; |
||
1326 | __node_pointer __cache = __p1_.first().__next_; |
||
1327 | __p1_.first().__next_ = nullptr; |
||
1328 | return __cache; |
||
1329 | } |
||
1330 | |||
1331 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1332 | |||
1333 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1334 | void |
||
1335 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( |
||
1336 | __hash_table& __u, true_type) |
||
1337 | _NOEXCEPT_( |
||
1338 | is_nothrow_move_assignable<__node_allocator>::value && |
||
1339 | is_nothrow_move_assignable<hasher>::value && |
||
1340 | is_nothrow_move_assignable<key_equal>::value) |
||
1341 | { |
||
1342 | clear(); |
||
1343 | __bucket_list_.reset(__u.__bucket_list_.release()); |
||
1344 | __bucket_list_.get_deleter().size() = __u.__bucket_list_.get_deleter().size(); |
||
1345 | __u.__bucket_list_.get_deleter().size() = 0; |
||
1346 | __move_assign_alloc(__u); |
||
1347 | size() = __u.size(); |
||
1348 | hash_function() = _VSTD::move(__u.hash_function()); |
||
1349 | max_load_factor() = __u.max_load_factor(); |
||
1350 | key_eq() = _VSTD::move(__u.key_eq()); |
||
1351 | __p1_.first().__next_ = __u.__p1_.first().__next_; |
||
1352 | if (size() > 0) |
||
1353 | { |
||
1354 | __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] = |
||
1355 | static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); |
||
1356 | __u.__p1_.first().__next_ = nullptr; |
||
1357 | __u.size() = 0; |
||
1358 | } |
||
1359 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1360 | __get_db()->swap(this, &__u); |
||
1361 | #endif |
||
1362 | } |
||
1363 | |||
1364 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1365 | void |
||
1366 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__move_assign( |
||
1367 | __hash_table& __u, false_type) |
||
1368 | { |
||
1369 | if (__node_alloc() == __u.__node_alloc()) |
||
1370 | __move_assign(__u, true_type()); |
||
1371 | else |
||
1372 | { |
||
1373 | hash_function() = _VSTD::move(__u.hash_function()); |
||
1374 | key_eq() = _VSTD::move(__u.key_eq()); |
||
1375 | max_load_factor() = __u.max_load_factor(); |
||
1376 | if (bucket_count() != 0) |
||
1377 | { |
||
1378 | __node_pointer __cache = __detach(); |
||
1379 | #ifndef _LIBCPP_NO_EXCEPTIONS |
||
1380 | try |
||
1381 | { |
||
1382 | #endif // _LIBCPP_NO_EXCEPTIONS |
||
1383 | const_iterator __i = __u.begin(); |
||
1384 | while (__cache != nullptr && __u.size() != 0) |
||
1385 | { |
||
1386 | __cache->__value_ = _VSTD::move(__u.remove(__i++)->__value_); |
||
1387 | __node_pointer __next = __cache->__next_; |
||
1388 | __node_insert_multi(__cache); |
||
1389 | __cache = __next; |
||
1390 | } |
||
1391 | #ifndef _LIBCPP_NO_EXCEPTIONS |
||
1392 | } |
||
1393 | catch (...) |
||
1394 | { |
||
1395 | __deallocate(__cache); |
||
1396 | throw; |
||
1397 | } |
||
1398 | #endif // _LIBCPP_NO_EXCEPTIONS |
||
1399 | __deallocate(__cache); |
||
1400 | } |
||
1401 | const_iterator __i = __u.begin(); |
||
1402 | while (__u.size() != 0) |
||
1403 | { |
||
1404 | __node_holder __h = |
||
1405 | __construct_node(_VSTD::move(__u.remove(__i++)->__value_)); |
||
1406 | __node_insert_multi(__h.get()); |
||
1407 | __h.release(); |
||
1408 | } |
||
1409 | } |
||
1410 | } |
||
1411 | |||
1412 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1413 | inline _LIBCPP_INLINE_VISIBILITY |
||
1414 | __hash_table<_Tp, _Hash, _Equal, _Alloc>& |
||
1415 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::operator=(__hash_table&& __u) |
||
1416 | _NOEXCEPT_( |
||
1417 | __node_traits::propagate_on_container_move_assignment::value && |
||
1418 | is_nothrow_move_assignable<__node_allocator>::value && |
||
1419 | is_nothrow_move_assignable<hasher>::value && |
||
1420 | is_nothrow_move_assignable<key_equal>::value) |
||
1421 | { |
||
1422 | __move_assign(__u, integral_constant<bool, |
||
1423 | __node_traits::propagate_on_container_move_assignment::value>()); |
||
1424 | return *this; |
||
1425 | } |
||
1426 | |||
1427 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1428 | |||
1429 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1430 | template <class _InputIterator> |
||
1431 | void |
||
1432 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_unique(_InputIterator __first, |
||
1433 | _InputIterator __last) |
||
1434 | { |
||
1435 | if (bucket_count() != 0) |
||
1436 | { |
||
1437 | __node_pointer __cache = __detach(); |
||
1438 | #ifndef _LIBCPP_NO_EXCEPTIONS |
||
1439 | try |
||
1440 | { |
||
1441 | #endif // _LIBCPP_NO_EXCEPTIONS |
||
1442 | for (; __cache != nullptr && __first != __last; ++__first) |
||
1443 | { |
||
1444 | __cache->__value_ = *__first; |
||
1445 | __node_pointer __next = __cache->__next_; |
||
1446 | __node_insert_unique(__cache); |
||
1447 | __cache = __next; |
||
1448 | } |
||
1449 | #ifndef _LIBCPP_NO_EXCEPTIONS |
||
1450 | } |
||
1451 | catch (...) |
||
1452 | { |
||
1453 | __deallocate(__cache); |
||
1454 | throw; |
||
1455 | } |
||
1456 | #endif // _LIBCPP_NO_EXCEPTIONS |
||
1457 | __deallocate(__cache); |
||
1458 | } |
||
1459 | for (; __first != __last; ++__first) |
||
1460 | __insert_unique(*__first); |
||
1461 | } |
||
1462 | |||
1463 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1464 | template <class _InputIterator> |
||
1465 | void |
||
1466 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__assign_multi(_InputIterator __first, |
||
1467 | _InputIterator __last) |
||
1468 | { |
||
1469 | if (bucket_count() != 0) |
||
1470 | { |
||
1471 | __node_pointer __cache = __detach(); |
||
1472 | #ifndef _LIBCPP_NO_EXCEPTIONS |
||
1473 | try |
||
1474 | { |
||
1475 | #endif // _LIBCPP_NO_EXCEPTIONS |
||
1476 | for (; __cache != nullptr && __first != __last; ++__first) |
||
1477 | { |
||
1478 | __cache->__value_ = *__first; |
||
1479 | __node_pointer __next = __cache->__next_; |
||
1480 | __node_insert_multi(__cache); |
||
1481 | __cache = __next; |
||
1482 | } |
||
1483 | #ifndef _LIBCPP_NO_EXCEPTIONS |
||
1484 | } |
||
1485 | catch (...) |
||
1486 | { |
||
1487 | __deallocate(__cache); |
||
1488 | throw; |
||
1489 | } |
||
1490 | #endif // _LIBCPP_NO_EXCEPTIONS |
||
1491 | __deallocate(__cache); |
||
1492 | } |
||
1493 | for (; __first != __last; ++__first) |
||
1494 | __insert_multi(*__first); |
||
1495 | } |
||
1496 | |||
1497 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1498 | inline _LIBCPP_INLINE_VISIBILITY |
||
1499 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator |
||
1500 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() _NOEXCEPT |
||
1501 | { |
||
1502 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1503 | return iterator(__p1_.first().__next_, this); |
||
1504 | #else |
||
1505 | return iterator(__p1_.first().__next_); |
||
1506 | #endif |
||
1507 | } |
||
1508 | |||
1509 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1510 | inline _LIBCPP_INLINE_VISIBILITY |
||
1511 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator |
||
1512 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() _NOEXCEPT |
||
1513 | { |
||
1514 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1515 | return iterator(nullptr, this); |
||
1516 | #else |
||
1517 | return iterator(nullptr); |
||
1518 | #endif |
||
1519 | } |
||
1520 | |||
1521 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1522 | inline _LIBCPP_INLINE_VISIBILITY |
||
1523 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator |
||
1524 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::begin() const _NOEXCEPT |
||
1525 | { |
||
1526 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1527 | return const_iterator(__p1_.first().__next_, this); |
||
1528 | #else |
||
1529 | return const_iterator(__p1_.first().__next_); |
||
1530 | #endif |
||
1531 | } |
||
1532 | |||
1533 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1534 | inline _LIBCPP_INLINE_VISIBILITY |
||
1535 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator |
||
1536 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::end() const _NOEXCEPT |
||
1537 | { |
||
1538 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1539 | return const_iterator(nullptr, this); |
||
1540 | #else |
||
1541 | return const_iterator(nullptr); |
||
1542 | #endif |
||
1543 | } |
||
1544 | |||
1545 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1546 | void |
||
1547 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::clear() _NOEXCEPT |
||
1548 | { |
||
1549 | if (size() > 0) |
||
1550 | { |
||
1551 | __deallocate(__p1_.first().__next_); |
||
1552 | __p1_.first().__next_ = nullptr; |
||
1553 | size_type __bc = bucket_count(); |
||
1554 | for (size_type __i = 0; __i < __bc; ++__i) |
||
1555 | __bucket_list_[__i] = nullptr; |
||
1556 | size() = 0; |
||
1557 | } |
||
1558 | } |
||
1559 | |||
1560 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1561 | pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool> |
||
1562 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_unique(__node_pointer __nd) |
||
1563 | { |
||
1564 | __nd->__hash_ = hash_function()(__nd->__value_); |
||
1565 | size_type __bc = bucket_count(); |
||
1566 | bool __inserted = false; |
||
1567 | __node_pointer __ndptr; |
||
1568 | size_t __chash; |
||
1569 | if (__bc != 0) |
||
1570 | { |
||
1571 | __chash = __constrain_hash(__nd->__hash_, __bc); |
||
1572 | __ndptr = __bucket_list_[__chash]; |
||
1573 | if (__ndptr != nullptr) |
||
1574 | { |
||
1575 | for (__ndptr = __ndptr->__next_; __ndptr != nullptr && |
||
1576 | __constrain_hash(__ndptr->__hash_, __bc) == __chash; |
||
1577 | __ndptr = __ndptr->__next_) |
||
1578 | { |
||
1579 | if (key_eq()(__ndptr->__value_, __nd->__value_)) |
||
1580 | goto __done; |
||
1581 | } |
||
1582 | } |
||
1583 | } |
||
1584 | { |
||
1585 | if (size()+1 > __bc * max_load_factor() || __bc == 0) |
||
1586 | { |
||
1587 | rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc), |
||
1588 | size_type(ceil(float(size() + 1) / max_load_factor())))); |
||
1589 | __bc = bucket_count(); |
||
1590 | __chash = __constrain_hash(__nd->__hash_, __bc); |
||
1591 | } |
||
1592 | // insert_after __bucket_list_[__chash], or __first_node if bucket is null |
||
1593 | __node_pointer __pn = __bucket_list_[__chash]; |
||
1594 | if (__pn == nullptr) |
||
1595 | { |
||
1596 | __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); |
||
1597 | __nd->__next_ = __pn->__next_; |
||
1598 | __pn->__next_ = __nd; |
||
1599 | // fix up __bucket_list_ |
||
1600 | __bucket_list_[__chash] = __pn; |
||
1601 | if (__nd->__next_ != nullptr) |
||
1602 | __bucket_list_[__constrain_hash(__nd->__next_->__hash_, __bc)] = __nd; |
||
1603 | } |
||
1604 | else |
||
1605 | { |
||
1606 | __nd->__next_ = __pn->__next_; |
||
1607 | __pn->__next_ = __nd; |
||
1608 | } |
||
1609 | __ndptr = __nd; |
||
1610 | // increment size |
||
1611 | ++size(); |
||
1612 | __inserted = true; |
||
1613 | } |
||
1614 | __done: |
||
1615 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1616 | return pair<iterator, bool>(iterator(__ndptr, this), __inserted); |
||
1617 | #else |
||
1618 | return pair<iterator, bool>(iterator(__ndptr), __inserted); |
||
1619 | #endif |
||
1620 | } |
||
1621 | |||
1622 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1623 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator |
||
1624 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi(__node_pointer __cp) |
||
1625 | { |
||
1626 | __cp->__hash_ = hash_function()(__cp->__value_); |
||
1627 | size_type __bc = bucket_count(); |
||
1628 | if (size()+1 > __bc * max_load_factor() || __bc == 0) |
||
1629 | { |
||
1630 | rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc), |
||
1631 | size_type(ceil(float(size() + 1) / max_load_factor())))); |
||
1632 | __bc = bucket_count(); |
||
1633 | } |
||
1634 | size_t __chash = __constrain_hash(__cp->__hash_, __bc); |
||
1635 | __node_pointer __pn = __bucket_list_[__chash]; |
||
1636 | if (__pn == nullptr) |
||
1637 | { |
||
1638 | __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); |
||
1639 | __cp->__next_ = __pn->__next_; |
||
1640 | __pn->__next_ = __cp; |
||
1641 | // fix up __bucket_list_ |
||
1642 | __bucket_list_[__chash] = __pn; |
||
1643 | if (__cp->__next_ != nullptr) |
||
1644 | __bucket_list_[__constrain_hash(__cp->__next_->__hash_, __bc)] = __cp; |
||
1645 | } |
||
1646 | else |
||
1647 | { |
||
1648 | for (bool __found = false; __pn->__next_ != nullptr && |
||
1649 | __constrain_hash(__pn->__next_->__hash_, __bc) == __chash; |
||
1650 | __pn = __pn->__next_) |
||
1651 | { |
||
1652 | // __found key_eq() action |
||
1653 | // false false loop |
||
1654 | // true true loop |
||
1655 | // false true set __found to true |
||
1656 | // true false break |
||
1657 | if (__found != (__pn->__next_->__hash_ == __cp->__hash_ && |
||
1658 | key_eq()(__pn->__next_->__value_, __cp->__value_))) |
||
1659 | { |
||
1660 | if (!__found) |
||
1661 | __found = true; |
||
1662 | else |
||
1663 | break; |
||
1664 | } |
||
1665 | } |
||
1666 | __cp->__next_ = __pn->__next_; |
||
1667 | __pn->__next_ = __cp; |
||
1668 | if (__cp->__next_ != nullptr) |
||
1669 | { |
||
1670 | size_t __nhash = __constrain_hash(__cp->__next_->__hash_, __bc); |
||
1671 | if (__nhash != __chash) |
||
1672 | __bucket_list_[__nhash] = __cp; |
||
1673 | } |
||
1674 | } |
||
1675 | ++size(); |
||
1676 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1677 | return iterator(__cp, this); |
||
1678 | #else |
||
1679 | return iterator(__cp); |
||
1680 | #endif |
||
1681 | } |
||
1682 | |||
1683 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1684 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator |
||
1685 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_insert_multi( |
||
1686 | const_iterator __p, __node_pointer __cp) |
||
1687 | { |
||
1688 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1689 | _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, |
||
1690 | "unordered container::emplace_hint(const_iterator, args...) called with an iterator not" |
||
1691 | " referring to this unordered container"); |
||
1692 | #endif |
||
1693 | if (__p != end() && key_eq()(*__p, __cp->__value_)) |
||
1694 | { |
||
1695 | __node_pointer __np = __p.__node_; |
||
1696 | __cp->__hash_ = __np->__hash_; |
||
1697 | size_type __bc = bucket_count(); |
||
1698 | if (size()+1 > __bc * max_load_factor() || __bc == 0) |
||
1699 | { |
||
1700 | rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc), |
||
1701 | size_type(ceil(float(size() + 1) / max_load_factor())))); |
||
1702 | __bc = bucket_count(); |
||
1703 | } |
||
1704 | size_t __chash = __constrain_hash(__cp->__hash_, __bc); |
||
1705 | __node_pointer __pp = __bucket_list_[__chash]; |
||
1706 | while (__pp->__next_ != __np) |
||
1707 | __pp = __pp->__next_; |
||
1708 | __cp->__next_ = __np; |
||
1709 | __pp->__next_ = __cp; |
||
1710 | ++size(); |
||
1711 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1712 | return iterator(__cp, this); |
||
1713 | #else |
||
1714 | return iterator(__cp); |
||
1715 | #endif |
||
1716 | } |
||
1717 | return __node_insert_multi(__cp); |
||
1718 | } |
||
1719 | |||
1720 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1721 | pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool> |
||
1722 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(const value_type& __x) |
||
1723 | { |
||
1724 | return __insert_unique_value(__x); |
||
1725 | } |
||
1726 | |||
1727 | |||
1728 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1729 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1730 | template <class _ValueTp> |
||
1731 | _LIBCPP_INLINE_VISIBILITY |
||
1732 | pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool> |
||
1733 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique_value(_ValueTp&& __x) |
||
1734 | #else |
||
1735 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1736 | _LIBCPP_INLINE_VISIBILITY |
||
1737 | pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool> |
||
1738 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique_value(const value_type& __x) |
||
1739 | #endif |
||
1740 | { |
||
1741 | #if defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES) |
||
1742 | typedef const value_type& _ValueTp; |
||
1743 | #endif |
||
1744 | size_t __hash = hash_function()(__x); |
||
1745 | size_type __bc = bucket_count(); |
||
1746 | bool __inserted = false; |
||
1747 | __node_pointer __nd; |
||
1748 | size_t __chash; |
||
1749 | if (__bc != 0) |
||
1750 | { |
||
1751 | __chash = __constrain_hash(__hash, __bc); |
||
1752 | __nd = __bucket_list_[__chash]; |
||
1753 | if (__nd != nullptr) |
||
1754 | { |
||
1755 | for (__nd = __nd->__next_; __nd != nullptr && |
||
1756 | __constrain_hash(__nd->__hash_, __bc) == __chash; |
||
1757 | __nd = __nd->__next_) |
||
1758 | { |
||
1759 | if (key_eq()(__nd->__value_, __x)) |
||
1760 | goto __done; |
||
1761 | } |
||
1762 | } |
||
1763 | } |
||
1764 | { |
||
1765 | __node_holder __h = __construct_node(_VSTD::forward<_ValueTp>(__x), __hash); |
||
1766 | if (size()+1 > __bc * max_load_factor() || __bc == 0) |
||
1767 | { |
||
1768 | rehash(_VSTD::max<size_type>(2 * __bc + !__is_hash_power2(__bc), |
||
1769 | size_type(ceil(float(size() + 1) / max_load_factor())))); |
||
1770 | __bc = bucket_count(); |
||
1771 | __chash = __constrain_hash(__hash, __bc); |
||
1772 | } |
||
1773 | // insert_after __bucket_list_[__chash], or __first_node if bucket is null |
||
1774 | __node_pointer __pn = __bucket_list_[__chash]; |
||
1775 | if (__pn == nullptr) |
||
1776 | { |
||
1777 | __pn = static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); |
||
1778 | __h->__next_ = __pn->__next_; |
||
1779 | __pn->__next_ = __h.get(); |
||
1780 | // fix up __bucket_list_ |
||
1781 | __bucket_list_[__chash] = __pn; |
||
1782 | if (__h->__next_ != nullptr) |
||
1783 | __bucket_list_[__constrain_hash(__h->__next_->__hash_, __bc)] = __h.get(); |
||
1784 | } |
||
1785 | else |
||
1786 | { |
||
1787 | __h->__next_ = __pn->__next_; |
||
1788 | __pn->__next_ = __h.get(); |
||
1789 | } |
||
1790 | __nd = __h.release(); |
||
1791 | // increment size |
||
1792 | ++size(); |
||
1793 | __inserted = true; |
||
1794 | } |
||
1795 | __done: |
||
1796 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1797 | return pair<iterator, bool>(iterator(__nd, this), __inserted); |
||
1798 | #else |
||
1799 | return pair<iterator, bool>(iterator(__nd), __inserted); |
||
1800 | #endif |
||
1801 | } |
||
1802 | |||
1803 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1804 | #ifndef _LIBCPP_HAS_NO_VARIADICS |
||
1805 | |||
1806 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1807 | template <class... _Args> |
||
1808 | pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool> |
||
1809 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_unique(_Args&&... __args) |
||
1810 | { |
||
1811 | __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); |
||
1812 | pair<iterator, bool> __r = __node_insert_unique(__h.get()); |
||
1813 | if (__r.second) |
||
1814 | __h.release(); |
||
1815 | return __r; |
||
1816 | } |
||
1817 | |||
1818 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1819 | template <class... _Args> |
||
1820 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator |
||
1821 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_multi(_Args&&... __args) |
||
1822 | { |
||
1823 | __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); |
||
1824 | iterator __r = __node_insert_multi(__h.get()); |
||
1825 | __h.release(); |
||
1826 | return __r; |
||
1827 | } |
||
1828 | |||
1829 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1830 | template <class... _Args> |
||
1831 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator |
||
1832 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__emplace_hint_multi( |
||
1833 | const_iterator __p, _Args&&... __args) |
||
1834 | { |
||
1835 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1836 | _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, |
||
1837 | "unordered container::emplace_hint(const_iterator, args...) called with an iterator not" |
||
1838 | " referring to this unordered container"); |
||
1839 | #endif |
||
1840 | __node_holder __h = __construct_node(_VSTD::forward<_Args>(__args)...); |
||
1841 | iterator __r = __node_insert_multi(__p, __h.get()); |
||
1842 | __h.release(); |
||
1843 | return __r; |
||
1844 | } |
||
1845 | |||
1846 | #endif // _LIBCPP_HAS_NO_VARIADICS |
||
1847 | |||
1848 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1849 | pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool> |
||
1850 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(value_type&& __x) |
||
1851 | { |
||
1852 | return __insert_unique_value(_VSTD::move(__x)); |
||
1853 | } |
||
1854 | |||
1855 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1856 | template <class _Pp> |
||
1857 | pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, bool> |
||
1858 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_unique(_Pp&& __x) |
||
1859 | { |
||
1860 | __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x)); |
||
1861 | pair<iterator, bool> __r = __node_insert_unique(__h.get()); |
||
1862 | if (__r.second) |
||
1863 | __h.release(); |
||
1864 | return __r; |
||
1865 | } |
||
1866 | |||
1867 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1868 | |||
1869 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1870 | |||
1871 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1872 | template <class _Pp> |
||
1873 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator |
||
1874 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(_Pp&& __x) |
||
1875 | { |
||
1876 | __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x)); |
||
1877 | iterator __r = __node_insert_multi(__h.get()); |
||
1878 | __h.release(); |
||
1879 | return __r; |
||
1880 | } |
||
1881 | |||
1882 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1883 | template <class _Pp> |
||
1884 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator |
||
1885 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p, |
||
1886 | _Pp&& __x) |
||
1887 | { |
||
1888 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1889 | _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, |
||
1890 | "unordered container::insert(const_iterator, rvalue) called with an iterator not" |
||
1891 | " referring to this unordered container"); |
||
1892 | #endif |
||
1893 | __node_holder __h = __construct_node(_VSTD::forward<_Pp>(__x)); |
||
1894 | iterator __r = __node_insert_multi(__p, __h.get()); |
||
1895 | __h.release(); |
||
1896 | return __r; |
||
1897 | } |
||
1898 | |||
1899 | #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1900 | |||
1901 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1902 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator |
||
1903 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const value_type& __x) |
||
1904 | { |
||
1905 | __node_holder __h = __construct_node(__x); |
||
1906 | iterator __r = __node_insert_multi(__h.get()); |
||
1907 | __h.release(); |
||
1908 | return __r; |
||
1909 | } |
||
1910 | |||
1911 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1912 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator |
||
1913 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__insert_multi(const_iterator __p, |
||
1914 | const value_type& __x) |
||
1915 | { |
||
1916 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1917 | _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, |
||
1918 | "unordered container::insert(const_iterator, lvalue) called with an iterator not" |
||
1919 | " referring to this unordered container"); |
||
1920 | #endif |
||
1921 | __node_holder __h = __construct_node(__x); |
||
1922 | iterator __r = __node_insert_multi(__p, __h.get()); |
||
1923 | __h.release(); |
||
1924 | return __r; |
||
1925 | } |
||
1926 | |||
1927 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
1928 | |||
1929 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1930 | void |
||
1931 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::rehash(size_type __n) |
||
1932 | { |
||
1933 | if (__n == 1) |
||
1934 | __n = 2; |
||
1935 | else if (__n & (__n - 1)) |
||
1936 | __n = __next_prime(__n); |
||
1937 | size_type __bc = bucket_count(); |
||
1938 | if (__n > __bc) |
||
1939 | __rehash(__n); |
||
1940 | else if (__n < __bc) |
||
1941 | { |
||
1942 | __n = _VSTD::max<size_type> |
||
1943 | ( |
||
1944 | __n, |
||
1945 | __is_hash_power2(__bc) ? __next_hash_pow2(size_t(ceil(float(size()) / max_load_factor()))) : |
||
1946 | __next_prime(size_t(ceil(float(size()) / max_load_factor()))) |
||
1947 | ); |
||
1948 | if (__n < __bc) |
||
1949 | __rehash(__n); |
||
1950 | } |
||
1951 | } |
||
1952 | |||
1953 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
1954 | void |
||
1955 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc) |
||
1956 | { |
||
1957 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
1958 | __get_db()->__invalidate_all(this); |
||
1959 | #endif // _LIBCPP_DEBUG_LEVEL >= 2 |
||
1960 | __pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc(); |
||
1961 | __bucket_list_.reset(__nbc > 0 ? |
||
1962 | __pointer_alloc_traits::allocate(__npa, __nbc) : nullptr); |
||
1963 | __bucket_list_.get_deleter().size() = __nbc; |
||
1964 | if (__nbc > 0) |
||
1965 | { |
||
1966 | for (size_type __i = 0; __i < __nbc; ++__i) |
||
1967 | __bucket_list_[__i] = nullptr; |
||
1968 | __node_pointer __pp(static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first()))); |
||
1969 | __node_pointer __cp = __pp->__next_; |
||
1970 | if (__cp != nullptr) |
||
1971 | { |
||
1972 | size_type __chash = __constrain_hash(__cp->__hash_, __nbc); |
||
1973 | __bucket_list_[__chash] = __pp; |
||
1974 | size_type __phash = __chash; |
||
1975 | for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr; |
||
1976 | __cp = __pp->__next_) |
||
1977 | { |
||
1978 | __chash = __constrain_hash(__cp->__hash_, __nbc); |
||
1979 | if (__chash == __phash) |
||
1980 | __pp = __cp; |
||
1981 | else |
||
1982 | { |
||
1983 | if (__bucket_list_[__chash] == nullptr) |
||
1984 | { |
||
1985 | __bucket_list_[__chash] = __pp; |
||
1986 | __pp = __cp; |
||
1987 | __phash = __chash; |
||
1988 | } |
||
1989 | else |
||
1990 | { |
||
1991 | __node_pointer __np = __cp; |
||
1992 | for (; __np->__next_ != nullptr && |
||
1993 | key_eq()(__cp->__value_, __np->__next_->__value_); |
||
1994 | __np = __np->__next_) |
||
1995 | ; |
||
1996 | __pp->__next_ = __np->__next_; |
||
1997 | __np->__next_ = __bucket_list_[__chash]->__next_; |
||
1998 | __bucket_list_[__chash]->__next_ = __cp; |
||
1999 | |||
2000 | } |
||
2001 | } |
||
2002 | } |
||
2003 | } |
||
2004 | } |
||
2005 | } |
||
2006 | |||
2007 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2008 | template <class _Key> |
||
2009 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator |
||
2010 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) |
||
2011 | { |
||
2012 | size_t __hash = hash_function()(__k); |
||
2013 | size_type __bc = bucket_count(); |
||
2014 | if (__bc != 0) |
||
2015 | { |
||
2016 | size_t __chash = __constrain_hash(__hash, __bc); |
||
2017 | __node_pointer __nd = __bucket_list_[__chash]; |
||
2018 | if (__nd != nullptr) |
||
2019 | { |
||
2020 | for (__nd = __nd->__next_; __nd != nullptr && |
||
2021 | __constrain_hash(__nd->__hash_, __bc) == __chash; |
||
2022 | __nd = __nd->__next_) |
||
2023 | { |
||
2024 | if (key_eq()(__nd->__value_, __k)) |
||
2025 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
2026 | return iterator(__nd, this); |
||
2027 | #else |
||
2028 | return iterator(__nd); |
||
2029 | #endif |
||
2030 | } |
||
2031 | } |
||
2032 | } |
||
2033 | return end(); |
||
2034 | } |
||
2035 | |||
2036 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2037 | template <class _Key> |
||
2038 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator |
||
2039 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::find(const _Key& __k) const |
||
2040 | { |
||
2041 | size_t __hash = hash_function()(__k); |
||
2042 | size_type __bc = bucket_count(); |
||
2043 | if (__bc != 0) |
||
2044 | { |
||
2045 | size_t __chash = __constrain_hash(__hash, __bc); |
||
2046 | __node_const_pointer __nd = __bucket_list_[__chash]; |
||
2047 | if (__nd != nullptr) |
||
2048 | { |
||
2049 | for (__nd = __nd->__next_; __nd != nullptr && |
||
2050 | __constrain_hash(__nd->__hash_, __bc) == __chash; |
||
2051 | __nd = __nd->__next_) |
||
2052 | { |
||
2053 | if (key_eq()(__nd->__value_, __k)) |
||
2054 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
2055 | return const_iterator(__nd, this); |
||
2056 | #else |
||
2057 | return const_iterator(__nd); |
||
2058 | #endif |
||
2059 | } |
||
2060 | } |
||
2061 | |||
2062 | } |
||
2063 | return end(); |
||
2064 | } |
||
2065 | |||
2066 | #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
2067 | #ifndef _LIBCPP_HAS_NO_VARIADICS |
||
2068 | |||
2069 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2070 | template <class ..._Args> |
||
2071 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder |
||
2072 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(_Args&& ...__args) |
||
2073 | { |
||
2074 | __node_allocator& __na = __node_alloc(); |
||
2075 | __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); |
||
2076 | __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::forward<_Args>(__args)...); |
||
2077 | __h.get_deleter().__value_constructed = true; |
||
2078 | __h->__hash_ = hash_function()(__h->__value_); |
||
2079 | __h->__next_ = nullptr; |
||
2080 | return __h; |
||
2081 | } |
||
2082 | |||
2083 | #endif // _LIBCPP_HAS_NO_VARIADICS |
||
2084 | |||
2085 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2086 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder |
||
2087 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(value_type&& __v, |
||
2088 | size_t __hash) |
||
2089 | { |
||
2090 | __node_allocator& __na = __node_alloc(); |
||
2091 | __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); |
||
2092 | __node_traits::construct(__na, _VSTD::addressof(__h->__value_), _VSTD::move(__v)); |
||
2093 | __h.get_deleter().__value_constructed = true; |
||
2094 | __h->__hash_ = __hash; |
||
2095 | __h->__next_ = nullptr; |
||
2096 | return __h; |
||
2097 | } |
||
2098 | |||
2099 | #else // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
2100 | |||
2101 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2102 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder |
||
2103 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v) |
||
2104 | { |
||
2105 | __node_allocator& __na = __node_alloc(); |
||
2106 | __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); |
||
2107 | __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v); |
||
2108 | __h.get_deleter().__value_constructed = true; |
||
2109 | __h->__hash_ = hash_function()(__h->__value_); |
||
2110 | __h->__next_ = nullptr; |
||
2111 | return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03 |
||
2112 | } |
||
2113 | |||
2114 | #endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES |
||
2115 | |||
2116 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2117 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder |
||
2118 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__construct_node(const value_type& __v, |
||
2119 | size_t __hash) |
||
2120 | { |
||
2121 | __node_allocator& __na = __node_alloc(); |
||
2122 | __node_holder __h(__node_traits::allocate(__na, 1), _Dp(__na)); |
||
2123 | __node_traits::construct(__na, _VSTD::addressof(__h->__value_), __v); |
||
2124 | __h.get_deleter().__value_constructed = true; |
||
2125 | __h->__hash_ = __hash; |
||
2126 | __h->__next_ = nullptr; |
||
2127 | return _LIBCPP_EXPLICIT_MOVE(__h); // explicitly moved for C++03 |
||
2128 | } |
||
2129 | |||
2130 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2131 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator |
||
2132 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __p) |
||
2133 | { |
||
2134 | __node_pointer __np = __p.__node_; |
||
2135 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
2136 | _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__p) == this, |
||
2137 | "unordered container erase(iterator) called with an iterator not" |
||
2138 | " referring to this container"); |
||
2139 | _LIBCPP_ASSERT(__p != end(), |
||
2140 | "unordered container erase(iterator) called with a non-dereferenceable iterator"); |
||
2141 | iterator __r(__np, this); |
||
2142 | #else |
||
2143 | iterator __r(__np); |
||
2144 | #endif |
||
2145 | ++__r; |
||
2146 | remove(__p); |
||
2147 | return __r; |
||
2148 | } |
||
2149 | |||
2150 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2151 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator |
||
2152 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::erase(const_iterator __first, |
||
2153 | const_iterator __last) |
||
2154 | { |
||
2155 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
2156 | _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__first) == this, |
||
2157 | "unodered container::erase(iterator, iterator) called with an iterator not" |
||
2158 | " referring to this unodered container"); |
||
2159 | _LIBCPP_ASSERT(__get_const_db()->__find_c_from_i(&__last) == this, |
||
2160 | "unodered container::erase(iterator, iterator) called with an iterator not" |
||
2161 | " referring to this unodered container"); |
||
2162 | #endif |
||
2163 | for (const_iterator __p = __first; __first != __last; __p = __first) |
||
2164 | { |
||
2165 | ++__first; |
||
2166 | erase(__p); |
||
2167 | } |
||
2168 | __node_pointer __np = __last.__node_; |
||
2169 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
2170 | return iterator (__np, this); |
||
2171 | #else |
||
2172 | return iterator (__np); |
||
2173 | #endif |
||
2174 | } |
||
2175 | |||
2176 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2177 | template <class _Key> |
||
2178 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type |
||
2179 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_unique(const _Key& __k) |
||
2180 | { |
||
2181 | iterator __i = find(__k); |
||
2182 | if (__i == end()) |
||
2183 | return 0; |
||
2184 | erase(__i); |
||
2185 | return 1; |
||
2186 | } |
||
2187 | |||
2188 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2189 | template <class _Key> |
||
2190 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type |
||
2191 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__erase_multi(const _Key& __k) |
||
2192 | { |
||
2193 | size_type __r = 0; |
||
2194 | iterator __i = find(__k); |
||
2195 | if (__i != end()) |
||
2196 | { |
||
2197 | iterator __e = end(); |
||
2198 | do |
||
2199 | { |
||
2200 | erase(__i++); |
||
2201 | ++__r; |
||
2202 | } while (__i != __e && key_eq()(*__i, __k)); |
||
2203 | } |
||
2204 | return __r; |
||
2205 | } |
||
2206 | |||
2207 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2208 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::__node_holder |
||
2209 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::remove(const_iterator __p) _NOEXCEPT |
||
2210 | { |
||
2211 | // current node |
||
2212 | __node_pointer __cn = __p.__node_; |
||
2213 | size_type __bc = bucket_count(); |
||
2214 | size_t __chash = __constrain_hash(__cn->__hash_, __bc); |
||
2215 | // find previous node |
||
2216 | __node_pointer __pn = __bucket_list_[__chash]; |
||
2217 | for (; __pn->__next_ != __cn; __pn = __pn->__next_) |
||
2218 | ; |
||
2219 | // Fix up __bucket_list_ |
||
2220 | // if __pn is not in same bucket (before begin is not in same bucket) && |
||
2221 | // if __cn->__next_ is not in same bucket (nullptr is not in same bucket) |
||
2222 | if (__pn == static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())) |
||
2223 | || __constrain_hash(__pn->__hash_, __bc) != __chash) |
||
2224 | { |
||
2225 | if (__cn->__next_ == nullptr || __constrain_hash(__cn->__next_->__hash_, __bc) != __chash) |
||
2226 | __bucket_list_[__chash] = nullptr; |
||
2227 | } |
||
2228 | // if __cn->__next_ is not in same bucket (nullptr is in same bucket) |
||
2229 | if (__cn->__next_ != nullptr) |
||
2230 | { |
||
2231 | size_t __nhash = __constrain_hash(__cn->__next_->__hash_, __bc); |
||
2232 | if (__nhash != __chash) |
||
2233 | __bucket_list_[__nhash] = __pn; |
||
2234 | } |
||
2235 | // remove __cn |
||
2236 | __pn->__next_ = __cn->__next_; |
||
2237 | __cn->__next_ = nullptr; |
||
2238 | --size(); |
||
2239 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
2240 | __c_node* __c = __get_db()->__find_c_and_lock(this); |
||
2241 | for (__i_node** __p = __c->end_; __p != __c->beg_; ) |
||
2242 | { |
||
2243 | --__p; |
||
2244 | iterator* __i = static_cast<iterator*>((*__p)->__i_); |
||
2245 | if (__i->__node_ == __cn) |
||
2246 | { |
||
2247 | (*__p)->__c_ = nullptr; |
||
2248 | if (--__c->end_ != __p) |
||
2249 | memmove(__p, __p+1, (__c->end_ - __p)*sizeof(__i_node*)); |
||
2250 | } |
||
2251 | } |
||
2252 | __get_db()->unlock(); |
||
2253 | #endif |
||
2254 | return __node_holder(__cn, _Dp(__node_alloc(), true)); |
||
2255 | } |
||
2256 | |||
2257 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2258 | template <class _Key> |
||
2259 | inline _LIBCPP_INLINE_VISIBILITY |
||
2260 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type |
||
2261 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_unique(const _Key& __k) const |
||
2262 | { |
||
2263 | return static_cast<size_type>(find(__k) != end()); |
||
2264 | } |
||
2265 | |||
2266 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2267 | template <class _Key> |
||
2268 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type |
||
2269 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__count_multi(const _Key& __k) const |
||
2270 | { |
||
2271 | size_type __r = 0; |
||
2272 | const_iterator __i = find(__k); |
||
2273 | if (__i != end()) |
||
2274 | { |
||
2275 | const_iterator __e = end(); |
||
2276 | do |
||
2277 | { |
||
2278 | ++__i; |
||
2279 | ++__r; |
||
2280 | } while (__i != __e && key_eq()(*__i, __k)); |
||
2281 | } |
||
2282 | return __r; |
||
2283 | } |
||
2284 | |||
2285 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2286 | template <class _Key> |
||
2287 | pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, |
||
2288 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator> |
||
2289 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique( |
||
2290 | const _Key& __k) |
||
2291 | { |
||
2292 | iterator __i = find(__k); |
||
2293 | iterator __j = __i; |
||
2294 | if (__i != end()) |
||
2295 | ++__j; |
||
2296 | return pair<iterator, iterator>(__i, __j); |
||
2297 | } |
||
2298 | |||
2299 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2300 | template <class _Key> |
||
2301 | pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator, |
||
2302 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator> |
||
2303 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_unique( |
||
2304 | const _Key& __k) const |
||
2305 | { |
||
2306 | const_iterator __i = find(__k); |
||
2307 | const_iterator __j = __i; |
||
2308 | if (__i != end()) |
||
2309 | ++__j; |
||
2310 | return pair<const_iterator, const_iterator>(__i, __j); |
||
2311 | } |
||
2312 | |||
2313 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2314 | template <class _Key> |
||
2315 | pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator, |
||
2316 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::iterator> |
||
2317 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi( |
||
2318 | const _Key& __k) |
||
2319 | { |
||
2320 | iterator __i = find(__k); |
||
2321 | iterator __j = __i; |
||
2322 | if (__i != end()) |
||
2323 | { |
||
2324 | iterator __e = end(); |
||
2325 | do |
||
2326 | { |
||
2327 | ++__j; |
||
2328 | } while (__j != __e && key_eq()(*__j, __k)); |
||
2329 | } |
||
2330 | return pair<iterator, iterator>(__i, __j); |
||
2331 | } |
||
2332 | |||
2333 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2334 | template <class _Key> |
||
2335 | pair<typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator, |
||
2336 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::const_iterator> |
||
2337 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__equal_range_multi( |
||
2338 | const _Key& __k) const |
||
2339 | { |
||
2340 | const_iterator __i = find(__k); |
||
2341 | const_iterator __j = __i; |
||
2342 | if (__i != end()) |
||
2343 | { |
||
2344 | const_iterator __e = end(); |
||
2345 | do |
||
2346 | { |
||
2347 | ++__j; |
||
2348 | } while (__j != __e && key_eq()(*__j, __k)); |
||
2349 | } |
||
2350 | return pair<const_iterator, const_iterator>(__i, __j); |
||
2351 | } |
||
2352 | |||
2353 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2354 | void |
||
2355 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::swap(__hash_table& __u) |
||
2356 | #if _LIBCPP_STD_VER <= 11 |
||
2357 | _NOEXCEPT_( |
||
2358 | __is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value |
||
2359 | && (!allocator_traits<__pointer_allocator>::propagate_on_container_swap::value |
||
2360 | || __is_nothrow_swappable<__pointer_allocator>::value) |
||
2361 | && (!__node_traits::propagate_on_container_swap::value |
||
2362 | || __is_nothrow_swappable<__node_allocator>::value) |
||
2363 | ) |
||
2364 | #else |
||
2365 | _NOEXCEPT_(__is_nothrow_swappable<hasher>::value && __is_nothrow_swappable<key_equal>::value) |
||
2366 | #endif |
||
2367 | { |
||
2368 | { |
||
2369 | __node_pointer_pointer __npp = __bucket_list_.release(); |
||
2370 | __bucket_list_.reset(__u.__bucket_list_.release()); |
||
2371 | __u.__bucket_list_.reset(__npp); |
||
2372 | } |
||
2373 | _VSTD::swap(__bucket_list_.get_deleter().size(), __u.__bucket_list_.get_deleter().size()); |
||
2374 | __swap_allocator(__bucket_list_.get_deleter().__alloc(), |
||
2375 | __u.__bucket_list_.get_deleter().__alloc()); |
||
2376 | __swap_allocator(__node_alloc(), __u.__node_alloc()); |
||
2377 | _VSTD::swap(__p1_.first().__next_, __u.__p1_.first().__next_); |
||
2378 | __p2_.swap(__u.__p2_); |
||
2379 | __p3_.swap(__u.__p3_); |
||
2380 | if (size() > 0) |
||
2381 | __bucket_list_[__constrain_hash(__p1_.first().__next_->__hash_, bucket_count())] = |
||
2382 | static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__p1_.first())); |
||
2383 | if (__u.size() > 0) |
||
2384 | __u.__bucket_list_[__constrain_hash(__u.__p1_.first().__next_->__hash_, __u.bucket_count())] = |
||
2385 | static_cast<__node_pointer>(pointer_traits<__node_base_pointer>::pointer_to(__u.__p1_.first())); |
||
2386 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
2387 | __get_db()->swap(this, &__u); |
||
2388 | #endif |
||
2389 | } |
||
2390 | |||
2391 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2392 | typename __hash_table<_Tp, _Hash, _Equal, _Alloc>::size_type |
||
2393 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::bucket_size(size_type __n) const |
||
2394 | { |
||
2395 | _LIBCPP_ASSERT(__n < bucket_count(), |
||
2396 | "unordered container::bucket_size(n) called with n >= bucket_count()"); |
||
2397 | __node_const_pointer __np = __bucket_list_[__n]; |
||
2398 | size_type __bc = bucket_count(); |
||
2399 | size_type __r = 0; |
||
2400 | if (__np != nullptr) |
||
2401 | { |
||
2402 | for (__np = __np->__next_; __np != nullptr && |
||
2403 | __constrain_hash(__np->__hash_, __bc) == __n; |
||
2404 | __np = __np->__next_, ++__r) |
||
2405 | ; |
||
2406 | } |
||
2407 | return __r; |
||
2408 | } |
||
2409 | |||
2410 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2411 | inline _LIBCPP_INLINE_VISIBILITY |
||
2412 | void |
||
2413 | swap(__hash_table<_Tp, _Hash, _Equal, _Alloc>& __x, |
||
2414 | __hash_table<_Tp, _Hash, _Equal, _Alloc>& __y) |
||
2415 | _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) |
||
2416 | { |
||
2417 | __x.swap(__y); |
||
2418 | } |
||
2419 | |||
2420 | #if _LIBCPP_DEBUG_LEVEL >= 2 |
||
2421 | |||
2422 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2423 | bool |
||
2424 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__dereferenceable(const const_iterator* __i) const |
||
2425 | { |
||
2426 | return __i->__node_ != nullptr; |
||
2427 | } |
||
2428 | |||
2429 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2430 | bool |
||
2431 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__decrementable(const const_iterator*) const |
||
2432 | { |
||
2433 | return false; |
||
2434 | } |
||
2435 | |||
2436 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2437 | bool |
||
2438 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__addable(const const_iterator*, ptrdiff_t) const |
||
2439 | { |
||
2440 | return false; |
||
2441 | } |
||
2442 | |||
2443 | template <class _Tp, class _Hash, class _Equal, class _Alloc> |
||
2444 | bool |
||
2445 | __hash_table<_Tp, _Hash, _Equal, _Alloc>::__subscriptable(const const_iterator*, ptrdiff_t) const |
||
2446 | { |
||
2447 | return false; |
||
2448 | } |
||
2449 | |||
2450 | #endif // _LIBCPP_DEBUG_LEVEL >= 2 |
||
2451 | _LIBCPP_END_NAMESPACE_STD |
||
2452 | |||
2453 | #endif // _LIBCPP__HASH_TABLE |