1// Debugging unordered_set/unordered_multiset implementation -*- C++ -*- 2 3// Copyright (C) 2003-2022 Free Software Foundation, Inc. 4// 5// This file is part of the GNU ISO C++ Library. This library is free 6// software; you can redistribute it and/or modify it under the 7// terms of the GNU General Public License as published by the 8// Free Software Foundation; either version 3, or (at your option) 9// any later version. 10 11// This library is distributed in the hope that it will be useful, 12// but WITHOUT ANY WARRANTY; without even the implied warranty of 13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14// GNU General Public License for more details. 15 16// Under Section 7 of GPL version 3, you are granted additional 17// permissions described in the GCC Runtime Library Exception, version 18// 3.1, as published by the Free Software Foundation. 19 20// You should have received a copy of the GNU General Public License and 21// a copy of the GCC Runtime Library Exception along with this program; 22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23// <http://www.gnu.org/licenses/>. 24 25/** @file debug/unordered_set 26 * This file is a GNU debug extension to the Standard C++ Library. 27 */ 28 29#ifndef _GLIBCXX_DEBUG_UNORDERED_SET 30#define _GLIBCXX_DEBUG_UNORDERED_SET 1 31 32#pragma GCC system_header 33 34#if __cplusplus < 201103L 35# include <bits/c++0x_warning.h> 36#else 37# include <bits/c++config.h> 38namespace std _GLIBCXX_VISIBILITY(default) { namespace __debug { 39 template<typename _Key, typename _Hash, typename _Pred, typename _Allocator> 40 class unordered_set; 41 template<typename _Key, typename _Hash, typename _Pred, typename _Allocator> 42 class unordered_multiset; 43} } // namespace std::__debug 44# include <unordered_set> 45 46#include <debug/safe_unordered_container.h> 47#include <debug/safe_container.h> 48#include <debug/safe_iterator.h> 49#include <debug/safe_local_iterator.h> 50 51namespace std _GLIBCXX_VISIBILITY(default) 52{ 53namespace __debug 54{ 55 /// Class std::unordered_set with safety/checking/debug instrumentation. 56 template<typename _Value, 57 typename _Hash = std::hash<_Value>, 58 typename _Pred = std::equal_to<_Value>, 59 typename _Alloc = std::allocator<_Value> > 60 class unordered_set 61 : public __gnu_debug::_Safe_container< 62 unordered_set<_Value, _Hash, _Pred, _Alloc>, _Alloc, 63 __gnu_debug::_Safe_unordered_container>, 64 public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc> 65 { 66 typedef _GLIBCXX_STD_C::unordered_set< 67 _Value, _Hash, _Pred, _Alloc> _Base; 68 typedef __gnu_debug::_Safe_container< 69 unordered_set, _Alloc, __gnu_debug::_Safe_unordered_container> _Safe; 70 71 typedef typename _Base::const_iterator _Base_const_iterator; 72 typedef typename _Base::iterator _Base_iterator; 73 typedef typename _Base::const_local_iterator _Base_const_local_iterator; 74 typedef typename _Base::local_iterator _Base_local_iterator; 75 76 template<typename _ItT, typename _SeqT, typename _CatT> 77 friend class ::__gnu_debug::_Safe_iterator; 78 template<typename _ItT, typename _SeqT> 79 friend class ::__gnu_debug::_Safe_local_iterator; 80 81 // Reference wrapper for base class. See PR libstdc++/90102. 82 struct _Base_ref 83 { 84 _Base_ref(const _Base& __r) : _M_ref(__r) { } 85 86 const _Base& _M_ref; 87 }; 88 89 public: 90 typedef typename _Base::size_type size_type; 91 typedef typename _Base::difference_type difference_type; 92 typedef typename _Base::hasher hasher; 93 typedef typename _Base::key_equal key_equal; 94 typedef typename _Base::allocator_type allocator_type; 95 96 typedef typename _Base::key_type key_type; 97 typedef typename _Base::value_type value_type; 98 99 typedef typename _Base::pointer pointer; 100 typedef typename _Base::const_pointer const_pointer; 101 typedef typename _Base::reference reference; 102 typedef typename _Base::const_reference const_reference; 103 typedef __gnu_debug::_Safe_iterator< 104 _Base_iterator, unordered_set> iterator; 105 typedef __gnu_debug::_Safe_iterator< 106 _Base_const_iterator, unordered_set> const_iterator; 107 typedef __gnu_debug::_Safe_local_iterator< 108 _Base_local_iterator, unordered_set> local_iterator; 109 typedef __gnu_debug::_Safe_local_iterator< 110 _Base_const_local_iterator, unordered_set> const_local_iterator; 111 112 unordered_set() = default; 113 114 explicit 115 unordered_set(size_type __n, 116 const hasher& __hf = hasher(), 117 const key_equal& __eql = key_equal(), 118 const allocator_type& __a = allocator_type()) 119 : _Base(__n, __hf, __eql, __a) { } 120 121 template<typename _InputIterator> 122 unordered_set(_InputIterator __first, _InputIterator __last, 123 size_type __n = 0, 124 const hasher& __hf = hasher(), 125 const key_equal& __eql = key_equal(), 126 const allocator_type& __a = allocator_type()) 127 : _Base(__gnu_debug::__base( 128 __glibcxx_check_valid_constructor_range(__first, __last)), 129 __gnu_debug::__base(__last), __n, 130 __hf, __eql, __a) { } 131 132 unordered_set(const unordered_set&) = default; 133 134 unordered_set(_Base_ref __x) 135 : _Base(__x._M_ref) { } 136 137 unordered_set(unordered_set&&) = default; 138 139 explicit 140 unordered_set(const allocator_type& __a) 141 : _Base(__a) { } 142 143 unordered_set(const unordered_set& __uset, 144 const allocator_type& __a) 145 : _Base(__uset, __a) { } 146 147 unordered_set(unordered_set&& __uset, 148 const allocator_type& __a) 149 noexcept( noexcept(_Base(std::move(__uset), __a)) ) 150 : _Safe(std::move(__uset), __a), 151 _Base(std::move(__uset), __a) { } 152 153 unordered_set(initializer_list<value_type> __l, 154 size_type __n = 0, 155 const hasher& __hf = hasher(), 156 const key_equal& __eql = key_equal(), 157 const allocator_type& __a = allocator_type()) 158 : _Base(__l, __n, __hf, __eql, __a) { } 159 160 unordered_set(size_type __n, const allocator_type& __a) 161 : unordered_set(__n, hasher(), key_equal(), __a) 162 { } 163 164 unordered_set(size_type __n, const hasher& __hf, 165 const allocator_type& __a) 166 : unordered_set(__n, __hf, key_equal(), __a) 167 { } 168 169 template<typename _InputIterator> 170 unordered_set(_InputIterator __first, _InputIterator __last, 171 size_type __n, 172 const allocator_type& __a) 173 : unordered_set(__first, __last, __n, hasher(), key_equal(), __a) 174 { } 175 176 template<typename _InputIterator> 177 unordered_set(_InputIterator __first, _InputIterator __last, 178 size_type __n, const hasher& __hf, 179 const allocator_type& __a) 180 : unordered_set(__first, __last, __n, __hf, key_equal(), __a) 181 { } 182 183 unordered_set(initializer_list<value_type> __l, 184 size_type __n, 185 const allocator_type& __a) 186 : unordered_set(__l, __n, hasher(), key_equal(), __a) 187 { } 188 189 unordered_set(initializer_list<value_type> __l, 190 size_type __n, const hasher& __hf, 191 const allocator_type& __a) 192 : unordered_set(__l, __n, __hf, key_equal(), __a) 193 { } 194 195 ~unordered_set() = default; 196 197 unordered_set& 198 operator=(const unordered_set&) = default; 199 200 unordered_set& 201 operator=(unordered_set&&) = default; 202 203 unordered_set& 204 operator=(initializer_list<value_type> __l) 205 { 206 _Base::operator=(__l); 207 this->_M_invalidate_all(); 208 return *this; 209 } 210 211 using _Base::get_allocator; 212 using _Base::empty; 213 using _Base::size; 214 using _Base::max_size; 215 216 void 217 swap(unordered_set& __x) 218 noexcept( noexcept(declval<_Base&>().swap(__x)) ) 219 { 220 _Safe::_M_swap(__x); 221 _Base::swap(__x); 222 } 223 224 void 225 clear() noexcept 226 { 227 _Base::clear(); 228 this->_M_invalidate_all(); 229 } 230 231 iterator 232 begin() noexcept 233 { return { _Base::begin(), this }; } 234 235 const_iterator 236 begin() const noexcept 237 { return { _Base::begin(), this }; } 238 239 iterator 240 end() noexcept 241 { return { _Base::end(), this }; } 242 243 const_iterator 244 end() const noexcept 245 { return { _Base::end(), this }; } 246 247 const_iterator 248 cbegin() const noexcept 249 { return { _Base::cbegin(), this }; } 250 251 const_iterator 252 cend() const noexcept 253 { return { _Base::cend(), this }; } 254 255 // local versions 256 local_iterator 257 begin(size_type __b) 258 { 259 __glibcxx_check_bucket_index(__b); 260 return { _Base::begin(__b), this }; 261 } 262 263 local_iterator 264 end(size_type __b) 265 { 266 __glibcxx_check_bucket_index(__b); 267 return { _Base::end(__b), this }; 268 } 269 270 const_local_iterator 271 begin(size_type __b) const 272 { 273 __glibcxx_check_bucket_index(__b); 274 return { _Base::begin(__b), this }; 275 } 276 277 const_local_iterator 278 end(size_type __b) const 279 { 280 __glibcxx_check_bucket_index(__b); 281 return { _Base::end(__b), this }; 282 } 283 284 const_local_iterator 285 cbegin(size_type __b) const 286 { 287 __glibcxx_check_bucket_index(__b); 288 return { _Base::cbegin(__b), this }; 289 } 290 291 const_local_iterator 292 cend(size_type __b) const 293 { 294 __glibcxx_check_bucket_index(__b); 295 return { _Base::cend(__b), this }; 296 } 297 298 using _Base::bucket_count; 299 using _Base::max_bucket_count; 300 301 size_type 302 bucket_size(size_type __b) const 303 { 304 __glibcxx_check_bucket_index(__b); 305 return _Base::bucket_size(__b); 306 } 307 308 using _Base::bucket; 309 using _Base::load_factor; 310 311 float 312 max_load_factor() const noexcept 313 { return _Base::max_load_factor(); } 314 315 void 316 max_load_factor(float __f) 317 { 318 __glibcxx_check_max_load_factor(__f); 319 _Base::max_load_factor(__f); 320 } 321 322 using _Base::rehash; 323 using _Base::reserve; 324 325 template<typename... _Args> 326 std::pair<iterator, bool> 327 emplace(_Args&&... __args) 328 { 329 size_type __bucket_count = this->bucket_count(); 330 auto __res = _Base::emplace(std::forward<_Args>(__args)...); 331 _M_check_rehashed(__bucket_count); 332 return { { __res.first, this }, __res.second }; 333 } 334 335 template<typename... _Args> 336 iterator 337 emplace_hint(const_iterator __hint, _Args&&... __args) 338 { 339 __glibcxx_check_insert(__hint); 340 size_type __bucket_count = this->bucket_count(); 341 auto __it = _Base::emplace_hint(__hint.base(), 342 std::forward<_Args>(__args)...); 343 _M_check_rehashed(__bucket_count); 344 return { __it, this }; 345 } 346 347 std::pair<iterator, bool> 348 insert(const value_type& __obj) 349 { 350 size_type __bucket_count = this->bucket_count(); 351 auto __res = _Base::insert(__obj); 352 _M_check_rehashed(__bucket_count); 353 return { { __res.first, this }, __res.second }; 354 } 355 356 iterator 357 insert(const_iterator __hint, const value_type& __obj) 358 { 359 __glibcxx_check_insert(__hint); 360 size_type __bucket_count = this->bucket_count(); 361 auto __it = _Base::insert(__hint.base(), __obj); 362 _M_check_rehashed(__bucket_count); 363 return { __it, this }; 364 } 365 366 std::pair<iterator, bool> 367 insert(value_type&& __obj) 368 { 369 size_type __bucket_count = this->bucket_count(); 370 auto __res = _Base::insert(std::move(__obj)); 371 _M_check_rehashed(__bucket_count); 372 return { { __res.first, this }, __res.second }; 373 } 374 375 iterator 376 insert(const_iterator __hint, value_type&& __obj) 377 { 378 __glibcxx_check_insert(__hint); 379 size_type __bucket_count = this->bucket_count(); 380 auto __it = _Base::insert(__hint.base(), std::move(__obj)); 381 _M_check_rehashed(__bucket_count); 382 return { __it, this }; 383 } 384 385 void 386 insert(std::initializer_list<value_type> __l) 387 { 388 size_type __bucket_count = this->bucket_count(); 389 _Base::insert(__l); 390 _M_check_rehashed(__bucket_count); 391 } 392 393 template<typename _InputIterator> 394 void 395 insert(_InputIterator __first, _InputIterator __last) 396 { 397 typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist; 398 __glibcxx_check_valid_range2(__first, __last, __dist); 399 size_type __bucket_count = this->bucket_count(); 400 401 if (__dist.second >= __gnu_debug::__dp_sign) 402 _Base::insert(__gnu_debug::__unsafe(__first), 403 __gnu_debug::__unsafe(__last)); 404 else 405 _Base::insert(__first, __last); 406 407 _M_check_rehashed(__bucket_count); 408 } 409 410#if __cplusplus > 201402L 411 using node_type = typename _Base::node_type; 412 using insert_return_type = _Node_insert_return<iterator, node_type>; 413 414 node_type 415 extract(const_iterator __position) 416 { 417 __glibcxx_check_erase(__position); 418 return _M_extract(__position.base()); 419 } 420 421 node_type 422 extract(const key_type& __key) 423 { 424 const auto __position = _Base::find(__key); 425 if (__position != _Base::end()) 426 return _M_extract(__position); 427 return {}; 428 } 429 430 insert_return_type 431 insert(node_type&& __nh) 432 { 433 auto __ret = _Base::insert(std::move(__nh)); 434 return 435 { { __ret.position, this }, __ret.inserted, std::move(__ret.node) }; 436 } 437 438 iterator 439 insert(const_iterator __hint, node_type&& __nh) 440 { 441 __glibcxx_check_insert(__hint); 442 return { _Base::insert(__hint.base(), std::move(__nh)), this }; 443 } 444 445 template<typename _H2, typename _P2> 446 void 447 merge(unordered_set<_Value, _H2, _P2, _Alloc>& __source) 448 { 449 auto __guard 450 = _Safe::_S_uc_guard(std::__detail::_Identity{}, __source); 451 _Base::merge(__source); 452 } 453 454 template<typename _H2, typename _P2> 455 void 456 merge(unordered_set<_Value, _H2, _P2, _Alloc>&& __source) 457 { merge(__source); } 458 459 template<typename _H2, typename _P2> 460 void 461 merge(unordered_multiset<_Value, _H2, _P2, _Alloc>& __source) 462 { 463 auto __guard 464 = _Safe::_S_umc_guard(std::__detail::_Identity{}, __source); 465 _Base::merge(__source); 466 } 467 468 template<typename _H2, typename _P2> 469 void 470 merge(unordered_multiset<_Value, _H2, _P2, _Alloc>&& __source) 471 { merge(__source); } 472#endif // C++17 473 474 using _Base::hash_function; 475 using _Base::key_eq; 476 477 iterator 478 find(const key_type& __key) 479 { return { _Base::find(__key), this }; } 480 481#if __cplusplus > 201703L 482 template<typename _Kt, 483 typename = std::__has_is_transparent_t<_Hash, _Kt>, 484 typename = std::__has_is_transparent_t<_Pred, _Kt>> 485 iterator 486 find(const _Kt& __k) 487 { return { _Base::find(__k), this }; } 488#endif 489 490 const_iterator 491 find(const key_type& __key) const 492 { return { _Base::find(__key), this }; } 493 494#if __cplusplus > 201703L 495 template<typename _Kt, 496 typename = std::__has_is_transparent_t<_Hash, _Kt>, 497 typename = std::__has_is_transparent_t<_Pred, _Kt>> 498 const_iterator 499 find(const _Kt& __k) const 500 { return { _Base::find(__k), this }; } 501#endif 502 503 using _Base::count; 504 505#if __cplusplus > 201703L 506 using _Base::contains; 507#endif 508 509 std::pair<iterator, iterator> 510 equal_range(const key_type& __key) 511 { 512 auto __res = _Base::equal_range(__key); 513 return { { __res.first, this }, { __res.second, this } }; 514 } 515 516#if __cplusplus > 201703L 517 template<typename _Kt, 518 typename = std::__has_is_transparent_t<_Hash, _Kt>, 519 typename = std::__has_is_transparent_t<_Pred, _Kt>> 520 std::pair<iterator, iterator> 521 equal_range(const _Kt& __k) 522 { 523 auto __res = _Base::equal_range(__k); 524 return { { __res.first, this }, { __res.second, this } }; 525 } 526#endif 527 528 std::pair<const_iterator, const_iterator> 529 equal_range(const key_type& __key) const 530 { 531 auto __res = _Base::equal_range(__key); 532 return { { __res.first, this }, { __res.second, this } }; 533 } 534 535#if __cplusplus > 201703L 536 template<typename _Kt, 537 typename = std::__has_is_transparent_t<_Hash, _Kt>, 538 typename = std::__has_is_transparent_t<_Pred, _Kt>> 539 std::pair<const_iterator, const_iterator> 540 equal_range(const _Kt& __k) const 541 { 542 auto __res = _Base::equal_range(__k); 543 return { { __res.first, this }, { __res.second, this } }; 544 } 545#endif 546 547 size_type 548 erase(const key_type& __key) 549 { 550 size_type __ret(0); 551 auto __victim = _Base::find(__key); 552 if (__victim != _Base::end()) 553 { 554 _M_erase(__victim); 555 __ret = 1; 556 } 557 return __ret; 558 } 559 560 iterator 561 erase(const_iterator __it) 562 { 563 __glibcxx_check_erase(__it); 564 return { _M_erase(__it.base()), this }; 565 } 566 567 _Base_iterator 568 erase(_Base_const_iterator __it) 569 { 570 __glibcxx_check_erase2(__it); 571 return _M_erase(__it); 572 } 573 574 iterator 575 erase(iterator __it) 576 { 577 __glibcxx_check_erase(__it); 578 return { _M_erase(__it.base()), this }; 579 } 580 581 iterator 582 erase(const_iterator __first, const_iterator __last) 583 { 584 __glibcxx_check_erase_range(__first, __last); 585 for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp) 586 { 587 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(), 588 _M_message(__gnu_debug::__msg_valid_range) 589 ._M_iterator(__first, "first") 590 ._M_iterator(__last, "last")); 591 _M_invalidate(__tmp); 592 } 593 594 size_type __bucket_count = this->bucket_count(); 595 auto __next = _Base::erase(__first.base(), __last.base()); 596 _M_check_rehashed(__bucket_count); 597 return { __next, this }; 598 } 599 600 _Base& 601 _M_base() noexcept { return *this; } 602 603 const _Base& 604 _M_base() const noexcept { return *this; } 605 606 private: 607 void 608 _M_check_rehashed(size_type __prev_count) 609 { 610 if (__prev_count != this->bucket_count()) 611 this->_M_invalidate_all(); 612 } 613 614 void 615 _M_invalidate(_Base_const_iterator __victim) 616 { 617 this->_M_invalidate_if( 618 [__victim](_Base_const_iterator __it) { return __it == __victim; }); 619 this->_M_invalidate_local_if( 620 [__victim](_Base_const_local_iterator __it) 621 { return __it == __victim; }); 622 } 623 624 _Base_iterator 625 _M_erase(_Base_const_iterator __victim) 626 { 627 _M_invalidate(__victim); 628 size_type __bucket_count = this->bucket_count(); 629 _Base_iterator __next = _Base::erase(__victim); 630 _M_check_rehashed(__bucket_count); 631 return __next; 632 } 633 634#if __cplusplus > 201402L 635 node_type 636 _M_extract(_Base_const_iterator __victim) 637 { 638 _M_invalidate(__victim); 639 return _Base::extract(__victim); 640 } 641#endif 642 }; 643 644#if __cpp_deduction_guides >= 201606 645 646 template<typename _InputIterator, 647 typename _Hash = 648 hash<typename iterator_traits<_InputIterator>::value_type>, 649 typename _Pred = 650 equal_to<typename iterator_traits<_InputIterator>::value_type>, 651 typename _Allocator = 652 allocator<typename iterator_traits<_InputIterator>::value_type>, 653 typename = _RequireInputIter<_InputIterator>, 654 typename = _RequireNotAllocatorOrIntegral<_Hash>, 655 typename = _RequireNotAllocator<_Pred>, 656 typename = _RequireAllocator<_Allocator>> 657 unordered_set(_InputIterator, _InputIterator, 658 unordered_set<int>::size_type = {}, 659 _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) 660 -> unordered_set<typename iterator_traits<_InputIterator>::value_type, 661 _Hash, _Pred, _Allocator>; 662 663 template<typename _Tp, typename _Hash = hash<_Tp>, 664 typename _Pred = equal_to<_Tp>, 665 typename _Allocator = allocator<_Tp>, 666 typename = _RequireNotAllocatorOrIntegral<_Hash>, 667 typename = _RequireNotAllocator<_Pred>, 668 typename = _RequireAllocator<_Allocator>> 669 unordered_set(initializer_list<_Tp>, 670 unordered_set<int>::size_type = {}, 671 _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) 672 -> unordered_set<_Tp, _Hash, _Pred, _Allocator>; 673 674 template<typename _InputIterator, typename _Allocator, 675 typename = _RequireInputIter<_InputIterator>, 676 typename = _RequireAllocator<_Allocator>> 677 unordered_set(_InputIterator, _InputIterator, 678 unordered_set<int>::size_type, _Allocator) 679 -> unordered_set<typename iterator_traits<_InputIterator>::value_type, 680 hash< 681 typename iterator_traits<_InputIterator>::value_type>, 682 equal_to< 683 typename iterator_traits<_InputIterator>::value_type>, 684 _Allocator>; 685 686 template<typename _InputIterator, typename _Hash, typename _Allocator, 687 typename = _RequireInputIter<_InputIterator>, 688 typename = _RequireNotAllocatorOrIntegral<_Hash>, 689 typename = _RequireAllocator<_Allocator>> 690 unordered_set(_InputIterator, _InputIterator, 691 unordered_set<int>::size_type, 692 _Hash, _Allocator) 693 -> unordered_set<typename iterator_traits<_InputIterator>::value_type, 694 _Hash, 695 equal_to< 696 typename iterator_traits<_InputIterator>::value_type>, 697 _Allocator>; 698 699 template<typename _Tp, typename _Allocator, 700 typename = _RequireAllocator<_Allocator>> 701 unordered_set(initializer_list<_Tp>, 702 unordered_set<int>::size_type, _Allocator) 703 -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; 704 705 template<typename _Tp, typename _Hash, typename _Allocator, 706 typename = _RequireNotAllocatorOrIntegral<_Hash>, 707 typename = _RequireAllocator<_Allocator>> 708 unordered_set(initializer_list<_Tp>, 709 unordered_set<int>::size_type, _Hash, _Allocator) 710 -> unordered_set<_Tp, _Hash, equal_to<_Tp>, _Allocator>; 711 712#endif 713 714 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 715 inline void 716 swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, 717 unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) 718 noexcept(noexcept(__x.swap(__y))) 719 { __x.swap(__y); } 720 721 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 722 inline bool 723 operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, 724 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) 725 { return __x._M_base() == __y._M_base(); } 726 727#if __cpp_impl_three_way_comparison < 201907L 728 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 729 inline bool 730 operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, 731 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) 732 { return !(__x == __y); } 733#endif 734 735 /// Class std::unordered_multiset with safety/checking/debug instrumentation. 736 template<typename _Value, 737 typename _Hash = std::hash<_Value>, 738 typename _Pred = std::equal_to<_Value>, 739 typename _Alloc = std::allocator<_Value> > 740 class unordered_multiset 741 : public __gnu_debug::_Safe_container< 742 unordered_multiset<_Value, _Hash, _Pred, _Alloc>, _Alloc, 743 __gnu_debug::_Safe_unordered_container>, 744 public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc> 745 { 746 typedef _GLIBCXX_STD_C::unordered_multiset< 747 _Value, _Hash, _Pred, _Alloc> _Base; 748 typedef __gnu_debug::_Safe_container<unordered_multiset, 749 _Alloc, __gnu_debug::_Safe_unordered_container> _Safe; 750 typedef typename _Base::const_iterator _Base_const_iterator; 751 typedef typename _Base::iterator _Base_iterator; 752 typedef typename _Base::const_local_iterator 753 _Base_const_local_iterator; 754 typedef typename _Base::local_iterator _Base_local_iterator; 755 756 template<typename _ItT, typename _SeqT, typename _CatT> 757 friend class ::__gnu_debug::_Safe_iterator; 758 template<typename _ItT, typename _SeqT> 759 friend class ::__gnu_debug::_Safe_local_iterator; 760 761 // Reference wrapper for base class. See PR libstdc++/90102. 762 struct _Base_ref 763 { 764 _Base_ref(const _Base& __r) : _M_ref(__r) { } 765 766 const _Base& _M_ref; 767 }; 768 769 public: 770 typedef typename _Base::size_type size_type; 771 typedef typename _Base::difference_type difference_type; 772 typedef typename _Base::hasher hasher; 773 typedef typename _Base::key_equal key_equal; 774 typedef typename _Base::allocator_type allocator_type; 775 776 typedef typename _Base::key_type key_type; 777 typedef typename _Base::value_type value_type; 778 779 typedef typename _Base::pointer pointer; 780 typedef typename _Base::const_pointer const_pointer; 781 typedef typename _Base::reference reference; 782 typedef typename _Base::const_reference const_reference; 783 typedef __gnu_debug::_Safe_iterator< 784 _Base_iterator, unordered_multiset> iterator; 785 typedef __gnu_debug::_Safe_iterator< 786 _Base_const_iterator, unordered_multiset> const_iterator; 787 typedef __gnu_debug::_Safe_local_iterator< 788 _Base_local_iterator, unordered_multiset> local_iterator; 789 typedef __gnu_debug::_Safe_local_iterator< 790 _Base_const_local_iterator, unordered_multiset> const_local_iterator; 791 792 unordered_multiset() = default; 793 794 explicit 795 unordered_multiset(size_type __n, 796 const hasher& __hf = hasher(), 797 const key_equal& __eql = key_equal(), 798 const allocator_type& __a = allocator_type()) 799 : _Base(__n, __hf, __eql, __a) { } 800 801 template<typename _InputIterator> 802 unordered_multiset(_InputIterator __first, _InputIterator __last, 803 size_type __n = 0, 804 const hasher& __hf = hasher(), 805 const key_equal& __eql = key_equal(), 806 const allocator_type& __a = allocator_type()) 807 : _Base(__gnu_debug::__base( 808 __glibcxx_check_valid_constructor_range(__first, __last)), 809 __gnu_debug::__base(__last), __n, 810 __hf, __eql, __a) { } 811 812 unordered_multiset(const unordered_multiset&) = default; 813 814 unordered_multiset(_Base_ref __x) 815 : _Base(__x._M_ref) { } 816 817 unordered_multiset(unordered_multiset&&) = default; 818 819 explicit 820 unordered_multiset(const allocator_type& __a) 821 : _Base(__a) { } 822 823 unordered_multiset(const unordered_multiset& __uset, 824 const allocator_type& __a) 825 : _Base(__uset, __a) { } 826 827 unordered_multiset(unordered_multiset&& __uset, 828 const allocator_type& __a) 829 noexcept( noexcept(_Base(std::move(__uset), __a)) ) 830 : _Safe(std::move(__uset), __a), 831 _Base(std::move(__uset), __a) { } 832 833 unordered_multiset(initializer_list<value_type> __l, 834 size_type __n = 0, 835 const hasher& __hf = hasher(), 836 const key_equal& __eql = key_equal(), 837 const allocator_type& __a = allocator_type()) 838 : _Base(__l, __n, __hf, __eql, __a) { } 839 840 unordered_multiset(size_type __n, const allocator_type& __a) 841 : unordered_multiset(__n, hasher(), key_equal(), __a) 842 { } 843 844 unordered_multiset(size_type __n, const hasher& __hf, 845 const allocator_type& __a) 846 : unordered_multiset(__n, __hf, key_equal(), __a) 847 { } 848 849 template<typename _InputIterator> 850 unordered_multiset(_InputIterator __first, _InputIterator __last, 851 size_type __n, 852 const allocator_type& __a) 853 : unordered_multiset(__first, __last, __n, hasher(), key_equal(), __a) 854 { } 855 856 template<typename _InputIterator> 857 unordered_multiset(_InputIterator __first, _InputIterator __last, 858 size_type __n, const hasher& __hf, 859 const allocator_type& __a) 860 : unordered_multiset(__first, __last, __n, __hf, key_equal(), __a) 861 { } 862 863 unordered_multiset(initializer_list<value_type> __l, 864 size_type __n, 865 const allocator_type& __a) 866 : unordered_multiset(__l, __n, hasher(), key_equal(), __a) 867 { } 868 869 unordered_multiset(initializer_list<value_type> __l, 870 size_type __n, const hasher& __hf, 871 const allocator_type& __a) 872 : unordered_multiset(__l, __n, __hf, key_equal(), __a) 873 { } 874 875 ~unordered_multiset() = default; 876 877 unordered_multiset& 878 operator=(const unordered_multiset&) = default; 879 880 unordered_multiset& 881 operator=(unordered_multiset&&) = default; 882 883 unordered_multiset& 884 operator=(initializer_list<value_type> __l) 885 { 886 _Base::operator=(__l); 887 this->_M_invalidate_all(); 888 return *this; 889 } 890 891 using _Base::get_allocator; 892 using _Base::empty; 893 using _Base::size; 894 using _Base::max_size; 895 896 void 897 swap(unordered_multiset& __x) 898 noexcept( noexcept(declval<_Base&>().swap(__x)) ) 899 { 900 _Safe::_M_swap(__x); 901 _Base::swap(__x); 902 } 903 904 void 905 clear() noexcept 906 { 907 _Base::clear(); 908 this->_M_invalidate_all(); 909 } 910 911 iterator 912 begin() noexcept 913 { return { _Base::begin(), this }; } 914 915 const_iterator 916 begin() const noexcept 917 { return { _Base::begin(), this }; } 918 919 iterator 920 end() noexcept 921 { return { _Base::end(), this }; } 922 923 const_iterator 924 end() const noexcept 925 { return { _Base::end(), this }; } 926 927 const_iterator 928 cbegin() const noexcept 929 { return { _Base::cbegin(), this }; } 930 931 const_iterator 932 cend() const noexcept 933 { return { _Base::cend(), this }; } 934 935 // local versions 936 local_iterator 937 begin(size_type __b) 938 { 939 __glibcxx_check_bucket_index(__b); 940 return { _Base::begin(__b), this }; 941 } 942 943 local_iterator 944 end(size_type __b) 945 { 946 __glibcxx_check_bucket_index(__b); 947 return { _Base::end(__b), this }; 948 } 949 950 const_local_iterator 951 begin(size_type __b) const 952 { 953 __glibcxx_check_bucket_index(__b); 954 return { _Base::begin(__b), this }; 955 } 956 957 const_local_iterator 958 end(size_type __b) const 959 { 960 __glibcxx_check_bucket_index(__b); 961 return { _Base::end(__b), this }; 962 } 963 964 const_local_iterator 965 cbegin(size_type __b) const 966 { 967 __glibcxx_check_bucket_index(__b); 968 return { _Base::cbegin(__b), this }; 969 } 970 971 const_local_iterator 972 cend(size_type __b) const 973 { 974 __glibcxx_check_bucket_index(__b); 975 return { _Base::cend(__b), this }; 976 } 977 978 using _Base::bucket_count; 979 using _Base::max_bucket_count; 980 981 size_type 982 bucket_size(size_type __b) const 983 { 984 __glibcxx_check_bucket_index(__b); 985 return _Base::bucket_size(__b); 986 } 987 988 using _Base::bucket; 989 using _Base::load_factor; 990 991 float 992 max_load_factor() const noexcept 993 { return _Base::max_load_factor(); } 994 995 void 996 max_load_factor(float __f) 997 { 998 __glibcxx_check_max_load_factor(__f); 999 _Base::max_load_factor(__f); 1000 } 1001 1002 using _Base::rehash; 1003 using _Base::reserve; 1004 1005 template<typename... _Args> 1006 iterator 1007 emplace(_Args&&... __args) 1008 { 1009 size_type __bucket_count = this->bucket_count(); 1010 auto __it = _Base::emplace(std::forward<_Args>(__args)...); 1011 _M_check_rehashed(__bucket_count); 1012 return { __it, this }; 1013 } 1014 1015 template<typename... _Args> 1016 iterator 1017 emplace_hint(const_iterator __hint, _Args&&... __args) 1018 { 1019 __glibcxx_check_insert(__hint); 1020 size_type __bucket_count = this->bucket_count(); 1021 auto __it = _Base::emplace_hint(__hint.base(), 1022 std::forward<_Args>(__args)...); 1023 _M_check_rehashed(__bucket_count); 1024 return { __it, this }; 1025 } 1026 1027 iterator 1028 insert(const value_type& __obj) 1029 { 1030 size_type __bucket_count = this->bucket_count(); 1031 auto __it = _Base::insert(__obj); 1032 _M_check_rehashed(__bucket_count); 1033 return { __it, this }; 1034 } 1035 1036 iterator 1037 insert(const_iterator __hint, const value_type& __obj) 1038 { 1039 __glibcxx_check_insert(__hint); 1040 size_type __bucket_count = this->bucket_count(); 1041 auto __it = _Base::insert(__hint.base(), __obj); 1042 _M_check_rehashed(__bucket_count); 1043 return { __it, this }; 1044 } 1045 1046 iterator 1047 insert(value_type&& __obj) 1048 { 1049 size_type __bucket_count = this->bucket_count(); 1050 auto __it = _Base::insert(std::move(__obj)); 1051 _M_check_rehashed(__bucket_count); 1052 return { __it, this }; 1053 } 1054 1055 iterator 1056 insert(const_iterator __hint, value_type&& __obj) 1057 { 1058 __glibcxx_check_insert(__hint); 1059 size_type __bucket_count = this->bucket_count(); 1060 auto __it = _Base::insert(__hint.base(), std::move(__obj)); 1061 _M_check_rehashed(__bucket_count); 1062 return { __it, this }; 1063 } 1064 1065 void 1066 insert(std::initializer_list<value_type> __l) 1067 { 1068 size_type __bucket_count = this->bucket_count(); 1069 _Base::insert(__l); 1070 _M_check_rehashed(__bucket_count); 1071 } 1072 1073 template<typename _InputIterator> 1074 void 1075 insert(_InputIterator __first, _InputIterator __last) 1076 { 1077 typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist; 1078 __glibcxx_check_valid_range2(__first, __last, __dist); 1079 size_type __bucket_count = this->bucket_count(); 1080 1081 if (__dist.second >= __gnu_debug::__dp_sign) 1082 _Base::insert(__gnu_debug::__unsafe(__first), 1083 __gnu_debug::__unsafe(__last)); 1084 else 1085 _Base::insert(__first, __last); 1086 1087 _M_check_rehashed(__bucket_count); 1088 } 1089 1090#if __cplusplus > 201402L 1091 using node_type = typename _Base::node_type; 1092 1093 node_type 1094 extract(const_iterator __position) 1095 { 1096 __glibcxx_check_erase(__position); 1097 return _M_extract(__position.base()); 1098 } 1099 1100 node_type 1101 extract(const key_type& __key) 1102 { 1103 const auto __position = _Base::find(__key); 1104 if (__position != _Base::end()) 1105 return _M_extract(__position); 1106 return {}; 1107 } 1108 1109 iterator 1110 insert(node_type&& __nh) 1111 { return { _Base::insert(std::move(__nh)), this }; } 1112 1113 iterator 1114 insert(const_iterator __hint, node_type&& __nh) 1115 { 1116 __glibcxx_check_insert(__hint); 1117 return { _Base::insert(__hint.base(), std::move(__nh)), this }; 1118 } 1119 1120 template<typename _H2, typename _P2> 1121 void 1122 merge(unordered_multiset<_Value, _H2, _P2, _Alloc>& __source) 1123 { 1124 auto __guard 1125 = _Safe::_S_umc_guard(std::__detail::_Identity{}, __source); 1126 _Base::merge(__source); 1127 } 1128 1129 template<typename _H2, typename _P2> 1130 void 1131 merge(unordered_multiset<_Value, _H2, _P2, _Alloc>&& __source) 1132 { merge(__source); } 1133 1134 template<typename _H2, typename _P2> 1135 void 1136 merge(unordered_set<_Value, _H2, _P2, _Alloc>& __source) 1137 { 1138 auto __guard 1139 = _Safe::_S_uc_guard(std::__detail::_Identity{}, __source); 1140 _Base::merge(__source); 1141 } 1142 1143 template<typename _H2, typename _P2> 1144 void 1145 merge(unordered_set<_Value, _H2, _P2, _Alloc>&& __source) 1146 { merge(__source); } 1147#endif // C++17 1148 1149 using _Base::hash_function; 1150 using _Base::key_eq; 1151 1152 iterator 1153 find(const key_type& __key) 1154 { return { _Base::find(__key), this }; } 1155 1156#if __cplusplus > 201703L 1157 template<typename _Kt, 1158 typename = std::__has_is_transparent_t<_Hash, _Kt>, 1159 typename = std::__has_is_transparent_t<_Pred, _Kt>> 1160 iterator 1161 find(const _Kt& __k) 1162 { return { _Base::find(__k), this }; } 1163#endif 1164 1165 const_iterator 1166 find(const key_type& __key) const 1167 { return { _Base::find(__key), this }; } 1168 1169#if __cplusplus > 201703L 1170 template<typename _Kt, 1171 typename = std::__has_is_transparent_t<_Hash, _Kt>, 1172 typename = std::__has_is_transparent_t<_Pred, _Kt>> 1173 const_iterator 1174 find(const _Kt& __k) const 1175 { return { _Base::find(__k), this }; } 1176#endif 1177 1178 using _Base::count; 1179 1180#if __cplusplus > 201703L 1181 using _Base::contains; 1182#endif 1183 1184 std::pair<iterator, iterator> 1185 equal_range(const key_type& __key) 1186 { 1187 auto __res = _Base::equal_range(__key); 1188 return { { __res.first, this }, { __res.second, this } }; 1189 } 1190 1191#if __cplusplus > 201703L 1192 template<typename _Kt, 1193 typename = std::__has_is_transparent_t<_Hash, _Kt>, 1194 typename = std::__has_is_transparent_t<_Pred, _Kt>> 1195 std::pair<iterator, iterator> 1196 equal_range(const _Kt& __k) 1197 { 1198 auto __res = _Base::equal_range(__k); 1199 return { { __res.first, this }, { __res.second, this } }; 1200 } 1201#endif 1202 1203 std::pair<const_iterator, const_iterator> 1204 equal_range(const key_type& __key) const 1205 { 1206 auto __res = _Base::equal_range(__key); 1207 return { { __res.first, this }, { __res.second, this } }; 1208 } 1209 1210#if __cplusplus > 201703L 1211 template<typename _Kt, 1212 typename = std::__has_is_transparent_t<_Hash, _Kt>, 1213 typename = std::__has_is_transparent_t<_Pred, _Kt>> 1214 std::pair<const_iterator, const_iterator> 1215 equal_range(const _Kt& __k) const 1216 { 1217 auto __res = _Base::equal_range(__k); 1218 return { { __res.first, this }, { __res.second, this } }; 1219 } 1220#endif 1221 1222 size_type 1223 erase(const key_type& __key) 1224 { 1225 size_type __ret(0); 1226 auto __pair = _Base::equal_range(__key); 1227 for (auto __victim = __pair.first; __victim != __pair.second;) 1228 { 1229 _M_invalidate(__victim); 1230 __victim = _Base::erase(__victim); 1231 ++__ret; 1232 } 1233 1234 return __ret; 1235 } 1236 1237 iterator 1238 erase(const_iterator __it) 1239 { 1240 __glibcxx_check_erase(__it); 1241 return { _M_erase(__it.base()), this }; 1242 } 1243 1244 _Base_iterator 1245 erase(_Base_const_iterator __it) 1246 { 1247 __glibcxx_check_erase2(__it); 1248 return _M_erase(__it); 1249 } 1250 1251 iterator 1252 erase(iterator __it) 1253 { 1254 __glibcxx_check_erase(__it); 1255 return { _M_erase(__it.base()), this }; 1256 } 1257 1258 iterator 1259 erase(const_iterator __first, const_iterator __last) 1260 { 1261 __glibcxx_check_erase_range(__first, __last); 1262 for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp) 1263 { 1264 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(), 1265 _M_message(__gnu_debug::__msg_valid_range) 1266 ._M_iterator(__first, "first") 1267 ._M_iterator(__last, "last")); 1268 _M_invalidate(__tmp); 1269 } 1270 return { _Base::erase(__first.base(), __last.base()), this }; 1271 } 1272 1273 _Base& 1274 _M_base() noexcept { return *this; } 1275 1276 const _Base& 1277 _M_base() const noexcept { return *this; } 1278 1279 private: 1280 void 1281 _M_check_rehashed(size_type __prev_count) 1282 { 1283 if (__prev_count != this->bucket_count()) 1284 this->_M_invalidate_all(); 1285 } 1286 1287 void 1288 _M_invalidate(_Base_const_iterator __victim) 1289 { 1290 this->_M_invalidate_if( 1291 [__victim](_Base_const_iterator __it) { return __it == __victim; }); 1292 this->_M_invalidate_local_if( 1293 [__victim](_Base_const_local_iterator __it) 1294 { return __it == __victim; }); 1295 } 1296 1297 _Base_iterator 1298 _M_erase(_Base_const_iterator __victim) 1299 { 1300 _M_invalidate(__victim); 1301 size_type __bucket_count = this->bucket_count(); 1302 _Base_iterator __next = _Base::erase(__victim); 1303 _M_check_rehashed(__bucket_count); 1304 return __next; 1305 } 1306 1307#if __cplusplus > 201402L 1308 node_type 1309 _M_extract(_Base_const_iterator __victim) 1310 { 1311 _M_invalidate(__victim); 1312 return _Base::extract(__victim); 1313 } 1314#endif 1315 }; 1316 1317#if __cpp_deduction_guides >= 201606 1318 1319 template<typename _InputIterator, 1320 typename _Hash = 1321 hash<typename iterator_traits<_InputIterator>::value_type>, 1322 typename _Pred = 1323 equal_to<typename iterator_traits<_InputIterator>::value_type>, 1324 typename _Allocator = 1325 allocator<typename iterator_traits<_InputIterator>::value_type>, 1326 typename = _RequireInputIter<_InputIterator>, 1327 typename = _RequireNotAllocatorOrIntegral<_Hash>, 1328 typename = _RequireNotAllocator<_Pred>, 1329 typename = _RequireAllocator<_Allocator>> 1330 unordered_multiset(_InputIterator, _InputIterator, 1331 unordered_multiset<int>::size_type = {}, 1332 _Hash = _Hash(), _Pred = _Pred(), 1333 _Allocator = _Allocator()) 1334 -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type, 1335 _Hash, _Pred, _Allocator>; 1336 1337 template<typename _Tp, typename _Hash = hash<_Tp>, 1338 typename _Pred = equal_to<_Tp>, 1339 typename _Allocator = allocator<_Tp>, 1340 typename = _RequireNotAllocatorOrIntegral<_Hash>, 1341 typename = _RequireNotAllocator<_Pred>, 1342 typename = _RequireAllocator<_Allocator>> 1343 unordered_multiset(initializer_list<_Tp>, 1344 unordered_multiset<int>::size_type = {}, 1345 _Hash = _Hash(), _Pred = _Pred(), 1346 _Allocator = _Allocator()) 1347 -> unordered_multiset<_Tp, _Hash, _Pred, _Allocator>; 1348 1349 template<typename _InputIterator, typename _Allocator, 1350 typename = _RequireInputIter<_InputIterator>, 1351 typename = _RequireAllocator<_Allocator>> 1352 unordered_multiset(_InputIterator, _InputIterator, 1353 unordered_multiset<int>::size_type, _Allocator) 1354 -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type, 1355 hash<typename 1356 iterator_traits<_InputIterator>::value_type>, 1357 equal_to<typename 1358 iterator_traits<_InputIterator>::value_type>, 1359 _Allocator>; 1360 1361 template<typename _InputIterator, typename _Hash, typename _Allocator, 1362 typename = _RequireInputIter<_InputIterator>, 1363 typename = _RequireNotAllocatorOrIntegral<_Hash>, 1364 typename = _RequireAllocator<_Allocator>> 1365 unordered_multiset(_InputIterator, _InputIterator, 1366 unordered_multiset<int>::size_type, 1367 _Hash, _Allocator) 1368 -> unordered_multiset<typename 1369 iterator_traits<_InputIterator>::value_type, 1370 _Hash, 1371 equal_to< 1372 typename 1373 iterator_traits<_InputIterator>::value_type>, 1374 _Allocator>; 1375 1376 template<typename _Tp, typename _Allocator, 1377 typename = _RequireAllocator<_Allocator>> 1378 unordered_multiset(initializer_list<_Tp>, 1379 unordered_multiset<int>::size_type, _Allocator) 1380 -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; 1381 1382 template<typename _Tp, typename _Hash, typename _Allocator, 1383 typename = _RequireNotAllocatorOrIntegral<_Hash>, 1384 typename = _RequireAllocator<_Allocator>> 1385 unordered_multiset(initializer_list<_Tp>, 1386 unordered_multiset<int>::size_type, _Hash, _Allocator) 1387 -> unordered_multiset<_Tp, _Hash, equal_to<_Tp>, _Allocator>; 1388 1389#endif 1390 1391 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 1392 inline void 1393 swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, 1394 unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) 1395 noexcept(noexcept(__x.swap(__y))) 1396 { __x.swap(__y); } 1397 1398 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 1399 inline bool 1400 operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, 1401 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) 1402 { return __x._M_base() == __y._M_base(); } 1403 1404#if __cpp_impl_three_way_comparison < 201907L 1405 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 1406 inline bool 1407 operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, 1408 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) 1409 { return !(__x == __y); } 1410#endif 1411 1412} // namespace __debug 1413} // namespace std 1414 1415#endif // C++11 1416 1417#endif 1418