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