1// Debugging unordered_set/unordered_multiset implementation -*- C++ -*- 2 3// Copyright (C) 2003-2020 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 public: 82 typedef typename _Base::size_type size_type; 83 typedef typename _Base::hasher hasher; 84 typedef typename _Base::key_equal key_equal; 85 typedef typename _Base::allocator_type allocator_type; 86 87 typedef typename _Base::key_type key_type; 88 typedef typename _Base::value_type value_type; 89 90 typedef __gnu_debug::_Safe_iterator< 91 _Base_iterator, unordered_set> iterator; 92 typedef __gnu_debug::_Safe_iterator< 93 _Base_const_iterator, unordered_set> const_iterator; 94 typedef __gnu_debug::_Safe_local_iterator< 95 _Base_local_iterator, unordered_set> local_iterator; 96 typedef __gnu_debug::_Safe_local_iterator< 97 _Base_const_local_iterator, unordered_set> const_local_iterator; 98 99 unordered_set() = default; 100 101 explicit 102 unordered_set(size_type __n, 103 const hasher& __hf = hasher(), 104 const key_equal& __eql = key_equal(), 105 const allocator_type& __a = allocator_type()) 106 : _Base(__n, __hf, __eql, __a) { } 107 108 template<typename _InputIterator> 109 unordered_set(_InputIterator __first, _InputIterator __last, 110 size_type __n = 0, 111 const hasher& __hf = hasher(), 112 const key_equal& __eql = key_equal(), 113 const allocator_type& __a = allocator_type()) 114 : _Base(__gnu_debug::__base( 115 __glibcxx_check_valid_constructor_range(__first, __last)), 116 __gnu_debug::__base(__last), __n, 117 __hf, __eql, __a) { } 118 119 unordered_set(const unordered_set&) = default; 120 121 unordered_set(const _Base& __x) 122 : _Base(__x) { } 123 124 unordered_set(unordered_set&&) = default; 125 126 explicit 127 unordered_set(const allocator_type& __a) 128 : _Base(__a) { } 129 130 unordered_set(const unordered_set& __uset, 131 const allocator_type& __a) 132 : _Base(__uset, __a) { } 133 134 unordered_set(unordered_set&& __uset, 135 const allocator_type& __a) 136 noexcept( noexcept(_Base(std::move(__uset._M_base()), __a)) ) 137 : _Safe(std::move(__uset._M_safe()), __a), 138 _Base(std::move(__uset._M_base()), __a) { } 139 140 unordered_set(initializer_list<value_type> __l, 141 size_type __n = 0, 142 const hasher& __hf = hasher(), 143 const key_equal& __eql = key_equal(), 144 const allocator_type& __a = allocator_type()) 145 : _Base(__l, __n, __hf, __eql, __a) { } 146 147 unordered_set(size_type __n, const allocator_type& __a) 148 : unordered_set(__n, hasher(), key_equal(), __a) 149 { } 150 151 unordered_set(size_type __n, const hasher& __hf, 152 const allocator_type& __a) 153 : unordered_set(__n, __hf, key_equal(), __a) 154 { } 155 156 template<typename _InputIterator> 157 unordered_set(_InputIterator __first, _InputIterator __last, 158 size_type __n, 159 const allocator_type& __a) 160 : unordered_set(__first, __last, __n, hasher(), key_equal(), __a) 161 { } 162 163 template<typename _InputIterator> 164 unordered_set(_InputIterator __first, _InputIterator __last, 165 size_type __n, const hasher& __hf, 166 const allocator_type& __a) 167 : unordered_set(__first, __last, __n, __hf, key_equal(), __a) 168 { } 169 170 unordered_set(initializer_list<value_type> __l, 171 size_type __n, 172 const allocator_type& __a) 173 : unordered_set(__l, __n, hasher(), key_equal(), __a) 174 { } 175 176 unordered_set(initializer_list<value_type> __l, 177 size_type __n, const hasher& __hf, 178 const allocator_type& __a) 179 : unordered_set(__l, __n, __hf, key_equal(), __a) 180 { } 181 182 ~unordered_set() = default; 183 184 unordered_set& 185 operator=(const unordered_set&) = default; 186 187 unordered_set& 188 operator=(unordered_set&&) = default; 189 190 unordered_set& 191 operator=(initializer_list<value_type> __l) 192 { 193 _M_base() = __l; 194 this->_M_invalidate_all(); 195 return *this; 196 } 197 198 void 199 swap(unordered_set& __x) 200 noexcept( noexcept(declval<_Base&>().swap(__x)) ) 201 { 202 _Safe::_M_swap(__x); 203 _Base::swap(__x); 204 } 205 206 void 207 clear() noexcept 208 { 209 _Base::clear(); 210 this->_M_invalidate_all(); 211 } 212 213 iterator 214 begin() noexcept 215 { return { _Base::begin(), this }; } 216 217 const_iterator 218 begin() const noexcept 219 { return { _Base::begin(), this }; } 220 221 iterator 222 end() noexcept 223 { return { _Base::end(), this }; } 224 225 const_iterator 226 end() const noexcept 227 { return { _Base::end(), this }; } 228 229 const_iterator 230 cbegin() const noexcept 231 { return { _Base::cbegin(), this }; } 232 233 const_iterator 234 cend() const noexcept 235 { return { _Base::cend(), this }; } 236 237 // local versions 238 local_iterator 239 begin(size_type __b) 240 { 241 __glibcxx_check_bucket_index(__b); 242 return { _Base::begin(__b), this }; 243 } 244 245 local_iterator 246 end(size_type __b) 247 { 248 __glibcxx_check_bucket_index(__b); 249 return { _Base::end(__b), this }; 250 } 251 252 const_local_iterator 253 begin(size_type __b) const 254 { 255 __glibcxx_check_bucket_index(__b); 256 return { _Base::begin(__b), this }; 257 } 258 259 const_local_iterator 260 end(size_type __b) const 261 { 262 __glibcxx_check_bucket_index(__b); 263 return { _Base::end(__b), this }; 264 } 265 266 const_local_iterator 267 cbegin(size_type __b) const 268 { 269 __glibcxx_check_bucket_index(__b); 270 return { _Base::cbegin(__b), this }; 271 } 272 273 const_local_iterator 274 cend(size_type __b) const 275 { 276 __glibcxx_check_bucket_index(__b); 277 return { _Base::cend(__b), this }; 278 } 279 280 size_type 281 bucket_size(size_type __b) const 282 { 283 __glibcxx_check_bucket_index(__b); 284 return _Base::bucket_size(__b); 285 } 286 287 float 288 max_load_factor() const noexcept 289 { return _Base::max_load_factor(); } 290 291 void 292 max_load_factor(float __f) 293 { 294 __glibcxx_check_max_load_factor(__f); 295 _Base::max_load_factor(__f); 296 } 297 298 template<typename... _Args> 299 std::pair<iterator, bool> 300 emplace(_Args&&... __args) 301 { 302 size_type __bucket_count = this->bucket_count(); 303 auto __res = _Base::emplace(std::forward<_Args>(__args)...); 304 _M_check_rehashed(__bucket_count); 305 return { { __res.first, this }, __res.second }; 306 } 307 308 template<typename... _Args> 309 iterator 310 emplace_hint(const_iterator __hint, _Args&&... __args) 311 { 312 __glibcxx_check_insert(__hint); 313 size_type __bucket_count = this->bucket_count(); 314 auto __it = _Base::emplace_hint(__hint.base(), 315 std::forward<_Args>(__args)...); 316 _M_check_rehashed(__bucket_count); 317 return { __it, this }; 318 } 319 320 std::pair<iterator, bool> 321 insert(const value_type& __obj) 322 { 323 size_type __bucket_count = this->bucket_count(); 324 auto __res = _Base::insert(__obj); 325 _M_check_rehashed(__bucket_count); 326 return { { __res.first, this }, __res.second }; 327 } 328 329 iterator 330 insert(const_iterator __hint, const value_type& __obj) 331 { 332 __glibcxx_check_insert(__hint); 333 size_type __bucket_count = this->bucket_count(); 334 auto __it = _Base::insert(__hint.base(), __obj); 335 _M_check_rehashed(__bucket_count); 336 return { __it, this }; 337 } 338 339 std::pair<iterator, bool> 340 insert(value_type&& __obj) 341 { 342 size_type __bucket_count = this->bucket_count(); 343 auto __res = _Base::insert(std::move(__obj)); 344 _M_check_rehashed(__bucket_count); 345 return { { __res.first, this }, __res.second }; 346 } 347 348 iterator 349 insert(const_iterator __hint, value_type&& __obj) 350 { 351 __glibcxx_check_insert(__hint); 352 size_type __bucket_count = this->bucket_count(); 353 auto __it = _Base::insert(__hint.base(), std::move(__obj)); 354 _M_check_rehashed(__bucket_count); 355 return { __it, this }; 356 } 357 358 void 359 insert(std::initializer_list<value_type> __l) 360 { 361 size_type __bucket_count = this->bucket_count(); 362 _Base::insert(__l); 363 _M_check_rehashed(__bucket_count); 364 } 365 366 template<typename _InputIterator> 367 void 368 insert(_InputIterator __first, _InputIterator __last) 369 { 370 typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist; 371 __glibcxx_check_valid_range2(__first, __last, __dist); 372 size_type __bucket_count = this->bucket_count(); 373 374 if (__dist.second >= __gnu_debug::__dp_sign) 375 _Base::insert(__gnu_debug::__unsafe(__first), 376 __gnu_debug::__unsafe(__last)); 377 else 378 _Base::insert(__first, __last); 379 380 _M_check_rehashed(__bucket_count); 381 } 382 383#if __cplusplus > 201402L 384 using node_type = typename _Base::node_type; 385 using insert_return_type = _Node_insert_return<iterator, node_type>; 386 387 node_type 388 extract(const_iterator __position) 389 { 390 __glibcxx_check_erase(__position); 391 return _M_extract(__position.base()); 392 } 393 394 node_type 395 extract(const key_type& __key) 396 { 397 const auto __position = _Base::find(__key); 398 if (__position != _Base::end()) 399 return _M_extract(__position); 400 return {}; 401 } 402 403 insert_return_type 404 insert(node_type&& __nh) 405 { 406 auto __ret = _Base::insert(std::move(__nh)); 407 return 408 { { __ret.position, this }, __ret.inserted, std::move(__ret.node) }; 409 } 410 411 iterator 412 insert(const_iterator __hint, node_type&& __nh) 413 { 414 __glibcxx_check_insert(__hint); 415 return { _Base::insert(__hint.base(), std::move(__nh)), this }; 416 } 417 418 using _Base::merge; 419#endif // C++17 420 421 iterator 422 find(const key_type& __key) 423 { return { _Base::find(__key), this }; } 424 425 const_iterator 426 find(const key_type& __key) const 427 { return { _Base::find(__key), this }; } 428 429 std::pair<iterator, iterator> 430 equal_range(const key_type& __key) 431 { 432 auto __res = _Base::equal_range(__key); 433 return { { __res.first, this }, { __res.second, this } }; 434 } 435 436 std::pair<const_iterator, const_iterator> 437 equal_range(const key_type& __key) const 438 { 439 auto __res = _Base::equal_range(__key); 440 return { { __res.first, this }, { __res.second, this } }; 441 } 442 443 size_type 444 erase(const key_type& __key) 445 { 446 size_type __ret(0); 447 auto __victim = _Base::find(__key); 448 if (__victim != _Base::end()) 449 { 450 _M_erase(__victim); 451 __ret = 1; 452 } 453 return __ret; 454 } 455 456 iterator 457 erase(const_iterator __it) 458 { 459 __glibcxx_check_erase(__it); 460 return { _M_erase(__it.base()), this }; 461 } 462 463 iterator 464 erase(iterator __it) 465 { 466 __glibcxx_check_erase(__it); 467 return { _M_erase(__it.base()), this }; 468 } 469 470 iterator 471 erase(const_iterator __first, const_iterator __last) 472 { 473 __glibcxx_check_erase_range(__first, __last); 474 for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp) 475 { 476 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(), 477 _M_message(__gnu_debug::__msg_valid_range) 478 ._M_iterator(__first, "first") 479 ._M_iterator(__last, "last")); 480 _M_invalidate(__tmp); 481 } 482 483 size_type __bucket_count = this->bucket_count(); 484 auto __next = _Base::erase(__first.base(), __last.base()); 485 _M_check_rehashed(__bucket_count); 486 return { __next, this }; 487 } 488 489 _Base& 490 _M_base() noexcept { return *this; } 491 492 const _Base& 493 _M_base() const noexcept { return *this; } 494 495 private: 496 void 497 _M_check_rehashed(size_type __prev_count) 498 { 499 if (__prev_count != this->bucket_count()) 500 this->_M_invalidate_all(); 501 } 502 503 void 504 _M_invalidate(_Base_const_iterator __victim) 505 { 506 this->_M_invalidate_if( 507 [__victim](_Base_const_iterator __it) { return __it == __victim; }); 508 this->_M_invalidate_local_if( 509 [__victim](_Base_const_local_iterator __it) 510 { return __it._M_curr() == __victim._M_cur; }); 511 } 512 513 _Base_iterator 514 _M_erase(_Base_const_iterator __victim) 515 { 516 _M_invalidate(__victim); 517 size_type __bucket_count = this->bucket_count(); 518 _Base_iterator __next = _Base::erase(__victim); 519 _M_check_rehashed(__bucket_count); 520 return __next; 521 } 522 523#if __cplusplus > 201402L 524 node_type 525 _M_extract(_Base_const_iterator __victim) 526 { 527 _M_invalidate(__victim); 528 return _Base::extract(__victim); 529 } 530#endif 531 }; 532 533#if __cpp_deduction_guides >= 201606 534 535 template<typename _InputIterator, 536 typename _Hash = 537 hash<typename iterator_traits<_InputIterator>::value_type>, 538 typename _Pred = 539 equal_to<typename iterator_traits<_InputIterator>::value_type>, 540 typename _Allocator = 541 allocator<typename iterator_traits<_InputIterator>::value_type>, 542 typename = _RequireInputIter<_InputIterator>, 543 typename = _RequireNotAllocatorOrIntegral<_Hash>, 544 typename = _RequireNotAllocator<_Pred>, 545 typename = _RequireAllocator<_Allocator>> 546 unordered_set(_InputIterator, _InputIterator, 547 unordered_set<int>::size_type = {}, 548 _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) 549 -> unordered_set<typename iterator_traits<_InputIterator>::value_type, 550 _Hash, _Pred, _Allocator>; 551 552 template<typename _Tp, typename _Hash = hash<_Tp>, 553 typename _Pred = equal_to<_Tp>, 554 typename _Allocator = allocator<_Tp>, 555 typename = _RequireNotAllocatorOrIntegral<_Hash>, 556 typename = _RequireNotAllocator<_Pred>, 557 typename = _RequireAllocator<_Allocator>> 558 unordered_set(initializer_list<_Tp>, 559 unordered_set<int>::size_type = {}, 560 _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) 561 -> unordered_set<_Tp, _Hash, _Pred, _Allocator>; 562 563 template<typename _InputIterator, typename _Allocator, 564 typename = _RequireInputIter<_InputIterator>, 565 typename = _RequireAllocator<_Allocator>> 566 unordered_set(_InputIterator, _InputIterator, 567 unordered_set<int>::size_type, _Allocator) 568 -> unordered_set<typename iterator_traits<_InputIterator>::value_type, 569 hash< 570 typename iterator_traits<_InputIterator>::value_type>, 571 equal_to< 572 typename iterator_traits<_InputIterator>::value_type>, 573 _Allocator>; 574 575 template<typename _InputIterator, typename _Hash, typename _Allocator, 576 typename = _RequireInputIter<_InputIterator>, 577 typename = _RequireNotAllocatorOrIntegral<_Hash>, 578 typename = _RequireAllocator<_Allocator>> 579 unordered_set(_InputIterator, _InputIterator, 580 unordered_set<int>::size_type, 581 _Hash, _Allocator) 582 -> unordered_set<typename iterator_traits<_InputIterator>::value_type, 583 _Hash, 584 equal_to< 585 typename iterator_traits<_InputIterator>::value_type>, 586 _Allocator>; 587 588 template<typename _Tp, typename _Allocator, 589 typename = _RequireAllocator<_Allocator>> 590 unordered_set(initializer_list<_Tp>, 591 unordered_set<int>::size_type, _Allocator) 592 -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; 593 594 template<typename _Tp, typename _Hash, typename _Allocator, 595 typename = _RequireNotAllocatorOrIntegral<_Hash>, 596 typename = _RequireAllocator<_Allocator>> 597 unordered_set(initializer_list<_Tp>, 598 unordered_set<int>::size_type, _Hash, _Allocator) 599 -> unordered_set<_Tp, _Hash, equal_to<_Tp>, _Allocator>; 600 601#endif 602 603 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 604 inline void 605 swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, 606 unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) 607 noexcept(noexcept(__x.swap(__y))) 608 { __x.swap(__y); } 609 610 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 611 inline bool 612 operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, 613 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) 614 { return __x._M_base() == __y._M_base(); } 615 616#if __cpp_impl_three_way_comparison < 201907L 617 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 618 inline bool 619 operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, 620 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) 621 { return !(__x == __y); } 622#endif 623 624 /// Class std::unordered_multiset with safety/checking/debug instrumentation. 625 template<typename _Value, 626 typename _Hash = std::hash<_Value>, 627 typename _Pred = std::equal_to<_Value>, 628 typename _Alloc = std::allocator<_Value> > 629 class unordered_multiset 630 : public __gnu_debug::_Safe_container< 631 unordered_multiset<_Value, _Hash, _Pred, _Alloc>, _Alloc, 632 __gnu_debug::_Safe_unordered_container>, 633 public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc> 634 { 635 typedef _GLIBCXX_STD_C::unordered_multiset< 636 _Value, _Hash, _Pred, _Alloc> _Base; 637 typedef __gnu_debug::_Safe_container<unordered_multiset, 638 _Alloc, __gnu_debug::_Safe_unordered_container> _Safe; 639 typedef typename _Base::const_iterator _Base_const_iterator; 640 typedef typename _Base::iterator _Base_iterator; 641 typedef typename _Base::const_local_iterator 642 _Base_const_local_iterator; 643 typedef typename _Base::local_iterator _Base_local_iterator; 644 645 template<typename _ItT, typename _SeqT, typename _CatT> 646 friend class ::__gnu_debug::_Safe_iterator; 647 template<typename _ItT, typename _SeqT> 648 friend class ::__gnu_debug::_Safe_local_iterator; 649 650 public: 651 typedef typename _Base::size_type size_type; 652 typedef typename _Base::hasher hasher; 653 typedef typename _Base::key_equal key_equal; 654 typedef typename _Base::allocator_type allocator_type; 655 656 typedef typename _Base::key_type key_type; 657 typedef typename _Base::value_type value_type; 658 659 typedef __gnu_debug::_Safe_iterator< 660 _Base_iterator, unordered_multiset> iterator; 661 typedef __gnu_debug::_Safe_iterator< 662 _Base_const_iterator, unordered_multiset> const_iterator; 663 typedef __gnu_debug::_Safe_local_iterator< 664 _Base_local_iterator, unordered_multiset> local_iterator; 665 typedef __gnu_debug::_Safe_local_iterator< 666 _Base_const_local_iterator, unordered_multiset> const_local_iterator; 667 668 unordered_multiset() = default; 669 670 explicit 671 unordered_multiset(size_type __n, 672 const hasher& __hf = hasher(), 673 const key_equal& __eql = key_equal(), 674 const allocator_type& __a = allocator_type()) 675 : _Base(__n, __hf, __eql, __a) { } 676 677 template<typename _InputIterator> 678 unordered_multiset(_InputIterator __first, _InputIterator __last, 679 size_type __n = 0, 680 const hasher& __hf = hasher(), 681 const key_equal& __eql = key_equal(), 682 const allocator_type& __a = allocator_type()) 683 : _Base(__gnu_debug::__base( 684 __glibcxx_check_valid_constructor_range(__first, __last)), 685 __gnu_debug::__base(__last), __n, 686 __hf, __eql, __a) { } 687 688 unordered_multiset(const unordered_multiset&) = default; 689 690 unordered_multiset(const _Base& __x) 691 : _Base(__x) { } 692 693 unordered_multiset(unordered_multiset&&) = default; 694 695 explicit 696 unordered_multiset(const allocator_type& __a) 697 : _Base(__a) { } 698 699 unordered_multiset(const unordered_multiset& __uset, 700 const allocator_type& __a) 701 : _Base(__uset, __a) { } 702 703 unordered_multiset(unordered_multiset&& __uset, 704 const allocator_type& __a) 705 noexcept( noexcept(_Base(std::move(__uset._M_base()), __a)) ) 706 : _Safe(std::move(__uset._M_safe()), __a), 707 _Base(std::move(__uset._M_base()), __a) { } 708 709 unordered_multiset(initializer_list<value_type> __l, 710 size_type __n = 0, 711 const hasher& __hf = hasher(), 712 const key_equal& __eql = key_equal(), 713 const allocator_type& __a = allocator_type()) 714 : _Base(__l, __n, __hf, __eql, __a) { } 715 716 unordered_multiset(size_type __n, const allocator_type& __a) 717 : unordered_multiset(__n, hasher(), key_equal(), __a) 718 { } 719 720 unordered_multiset(size_type __n, const hasher& __hf, 721 const allocator_type& __a) 722 : unordered_multiset(__n, __hf, key_equal(), __a) 723 { } 724 725 template<typename _InputIterator> 726 unordered_multiset(_InputIterator __first, _InputIterator __last, 727 size_type __n, 728 const allocator_type& __a) 729 : unordered_multiset(__first, __last, __n, hasher(), key_equal(), __a) 730 { } 731 732 template<typename _InputIterator> 733 unordered_multiset(_InputIterator __first, _InputIterator __last, 734 size_type __n, const hasher& __hf, 735 const allocator_type& __a) 736 : unordered_multiset(__first, __last, __n, __hf, key_equal(), __a) 737 { } 738 739 unordered_multiset(initializer_list<value_type> __l, 740 size_type __n, 741 const allocator_type& __a) 742 : unordered_multiset(__l, __n, hasher(), key_equal(), __a) 743 { } 744 745 unordered_multiset(initializer_list<value_type> __l, 746 size_type __n, const hasher& __hf, 747 const allocator_type& __a) 748 : unordered_multiset(__l, __n, __hf, key_equal(), __a) 749 { } 750 751 ~unordered_multiset() = default; 752 753 unordered_multiset& 754 operator=(const unordered_multiset&) = default; 755 756 unordered_multiset& 757 operator=(unordered_multiset&&) = default; 758 759 unordered_multiset& 760 operator=(initializer_list<value_type> __l) 761 { 762 this->_M_base() = __l; 763 this->_M_invalidate_all(); 764 return *this; 765 } 766 767 void 768 swap(unordered_multiset& __x) 769 noexcept( noexcept(declval<_Base&>().swap(__x)) ) 770 { 771 _Safe::_M_swap(__x); 772 _Base::swap(__x); 773 } 774 775 void 776 clear() noexcept 777 { 778 _Base::clear(); 779 this->_M_invalidate_all(); 780 } 781 782 iterator 783 begin() noexcept 784 { return { _Base::begin(), this }; } 785 786 const_iterator 787 begin() const noexcept 788 { return { _Base::begin(), this }; } 789 790 iterator 791 end() noexcept 792 { return { _Base::end(), this }; } 793 794 const_iterator 795 end() const noexcept 796 { return { _Base::end(), this }; } 797 798 const_iterator 799 cbegin() const noexcept 800 { return { _Base::cbegin(), this }; } 801 802 const_iterator 803 cend() const noexcept 804 { return { _Base::cend(), this }; } 805 806 // local versions 807 local_iterator 808 begin(size_type __b) 809 { 810 __glibcxx_check_bucket_index(__b); 811 return { _Base::begin(__b), this }; 812 } 813 814 local_iterator 815 end(size_type __b) 816 { 817 __glibcxx_check_bucket_index(__b); 818 return { _Base::end(__b), this }; 819 } 820 821 const_local_iterator 822 begin(size_type __b) const 823 { 824 __glibcxx_check_bucket_index(__b); 825 return { _Base::begin(__b), this }; 826 } 827 828 const_local_iterator 829 end(size_type __b) const 830 { 831 __glibcxx_check_bucket_index(__b); 832 return { _Base::end(__b), this }; 833 } 834 835 const_local_iterator 836 cbegin(size_type __b) const 837 { 838 __glibcxx_check_bucket_index(__b); 839 return { _Base::cbegin(__b), this }; 840 } 841 842 const_local_iterator 843 cend(size_type __b) const 844 { 845 __glibcxx_check_bucket_index(__b); 846 return { _Base::cend(__b), this }; 847 } 848 849 size_type 850 bucket_size(size_type __b) const 851 { 852 __glibcxx_check_bucket_index(__b); 853 return _Base::bucket_size(__b); 854 } 855 856 float 857 max_load_factor() const noexcept 858 { return _Base::max_load_factor(); } 859 860 void 861 max_load_factor(float __f) 862 { 863 __glibcxx_check_max_load_factor(__f); 864 _Base::max_load_factor(__f); 865 } 866 867 template<typename... _Args> 868 iterator 869 emplace(_Args&&... __args) 870 { 871 size_type __bucket_count = this->bucket_count(); 872 auto __it = _Base::emplace(std::forward<_Args>(__args)...); 873 _M_check_rehashed(__bucket_count); 874 return { __it, this }; 875 } 876 877 template<typename... _Args> 878 iterator 879 emplace_hint(const_iterator __hint, _Args&&... __args) 880 { 881 __glibcxx_check_insert(__hint); 882 size_type __bucket_count = this->bucket_count(); 883 auto __it = _Base::emplace_hint(__hint.base(), 884 std::forward<_Args>(__args)...); 885 _M_check_rehashed(__bucket_count); 886 return { __it, this }; 887 } 888 889 iterator 890 insert(const value_type& __obj) 891 { 892 size_type __bucket_count = this->bucket_count(); 893 auto __it = _Base::insert(__obj); 894 _M_check_rehashed(__bucket_count); 895 return { __it, this }; 896 } 897 898 iterator 899 insert(const_iterator __hint, const value_type& __obj) 900 { 901 __glibcxx_check_insert(__hint); 902 size_type __bucket_count = this->bucket_count(); 903 auto __it = _Base::insert(__hint.base(), __obj); 904 _M_check_rehashed(__bucket_count); 905 return { __it, this }; 906 } 907 908 iterator 909 insert(value_type&& __obj) 910 { 911 size_type __bucket_count = this->bucket_count(); 912 auto __it = _Base::insert(std::move(__obj)); 913 _M_check_rehashed(__bucket_count); 914 return { __it, this }; 915 } 916 917 iterator 918 insert(const_iterator __hint, value_type&& __obj) 919 { 920 __glibcxx_check_insert(__hint); 921 size_type __bucket_count = this->bucket_count(); 922 auto __it = _Base::insert(__hint.base(), std::move(__obj)); 923 _M_check_rehashed(__bucket_count); 924 return { __it, this }; 925 } 926 927 void 928 insert(std::initializer_list<value_type> __l) 929 { 930 size_type __bucket_count = this->bucket_count(); 931 _Base::insert(__l); 932 _M_check_rehashed(__bucket_count); 933 } 934 935 template<typename _InputIterator> 936 void 937 insert(_InputIterator __first, _InputIterator __last) 938 { 939 typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist; 940 __glibcxx_check_valid_range2(__first, __last, __dist); 941 size_type __bucket_count = this->bucket_count(); 942 943 if (__dist.second >= __gnu_debug::__dp_sign) 944 _Base::insert(__gnu_debug::__unsafe(__first), 945 __gnu_debug::__unsafe(__last)); 946 else 947 _Base::insert(__first, __last); 948 949 _M_check_rehashed(__bucket_count); 950 } 951 952#if __cplusplus > 201402L 953 using node_type = typename _Base::node_type; 954 955 node_type 956 extract(const_iterator __position) 957 { 958 __glibcxx_check_erase(__position); 959 return _M_extract(__position.base()); 960 } 961 962 node_type 963 extract(const key_type& __key) 964 { 965 const auto __position = _Base::find(__key); 966 if (__position != _Base::end()) 967 return _M_extract(__position); 968 return {}; 969 } 970 971 iterator 972 insert(node_type&& __nh) 973 { return { _Base::insert(std::move(__nh)), this }; } 974 975 iterator 976 insert(const_iterator __hint, node_type&& __nh) 977 { 978 __glibcxx_check_insert(__hint); 979 return { _Base::insert(__hint.base(), std::move(__nh)), this }; 980 } 981 982 using _Base::merge; 983#endif // C++17 984 985 iterator 986 find(const key_type& __key) 987 { return { _Base::find(__key), this }; } 988 989 const_iterator 990 find(const key_type& __key) const 991 { return { _Base::find(__key), this }; } 992 993 std::pair<iterator, iterator> 994 equal_range(const key_type& __key) 995 { 996 auto __res = _Base::equal_range(__key); 997 return { { __res.first, this }, { __res.second, this } }; 998 } 999 1000 std::pair<const_iterator, const_iterator> 1001 equal_range(const key_type& __key) const 1002 { 1003 auto __res = _Base::equal_range(__key); 1004 return { { __res.first, this }, { __res.second, this } }; 1005 } 1006 1007 size_type 1008 erase(const key_type& __key) 1009 { 1010 size_type __ret(0); 1011 auto __pair = _Base::equal_range(__key); 1012 for (auto __victim = __pair.first; __victim != __pair.second;) 1013 { 1014 _M_invalidate(__victim); 1015 __victim = _Base::erase(__victim); 1016 ++__ret; 1017 } 1018 1019 return __ret; 1020 } 1021 1022 iterator 1023 erase(const_iterator __it) 1024 { 1025 __glibcxx_check_erase(__it); 1026 return { _M_erase(__it.base()), this }; 1027 } 1028 1029 iterator 1030 erase(iterator __it) 1031 { 1032 __glibcxx_check_erase(__it); 1033 return { _M_erase(__it.base()), this }; 1034 } 1035 1036 iterator 1037 erase(const_iterator __first, const_iterator __last) 1038 { 1039 __glibcxx_check_erase_range(__first, __last); 1040 for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp) 1041 { 1042 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(), 1043 _M_message(__gnu_debug::__msg_valid_range) 1044 ._M_iterator(__first, "first") 1045 ._M_iterator(__last, "last")); 1046 _M_invalidate(__tmp); 1047 } 1048 return { _Base::erase(__first.base(), __last.base()), this }; 1049 } 1050 1051 _Base& 1052 _M_base() noexcept { return *this; } 1053 1054 const _Base& 1055 _M_base() const noexcept { return *this; } 1056 1057 private: 1058 void 1059 _M_check_rehashed(size_type __prev_count) 1060 { 1061 if (__prev_count != this->bucket_count()) 1062 this->_M_invalidate_all(); 1063 } 1064 1065 void 1066 _M_invalidate(_Base_const_iterator __victim) 1067 { 1068 this->_M_invalidate_if( 1069 [__victim](_Base_const_iterator __it) { return __it == __victim; }); 1070 this->_M_invalidate_local_if( 1071 [__victim](_Base_const_local_iterator __it) 1072 { return __it._M_curr() == __victim._M_cur; }); 1073 } 1074 1075 _Base_iterator 1076 _M_erase(_Base_const_iterator __victim) 1077 { 1078 _M_invalidate(__victim); 1079 size_type __bucket_count = this->bucket_count(); 1080 _Base_iterator __next = _Base::erase(__victim); 1081 _M_check_rehashed(__bucket_count); 1082 return __next; 1083 } 1084 1085#if __cplusplus > 201402L 1086 node_type 1087 _M_extract(_Base_const_iterator __victim) 1088 { 1089 _M_invalidate(__victim); 1090 return _Base::extract(__victim); 1091 } 1092#endif 1093 }; 1094 1095#if __cpp_deduction_guides >= 201606 1096 1097 template<typename _InputIterator, 1098 typename _Hash = 1099 hash<typename iterator_traits<_InputIterator>::value_type>, 1100 typename _Pred = 1101 equal_to<typename iterator_traits<_InputIterator>::value_type>, 1102 typename _Allocator = 1103 allocator<typename iterator_traits<_InputIterator>::value_type>, 1104 typename = _RequireInputIter<_InputIterator>, 1105 typename = _RequireNotAllocatorOrIntegral<_Hash>, 1106 typename = _RequireNotAllocator<_Pred>, 1107 typename = _RequireAllocator<_Allocator>> 1108 unordered_multiset(_InputIterator, _InputIterator, 1109 unordered_multiset<int>::size_type = {}, 1110 _Hash = _Hash(), _Pred = _Pred(), 1111 _Allocator = _Allocator()) 1112 -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type, 1113 _Hash, _Pred, _Allocator>; 1114 1115 template<typename _Tp, typename _Hash = hash<_Tp>, 1116 typename _Pred = equal_to<_Tp>, 1117 typename _Allocator = allocator<_Tp>, 1118 typename = _RequireNotAllocatorOrIntegral<_Hash>, 1119 typename = _RequireNotAllocator<_Pred>, 1120 typename = _RequireAllocator<_Allocator>> 1121 unordered_multiset(initializer_list<_Tp>, 1122 unordered_multiset<int>::size_type = {}, 1123 _Hash = _Hash(), _Pred = _Pred(), 1124 _Allocator = _Allocator()) 1125 -> unordered_multiset<_Tp, _Hash, _Pred, _Allocator>; 1126 1127 template<typename _InputIterator, typename _Allocator, 1128 typename = _RequireInputIter<_InputIterator>, 1129 typename = _RequireAllocator<_Allocator>> 1130 unordered_multiset(_InputIterator, _InputIterator, 1131 unordered_multiset<int>::size_type, _Allocator) 1132 -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type, 1133 hash<typename 1134 iterator_traits<_InputIterator>::value_type>, 1135 equal_to<typename 1136 iterator_traits<_InputIterator>::value_type>, 1137 _Allocator>; 1138 1139 template<typename _InputIterator, typename _Hash, typename _Allocator, 1140 typename = _RequireInputIter<_InputIterator>, 1141 typename = _RequireNotAllocatorOrIntegral<_Hash>, 1142 typename = _RequireAllocator<_Allocator>> 1143 unordered_multiset(_InputIterator, _InputIterator, 1144 unordered_multiset<int>::size_type, 1145 _Hash, _Allocator) 1146 -> unordered_multiset<typename 1147 iterator_traits<_InputIterator>::value_type, 1148 _Hash, 1149 equal_to< 1150 typename 1151 iterator_traits<_InputIterator>::value_type>, 1152 _Allocator>; 1153 1154 template<typename _Tp, typename _Allocator, 1155 typename = _RequireAllocator<_Allocator>> 1156 unordered_multiset(initializer_list<_Tp>, 1157 unordered_multiset<int>::size_type, _Allocator) 1158 -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; 1159 1160 template<typename _Tp, typename _Hash, typename _Allocator, 1161 typename = _RequireNotAllocatorOrIntegral<_Hash>, 1162 typename = _RequireAllocator<_Allocator>> 1163 unordered_multiset(initializer_list<_Tp>, 1164 unordered_multiset<int>::size_type, _Hash, _Allocator) 1165 -> unordered_multiset<_Tp, _Hash, equal_to<_Tp>, _Allocator>; 1166 1167#endif 1168 1169 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 1170 inline void 1171 swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, 1172 unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) 1173 noexcept(noexcept(__x.swap(__y))) 1174 { __x.swap(__y); } 1175 1176 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 1177 inline bool 1178 operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, 1179 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) 1180 { return __x._M_base() == __y._M_base(); } 1181 1182#if __cpp_impl_three_way_comparison < 201907L 1183 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 1184 inline bool 1185 operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, 1186 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) 1187 { return !(__x == __y); } 1188#endif 1189 1190} // namespace __debug 1191} // namespace std 1192 1193#endif // C++11 1194 1195#endif 1196