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