1// Debugging unordered_set/unordered_multiset implementation -*- C++ -*- 2 3// Copyright (C) 2003-2014 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#if __cplusplus < 201103L 33# include <bits/c++0x_warning.h> 34#else 35# include <unordered_set> 36 37#include <debug/safe_unordered_container.h> 38#include <debug/safe_iterator.h> 39#include <debug/safe_local_iterator.h> 40 41namespace std _GLIBCXX_VISIBILITY(default) 42{ 43namespace __debug 44{ 45 /// Class std::unordered_set with safety/checking/debug instrumentation. 46 template<typename _Value, 47 typename _Hash = std::hash<_Value>, 48 typename _Pred = std::equal_to<_Value>, 49 typename _Alloc = std::allocator<_Value> > 50 class unordered_set 51 : public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc>, 52 public __gnu_debug::_Safe_unordered_container<unordered_set<_Value, _Hash, 53 _Pred, _Alloc> > 54 { 55 typedef _GLIBCXX_STD_C::unordered_set<_Value, _Hash, 56 _Pred, _Alloc> _Base; 57 typedef __gnu_debug::_Safe_unordered_container<unordered_set> _Safe_base; 58 typedef typename _Base::const_iterator _Base_const_iterator; 59 typedef typename _Base::iterator _Base_iterator; 60 typedef typename _Base::const_local_iterator _Base_const_local_iterator; 61 typedef typename _Base::local_iterator _Base_local_iterator; 62 63 typedef __gnu_cxx::__alloc_traits<typename 64 _Base::allocator_type> _Alloc_traits; 65 public: 66 typedef typename _Base::size_type size_type; 67 typedef typename _Base::hasher hasher; 68 typedef typename _Base::key_equal key_equal; 69 typedef typename _Base::allocator_type allocator_type; 70 71 typedef typename _Base::key_type key_type; 72 typedef typename _Base::value_type value_type; 73 74 typedef __gnu_debug::_Safe_iterator<_Base_iterator, 75 unordered_set> iterator; 76 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, 77 unordered_set> const_iterator; 78 typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator, 79 unordered_set> local_iterator; 80 typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator, 81 unordered_set> const_local_iterator; 82 83 explicit 84 unordered_set(size_type __n = 10, 85 const hasher& __hf = hasher(), 86 const key_equal& __eql = key_equal(), 87 const allocator_type& __a = allocator_type()) 88 : _Base(__n, __hf, __eql, __a) { } 89 90 template<typename _InputIterator> 91 unordered_set(_InputIterator __first, _InputIterator __last, 92 size_type __n = 0, 93 const hasher& __hf = hasher(), 94 const key_equal& __eql = key_equal(), 95 const allocator_type& __a = allocator_type()) 96 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, 97 __last)), 98 __gnu_debug::__base(__last), __n, 99 __hf, __eql, __a) { } 100 101 unordered_set(const unordered_set&) = default; 102 103 unordered_set(const _Base& __x) 104 : _Base(__x) { } 105 106 unordered_set(unordered_set&&) = default; 107 108 explicit 109 unordered_set(const allocator_type& __a) 110 : _Base(__a) 111 { } 112 113 unordered_set(const unordered_set& __uset, 114 const allocator_type& __a) 115 : _Base(__uset._M_base(), __a) 116 { } 117 118 unordered_set(unordered_set&& __uset, 119 const allocator_type& __a) 120 : _Base(std::move(__uset._M_base()), __a) 121 { } 122 123 unordered_set(initializer_list<value_type> __l, 124 size_type __n = 0, 125 const hasher& __hf = hasher(), 126 const key_equal& __eql = key_equal(), 127 const allocator_type& __a = allocator_type()) 128 : _Base(__l, __n, __hf, __eql, __a) { } 129 130 ~unordered_set() noexcept { } 131 132 unordered_set& 133 operator=(const unordered_set& __x) 134 { 135 _M_base() = __x._M_base(); 136 this->_M_invalidate_all(); 137 return *this; 138 } 139 140 unordered_set& 141 operator=(unordered_set&& __x) 142 noexcept(_Alloc_traits::_S_nothrow_move()) 143 { 144 __glibcxx_check_self_move_assign(__x); 145 bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign() 146 || __x.get_allocator() == this->get_allocator(); 147 _M_base() = std::move(__x._M_base()); 148 if (__xfer_memory) 149 this->_M_swap(__x); 150 else 151 this->_M_invalidate_all(); 152 __x._M_invalidate_all(); 153 return *this; 154 } 155 156 unordered_set& 157 operator=(initializer_list<value_type> __l) 158 { 159 _M_base() = __l; 160 this->_M_invalidate_all(); 161 return *this; 162 } 163 164 void 165 swap(unordered_set& __x) 166 noexcept(_Alloc_traits::_S_nothrow_swap()) 167 { 168 if (!_Alloc_traits::_S_propagate_on_swap()) 169 __glibcxx_check_equal_allocs(__x); 170 _Base::swap(__x); 171 _Safe_base::_M_swap(__x); 172 } 173 174 void 175 clear() noexcept 176 { 177 _Base::clear(); 178 this->_M_invalidate_all(); 179 } 180 181 iterator 182 begin() noexcept 183 { return iterator(_Base::begin(), this); } 184 185 const_iterator 186 begin() const noexcept 187 { return const_iterator(_Base::begin(), this); } 188 189 iterator 190 end() noexcept 191 { return iterator(_Base::end(), this); } 192 193 const_iterator 194 end() const noexcept 195 { return const_iterator(_Base::end(), this); } 196 197 const_iterator 198 cbegin() const noexcept 199 { return const_iterator(_Base::begin(), this); } 200 201 const_iterator 202 cend() const noexcept 203 { return const_iterator(_Base::end(), this); } 204 205 // local versions 206 local_iterator 207 begin(size_type __b) 208 { 209 __glibcxx_check_bucket_index(__b); 210 return local_iterator(_Base::begin(__b), this); 211 } 212 213 local_iterator 214 end(size_type __b) 215 { 216 __glibcxx_check_bucket_index(__b); 217 return local_iterator(_Base::end(__b), this); 218 } 219 220 const_local_iterator 221 begin(size_type __b) const 222 { 223 __glibcxx_check_bucket_index(__b); 224 return const_local_iterator(_Base::begin(__b), this); 225 } 226 227 const_local_iterator 228 end(size_type __b) const 229 { 230 __glibcxx_check_bucket_index(__b); 231 return const_local_iterator(_Base::end(__b), this); 232 } 233 234 const_local_iterator 235 cbegin(size_type __b) const 236 { 237 __glibcxx_check_bucket_index(__b); 238 return const_local_iterator(_Base::cbegin(__b), this); 239 } 240 241 const_local_iterator 242 cend(size_type __b) const 243 { 244 __glibcxx_check_bucket_index(__b); 245 return const_local_iterator(_Base::cend(__b), this); 246 } 247 248 size_type 249 bucket_size(size_type __b) const 250 { 251 __glibcxx_check_bucket_index(__b); 252 return _Base::bucket_size(__b); 253 } 254 255 float 256 max_load_factor() const noexcept 257 { return _Base::max_load_factor(); } 258 259 void 260 max_load_factor(float __f) 261 { 262 __glibcxx_check_max_load_factor(__f); 263 _Base::max_load_factor(__f); 264 } 265 266 template<typename... _Args> 267 std::pair<iterator, bool> 268 emplace(_Args&&... __args) 269 { 270 size_type __bucket_count = this->bucket_count(); 271 std::pair<_Base_iterator, bool> __res 272 = _Base::emplace(std::forward<_Args>(__args)...); 273 _M_check_rehashed(__bucket_count); 274 return std::make_pair(iterator(__res.first, this), __res.second); 275 } 276 277 template<typename... _Args> 278 iterator 279 emplace_hint(const_iterator __hint, _Args&&... __args) 280 { 281 __glibcxx_check_insert(__hint); 282 size_type __bucket_count = this->bucket_count(); 283 _Base_iterator __it = _Base::emplace_hint(__hint.base(), 284 std::forward<_Args>(__args)...); 285 _M_check_rehashed(__bucket_count); 286 return iterator(__it, this); 287 } 288 289 std::pair<iterator, bool> 290 insert(const value_type& __obj) 291 { 292 size_type __bucket_count = this->bucket_count(); 293 typedef std::pair<_Base_iterator, bool> __pair_type; 294 __pair_type __res = _Base::insert(__obj); 295 _M_check_rehashed(__bucket_count); 296 return std::make_pair(iterator(__res.first, this), __res.second); 297 } 298 299 iterator 300 insert(const_iterator __hint, const value_type& __obj) 301 { 302 __glibcxx_check_insert(__hint); 303 size_type __bucket_count = this->bucket_count(); 304 _Base_iterator __it = _Base::insert(__hint.base(), __obj); 305 _M_check_rehashed(__bucket_count); 306 return iterator(__it, this); 307 } 308 309 std::pair<iterator, bool> 310 insert(value_type&& __obj) 311 { 312 size_type __bucket_count = this->bucket_count(); 313 typedef std::pair<typename _Base::iterator, bool> __pair_type; 314 __pair_type __res = _Base::insert(std::move(__obj)); 315 _M_check_rehashed(__bucket_count); 316 return std::make_pair(iterator(__res.first, this), __res.second); 317 } 318 319 iterator 320 insert(const_iterator __hint, value_type&& __obj) 321 { 322 __glibcxx_check_insert(__hint); 323 size_type __bucket_count = this->bucket_count(); 324 _Base_iterator __it = _Base::insert(__hint.base(), std::move(__obj)); 325 _M_check_rehashed(__bucket_count); 326 return iterator(__it, this); 327 } 328 329 void 330 insert(std::initializer_list<value_type> __l) 331 { 332 size_type __bucket_count = this->bucket_count(); 333 _Base::insert(__l); 334 _M_check_rehashed(__bucket_count); 335 } 336 337 template<typename _InputIterator> 338 void 339 insert(_InputIterator __first, _InputIterator __last) 340 { 341 __glibcxx_check_valid_range(__first, __last); 342 size_type __bucket_count = this->bucket_count(); 343 _Base::insert(__gnu_debug::__base(__first), 344 __gnu_debug::__base(__last)); 345 _M_check_rehashed(__bucket_count); 346 } 347 348 iterator 349 find(const key_type& __key) 350 { return iterator(_Base::find(__key), this); } 351 352 const_iterator 353 find(const key_type& __key) const 354 { return const_iterator(_Base::find(__key), this); } 355 356 std::pair<iterator, iterator> 357 equal_range(const key_type& __key) 358 { 359 typedef std::pair<_Base_iterator, _Base_iterator> __pair_type; 360 __pair_type __res = _Base::equal_range(__key); 361 return std::make_pair(iterator(__res.first, this), 362 iterator(__res.second, this)); 363 } 364 365 std::pair<const_iterator, const_iterator> 366 equal_range(const key_type& __key) const 367 { 368 std::pair<_Base_const_iterator, _Base_const_iterator> 369 __res = _Base::equal_range(__key); 370 return std::make_pair(const_iterator(__res.first, this), 371 const_iterator(__res.second, this)); 372 } 373 374 size_type 375 erase(const key_type& __key) 376 { 377 size_type __ret(0); 378 _Base_iterator __victim(_Base::find(__key)); 379 if (__victim != _Base::end()) 380 { 381 this->_M_invalidate_if( 382 [__victim](_Base_const_iterator __it) 383 { return __it == __victim; }); 384 this->_M_invalidate_local_if( 385 [__victim](_Base_const_local_iterator __it) 386 { return __it._M_curr() == __victim._M_cur; }); 387 size_type __bucket_count = this->bucket_count(); 388 _Base::erase(__victim); 389 _M_check_rehashed(__bucket_count); 390 __ret = 1; 391 } 392 return __ret; 393 } 394 395 iterator 396 erase(const_iterator __it) 397 { 398 __glibcxx_check_erase(__it); 399 _Base_const_iterator __victim = __it.base(); 400 this->_M_invalidate_if( 401 [__victim](_Base_const_iterator __it) 402 { return __it == __victim; }); 403 this->_M_invalidate_local_if( 404 [__victim](_Base_const_local_iterator __it) 405 { return __it._M_curr() == __victim._M_cur; }); 406 size_type __bucket_count = this->bucket_count(); 407 _Base_iterator __next = _Base::erase(__it.base()); 408 _M_check_rehashed(__bucket_count); 409 return iterator(__next, this); 410 } 411 412 iterator 413 erase(iterator __it) 414 { return erase(const_iterator(__it)); } 415 416 iterator 417 erase(const_iterator __first, const_iterator __last) 418 { 419 __glibcxx_check_erase_range(__first, __last); 420 for (_Base_const_iterator __tmp = __first.base(); 421 __tmp != __last.base(); ++__tmp) 422 { 423 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(), 424 _M_message(__gnu_debug::__msg_valid_range) 425 ._M_iterator(__first, "first") 426 ._M_iterator(__last, "last")); 427 this->_M_invalidate_if( 428 [__tmp](_Base_const_iterator __it) 429 { return __it == __tmp; }); 430 this->_M_invalidate_local_if( 431 [__tmp](_Base_const_local_iterator __it) 432 { return __it._M_curr() == __tmp._M_cur; }); 433 } 434 size_type __bucket_count = this->bucket_count(); 435 _Base_iterator __next = _Base::erase(__first.base(), 436 __last.base()); 437 _M_check_rehashed(__bucket_count); 438 return iterator(__next, this); 439 } 440 441 _Base& 442 _M_base() noexcept { return *this; } 443 444 const _Base& 445 _M_base() const noexcept { return *this; } 446 447 private: 448 void 449 _M_invalidate_locals() 450 { 451 _Base_local_iterator __local_end = _Base::end(0); 452 this->_M_invalidate_local_if( 453 [__local_end](_Base_const_local_iterator __it) 454 { return __it != __local_end; }); 455 } 456 457 void 458 _M_invalidate_all() 459 { 460 _Base_iterator __end = _Base::end(); 461 this->_M_invalidate_if( 462 [__end](_Base_const_iterator __it) 463 { return __it != __end; }); 464 _M_invalidate_locals(); 465 } 466 467 void 468 _M_check_rehashed(size_type __prev_count) 469 { 470 if (__prev_count != this->bucket_count()) 471 _M_invalidate_locals(); 472 } 473 }; 474 475 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 476 inline void 477 swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, 478 unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) 479 { __x.swap(__y); } 480 481 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 482 inline bool 483 operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, 484 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) 485 { return __x._M_base() == __y._M_base(); } 486 487 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 488 inline bool 489 operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, 490 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) 491 { return !(__x == __y); } 492 493 494 /// Class std::unordered_multiset with safety/checking/debug instrumentation. 495 template<typename _Value, 496 typename _Hash = std::hash<_Value>, 497 typename _Pred = std::equal_to<_Value>, 498 typename _Alloc = std::allocator<_Value> > 499 class unordered_multiset 500 : public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>, 501 public __gnu_debug::_Safe_unordered_container< 502 unordered_multiset<_Value, _Hash, _Pred, _Alloc> > 503 { 504 typedef _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, 505 _Pred, _Alloc> _Base; 506 typedef __gnu_debug::_Safe_unordered_container<unordered_multiset> 507 _Safe_base; 508 typedef typename _Base::const_iterator _Base_const_iterator; 509 typedef typename _Base::iterator _Base_iterator; 510 typedef typename _Base::const_local_iterator _Base_const_local_iterator; 511 typedef typename _Base::local_iterator _Base_local_iterator; 512 513 typedef __gnu_cxx::__alloc_traits<typename 514 _Base::allocator_type> _Alloc_traits; 515 516 public: 517 typedef typename _Base::size_type size_type; 518 typedef typename _Base::hasher hasher; 519 typedef typename _Base::key_equal key_equal; 520 typedef typename _Base::allocator_type allocator_type; 521 522 typedef typename _Base::key_type key_type; 523 typedef typename _Base::value_type value_type; 524 525 typedef __gnu_debug::_Safe_iterator<_Base_iterator, 526 unordered_multiset> iterator; 527 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, 528 unordered_multiset> const_iterator; 529 typedef __gnu_debug::_Safe_local_iterator< 530 _Base_local_iterator, unordered_multiset> local_iterator; 531 typedef __gnu_debug::_Safe_local_iterator< 532 _Base_const_local_iterator, unordered_multiset> const_local_iterator; 533 534 explicit 535 unordered_multiset(size_type __n = 10, 536 const hasher& __hf = hasher(), 537 const key_equal& __eql = key_equal(), 538 const allocator_type& __a = allocator_type()) 539 : _Base(__n, __hf, __eql, __a) { } 540 541 template<typename _InputIterator> 542 unordered_multiset(_InputIterator __first, _InputIterator __last, 543 size_type __n = 0, 544 const hasher& __hf = hasher(), 545 const key_equal& __eql = key_equal(), 546 const allocator_type& __a = allocator_type()) 547 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, 548 __last)), 549 __gnu_debug::__base(__last), __n, 550 __hf, __eql, __a) { } 551 552 unordered_multiset(const unordered_multiset&) = default; 553 554 unordered_multiset(const _Base& __x) 555 : _Base(__x) { } 556 557 unordered_multiset(unordered_multiset&&) = default; 558 559 explicit 560 unordered_multiset(const allocator_type& __a) 561 : _Base(__a) 562 { } 563 564 unordered_multiset(const unordered_multiset& __uset, 565 const allocator_type& __a) 566 : _Base(__uset._M_base(), __a) 567 { } 568 569 unordered_multiset(unordered_multiset&& __uset, 570 const allocator_type& __a) 571 : _Base(std::move(__uset._M_base()), __a) 572 { } 573 574 unordered_multiset(initializer_list<value_type> __l, 575 size_type __n = 0, 576 const hasher& __hf = hasher(), 577 const key_equal& __eql = key_equal(), 578 const allocator_type& __a = allocator_type()) 579 : _Base(__l, __n, __hf, __eql, __a) { } 580 581 ~unordered_multiset() noexcept { } 582 583 unordered_multiset& 584 operator=(const unordered_multiset& __x) 585 { 586 _M_base() = __x._M_base(); 587 this->_M_invalidate_all(); 588 return *this; 589 } 590 591 unordered_multiset& 592 operator=(unordered_multiset&& __x) 593 noexcept(_Alloc_traits::_S_nothrow_move()) 594 { 595 __glibcxx_check_self_move_assign(__x); 596 bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign() 597 || __x.get_allocator() == this->get_allocator(); 598 _M_base() = std::move(__x._M_base()); 599 if (__xfer_memory) 600 this->_M_swap(__x); 601 else 602 this->_M_invalidate_all(); 603 __x._M_invalidate_all(); 604 return *this; 605 } 606 607 unordered_multiset& 608 operator=(initializer_list<value_type> __l) 609 { 610 _M_base() = __l; 611 this->_M_invalidate_all(); 612 return *this; 613 } 614 615 void 616 swap(unordered_multiset& __x) 617 noexcept(_Alloc_traits::_S_nothrow_swap()) 618 { 619 if (!_Alloc_traits::_S_propagate_on_swap()) 620 __glibcxx_check_equal_allocs(__x); 621 _Base::swap(__x); 622 _Safe_base::_M_swap(__x); 623 } 624 625 void 626 clear() noexcept 627 { 628 _Base::clear(); 629 this->_M_invalidate_all(); 630 } 631 632 iterator 633 begin() noexcept 634 { return iterator(_Base::begin(), this); } 635 636 const_iterator 637 begin() const noexcept 638 { return const_iterator(_Base::begin(), this); } 639 640 iterator 641 end() noexcept 642 { return iterator(_Base::end(), this); } 643 644 const_iterator 645 end() const noexcept 646 { return const_iterator(_Base::end(), this); } 647 648 const_iterator 649 cbegin() const noexcept 650 { return const_iterator(_Base::begin(), this); } 651 652 const_iterator 653 cend() const noexcept 654 { return const_iterator(_Base::end(), this); } 655 656 // local versions 657 local_iterator 658 begin(size_type __b) 659 { 660 __glibcxx_check_bucket_index(__b); 661 return local_iterator(_Base::begin(__b), this); 662 } 663 664 local_iterator 665 end(size_type __b) 666 { 667 __glibcxx_check_bucket_index(__b); 668 return local_iterator(_Base::end(__b), this); 669 } 670 671 const_local_iterator 672 begin(size_type __b) const 673 { 674 __glibcxx_check_bucket_index(__b); 675 return const_local_iterator(_Base::begin(__b), this); 676 } 677 678 const_local_iterator 679 end(size_type __b) const 680 { 681 __glibcxx_check_bucket_index(__b); 682 return const_local_iterator(_Base::end(__b), this); 683 } 684 685 const_local_iterator 686 cbegin(size_type __b) const 687 { 688 __glibcxx_check_bucket_index(__b); 689 return const_local_iterator(_Base::cbegin(__b), this); 690 } 691 692 const_local_iterator 693 cend(size_type __b) const 694 { 695 __glibcxx_check_bucket_index(__b); 696 return const_local_iterator(_Base::cend(__b), this); 697 } 698 699 size_type 700 bucket_size(size_type __b) const 701 { 702 __glibcxx_check_bucket_index(__b); 703 return _Base::bucket_size(__b); 704 } 705 706 float 707 max_load_factor() const noexcept 708 { return _Base::max_load_factor(); } 709 710 void 711 max_load_factor(float __f) 712 { 713 __glibcxx_check_max_load_factor(__f); 714 _Base::max_load_factor(__f); 715 } 716 717 template<typename... _Args> 718 iterator 719 emplace(_Args&&... __args) 720 { 721 size_type __bucket_count = this->bucket_count(); 722 _Base_iterator __it 723 = _Base::emplace(std::forward<_Args>(__args)...); 724 _M_check_rehashed(__bucket_count); 725 return iterator(__it, this); 726 } 727 728 template<typename... _Args> 729 iterator 730 emplace_hint(const_iterator __hint, _Args&&... __args) 731 { 732 __glibcxx_check_insert(__hint); 733 size_type __bucket_count = this->bucket_count(); 734 _Base_iterator __it = _Base::emplace_hint(__hint.base(), 735 std::forward<_Args>(__args)...); 736 _M_check_rehashed(__bucket_count); 737 return iterator(__it, this); 738 } 739 740 iterator 741 insert(const value_type& __obj) 742 { 743 size_type __bucket_count = this->bucket_count(); 744 _Base_iterator __it = _Base::insert(__obj); 745 _M_check_rehashed(__bucket_count); 746 return iterator(__it, this); 747 } 748 749 iterator 750 insert(const_iterator __hint, const value_type& __obj) 751 { 752 __glibcxx_check_insert(__hint); 753 size_type __bucket_count = this->bucket_count(); 754 _Base_iterator __it = _Base::insert(__hint.base(), __obj); 755 _M_check_rehashed(__bucket_count); 756 return iterator(__it, this); 757 } 758 759 iterator 760 insert(value_type&& __obj) 761 { 762 size_type __bucket_count = this->bucket_count(); 763 _Base_iterator __it = _Base::insert(std::move(__obj)); 764 _M_check_rehashed(__bucket_count); 765 return iterator(__it, this); 766 } 767 768 iterator 769 insert(const_iterator __hint, value_type&& __obj) 770 { 771 __glibcxx_check_insert(__hint); 772 size_type __bucket_count = this->bucket_count(); 773 _Base_iterator __it = _Base::insert(__hint.base(), std::move(__obj)); 774 _M_check_rehashed(__bucket_count); 775 return iterator(__it, this); 776 } 777 778 void 779 insert(std::initializer_list<value_type> __l) 780 { 781 size_type __bucket_count = this->bucket_count(); 782 _Base::insert(__l); 783 _M_check_rehashed(__bucket_count); 784 } 785 786 template<typename _InputIterator> 787 void 788 insert(_InputIterator __first, _InputIterator __last) 789 { 790 __glibcxx_check_valid_range(__first, __last); 791 size_type __bucket_count = this->bucket_count(); 792 _Base::insert(__gnu_debug::__base(__first), 793 __gnu_debug::__base(__last)); 794 _M_check_rehashed(__bucket_count); 795 } 796 797 iterator 798 find(const key_type& __key) 799 { return iterator(_Base::find(__key), this); } 800 801 const_iterator 802 find(const key_type& __key) const 803 { return const_iterator(_Base::find(__key), this); } 804 805 std::pair<iterator, iterator> 806 equal_range(const key_type& __key) 807 { 808 typedef std::pair<_Base_iterator, _Base_iterator> __pair_type; 809 __pair_type __res = _Base::equal_range(__key); 810 return std::make_pair(iterator(__res.first, this), 811 iterator(__res.second, this)); 812 } 813 814 std::pair<const_iterator, const_iterator> 815 equal_range(const key_type& __key) const 816 { 817 std::pair<_Base_const_iterator, _Base_const_iterator> 818 __res = _Base::equal_range(__key); 819 return std::make_pair(const_iterator(__res.first, this), 820 const_iterator(__res.second, this)); 821 } 822 823 size_type 824 erase(const key_type& __key) 825 { 826 size_type __ret(0); 827 std::pair<_Base_iterator, _Base_iterator> __pair = 828 _Base::equal_range(__key); 829 for (_Base_iterator __victim = __pair.first; __victim != __pair.second;) 830 { 831 this->_M_invalidate_if([__victim](_Base_const_iterator __it) 832 { return __it == __victim; }); 833 this->_M_invalidate_local_if( 834 [__victim](_Base_const_local_iterator __it) 835 { return __it._M_curr() == __victim._M_cur; }); 836 _Base::erase(__victim++); 837 ++__ret; 838 } 839 return __ret; 840 } 841 842 iterator 843 erase(const_iterator __it) 844 { 845 __glibcxx_check_erase(__it); 846 _Base_const_iterator __victim = __it.base(); 847 this->_M_invalidate_if([__victim](_Base_const_iterator __it) 848 { return __it == __victim; }); 849 this->_M_invalidate_local_if( 850 [__victim](_Base_const_local_iterator __it) 851 { return __it._M_curr() == __victim._M_cur; }); 852 return iterator(_Base::erase(__it.base()), this); 853 } 854 855 iterator 856 erase(iterator __it) 857 { return erase(const_iterator(__it)); } 858 859 iterator 860 erase(const_iterator __first, const_iterator __last) 861 { 862 __glibcxx_check_erase_range(__first, __last); 863 for (_Base_const_iterator __tmp = __first.base(); 864 __tmp != __last.base(); ++__tmp) 865 { 866 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(), 867 _M_message(__gnu_debug::__msg_valid_range) 868 ._M_iterator(__first, "first") 869 ._M_iterator(__last, "last")); 870 this->_M_invalidate_if([__tmp](_Base_const_iterator __it) 871 { return __it == __tmp; }); 872 this->_M_invalidate_local_if( 873 [__tmp](_Base_const_local_iterator __it) 874 { return __it._M_curr() == __tmp._M_cur; }); 875 } 876 return iterator(_Base::erase(__first.base(), 877 __last.base()), this); 878 } 879 880 _Base& 881 _M_base() noexcept { return *this; } 882 883 const _Base& 884 _M_base() const noexcept { return *this; } 885 886 private: 887 void 888 _M_invalidate_locals() 889 { 890 _Base_local_iterator __local_end = _Base::end(0); 891 this->_M_invalidate_local_if( 892 [__local_end](_Base_const_local_iterator __it) 893 { return __it != __local_end; }); 894 } 895 896 void 897 _M_invalidate_all() 898 { 899 _Base_iterator __end = _Base::end(); 900 this->_M_invalidate_if([__end](_Base_const_iterator __it) 901 { return __it != __end; }); 902 _M_invalidate_locals(); 903 } 904 905 void 906 _M_check_rehashed(size_type __prev_count) 907 { 908 if (__prev_count != this->bucket_count()) 909 _M_invalidate_locals(); 910 } 911 }; 912 913 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 914 inline void 915 swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, 916 unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) 917 { __x.swap(__y); } 918 919 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 920 inline bool 921 operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, 922 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) 923 { return __x._M_base() == __y._M_base(); } 924 925 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 926 inline bool 927 operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, 928 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) 929 { return !(__x == __y); } 930 931} // namespace __debug 932} // namespace std 933 934#endif // C++11 935 936#endif 937