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