1// Debugging unordered_map/unordered_multimap implementation -*- C++ -*- 2 3// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 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#ifdef __GXX_EXPERIMENTAL_CXX0X__ 34# include <unordered_map> 35#else 36# include <c++0x_warning.h> 37#endif 38 39#include <debug/safe_sequence.h> 40#include <debug/safe_iterator.h> 41#include <initializer_list> 42 43namespace std 44{ 45namespace __debug 46{ 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_D::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>, 53 public __gnu_debug::_Safe_sequence<unordered_map<_Key, _Tp, _Hash, 54 _Pred, _Alloc> > 55 { 56 typedef _GLIBCXX_STD_D::unordered_map<_Key, _Tp, _Hash, 57 _Pred, _Alloc> _Base; 58 typedef __gnu_debug::_Safe_sequence<unordered_map> _Safe_base; 59 60 public: 61 typedef typename _Base::size_type size_type; 62 typedef typename _Base::hasher hasher; 63 typedef typename _Base::key_equal key_equal; 64 typedef typename _Base::allocator_type allocator_type; 65 66 typedef typename _Base::key_type key_type; 67 typedef typename _Base::value_type value_type; 68 69 typedef __gnu_debug::_Safe_iterator<typename _Base::iterator, 70 unordered_map> iterator; 71 typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator, 72 unordered_map> const_iterator; 73 74 explicit 75 unordered_map(size_type __n = 10, 76 const hasher& __hf = hasher(), 77 const key_equal& __eql = key_equal(), 78 const allocator_type& __a = allocator_type()) 79 : _Base(__n, __hf, __eql, __a) { } 80 81 template<typename _InputIterator> 82 unordered_map(_InputIterator __f, _InputIterator __l, 83 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(__gnu_debug::__check_valid_range(__f, __l), __l, __n, 88 __hf, __eql, __a), _Safe_base() { } 89 90 unordered_map(const unordered_map& __x) 91 : _Base(__x), _Safe_base() { } 92 93 unordered_map(const _Base& __x) 94 : _Base(__x), _Safe_base() { } 95 96 unordered_map(unordered_map&& __x) 97 : _Base(std::forward<unordered_map>(__x)), _Safe_base() { } 98 99 unordered_map(initializer_list<value_type> __l, 100 size_type __n = 10, 101 const hasher& __hf = hasher(), 102 const key_equal& __eql = key_equal(), 103 const allocator_type& __a = allocator_type()) 104 : _Base(__l, __n, __hf, __eql, __a), _Safe_base() { } 105 106 unordered_map& 107 operator=(const unordered_map& __x) 108 { 109 *static_cast<_Base*>(this) = __x; 110 this->_M_invalidate_all(); 111 return *this; 112 } 113 114 unordered_map& 115 operator=(unordered_map&& __x) 116 { 117 // NB: DR 675. 118 clear(); 119 swap(__x); 120 return *this; 121 } 122 123 unordered_map& 124 operator=(initializer_list<value_type> __l) 125 { 126 this->clear(); 127 this->insert(__l); 128 return *this; 129 } 130 131 void 132 swap(unordered_map&& __x) 133 { 134 _Base::swap(__x); 135 _Safe_base::_M_swap(__x); 136 } 137 138 void 139 clear() 140 { 141 _Base::clear(); 142 this->_M_invalidate_all(); 143 } 144 145 iterator 146 begin() 147 { return iterator(_Base::begin(), this); } 148 149 const_iterator 150 begin() const 151 { return const_iterator(_Base::begin(), this); } 152 153 iterator 154 end() 155 { return iterator(_Base::end(), this); } 156 157 const_iterator 158 end() const 159 { return const_iterator(_Base::end(), this); } 160 161 const_iterator 162 cbegin() const 163 { return const_iterator(_Base::begin(), this); } 164 165 const_iterator 166 cend() const 167 { return const_iterator(_Base::end(), this); } 168 169 // local versions 170 using _Base::begin; 171 using _Base::end; 172 using _Base::cbegin; 173 using _Base::cend; 174 175 std::pair<iterator, bool> 176 insert(const value_type& __obj) 177 { 178 typedef std::pair<typename _Base::iterator, bool> __pair_type; 179 __pair_type __res = _Base::insert(__obj); 180 return std::make_pair(iterator(__res.first, this), __res.second); 181 } 182 183 iterator 184 insert(iterator, const value_type& __obj) 185 { 186 typedef std::pair<typename _Base::iterator, bool> __pair_type; 187 __pair_type __res = _Base::insert(__obj); 188 return iterator(__res.first, this); 189 } 190 191 const_iterator 192 insert(const_iterator, const value_type& __obj) 193 { 194 typedef std::pair<typename _Base::iterator, bool> __pair_type; 195 __pair_type __res = _Base::insert(__obj); 196 return const_iterator(__res.first, this); 197 } 198 199 void 200 insert(std::initializer_list<value_type> __l) 201 { _Base::insert(__l); } 202 203 template<typename _InputIterator> 204 void 205 insert(_InputIterator __first, _InputIterator __last) 206 { 207 __glibcxx_check_valid_range(__first, __last); 208 _Base::insert(__first, __last); 209 } 210 211 iterator 212 find(const key_type& __key) 213 { return iterator(_Base::find(__key), this); } 214 215 const_iterator 216 find(const key_type& __key) const 217 { return const_iterator(_Base::find(__key), this); } 218 219 std::pair<iterator, iterator> 220 equal_range(const key_type& __key) 221 { 222 typedef typename _Base::iterator _Base_iterator; 223 typedef std::pair<_Base_iterator, _Base_iterator> __pair_type; 224 __pair_type __res = _Base::equal_range(__key); 225 return std::make_pair(iterator(__res.first, this), 226 iterator(__res.second, this)); 227 } 228 229 std::pair<const_iterator, const_iterator> 230 equal_range(const key_type& __key) const 231 { 232 typedef typename _Base::const_iterator _Base_iterator; 233 typedef std::pair<_Base_iterator, _Base_iterator> __pair_type; 234 __pair_type __res = _Base::equal_range(__key); 235 return std::make_pair(const_iterator(__res.first, this), 236 const_iterator(__res.second, this)); 237 } 238 239 size_type 240 erase(const key_type& __key) 241 { 242 size_type __ret(0); 243 iterator __victim(_Base::find(__key), this); 244 if (__victim != end()) 245 { 246 this->erase(__victim); 247 __ret = 1; 248 } 249 return __ret; 250 } 251 252 iterator 253 erase(iterator __it) 254 { 255 __glibcxx_check_erase(__it); 256 __it._M_invalidate(); 257 return iterator(_Base::erase(__it.base()), this); 258 } 259 260 const_iterator 261 erase(const_iterator __it) 262 { 263 __glibcxx_check_erase(__it); 264 __it._M_invalidate(); 265 return const_iterator(_Base::erase(__it.base()), this); 266 } 267 268 iterator 269 erase(iterator __first, iterator __last) 270 { 271 __glibcxx_check_erase_range(__first, __last); 272 for (iterator __tmp = __first; __tmp != __last;) 273 { 274 iterator __victim = __tmp++; 275 __victim._M_invalidate(); 276 } 277 return iterator(_Base::erase(__first.base(), 278 __last.base()), this); 279 } 280 281 const_iterator 282 erase(const_iterator __first, const_iterator __last) 283 { 284 __glibcxx_check_erase_range(__first, __last); 285 for (const_iterator __tmp = __first; __tmp != __last;) 286 { 287 const_iterator __victim = __tmp++; 288 __victim._M_invalidate(); 289 } 290 return const_iterator(_Base::erase(__first.base(), 291 __last.base()), this); 292 } 293 294 _Base& 295 _M_base() { return *this; } 296 297 const _Base& 298 _M_base() const { return *this; } 299 300 private: 301 void 302 _M_invalidate_all() 303 { 304 typedef typename _Base::const_iterator _Base_const_iterator; 305 typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; 306 this->_M_invalidate_if(_Not_equal(_M_base().end())); 307 } 308 }; 309 310 template<typename _Key, typename _Tp, typename _Hash, 311 typename _Pred, typename _Alloc> 312 inline void 313 swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 314 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 315 { __x.swap(__y); } 316 317 template<typename _Key, typename _Tp, typename _Hash, 318 typename _Pred, typename _Alloc> 319 inline void 320 swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>&& __x, 321 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 322 { __x.swap(__y); } 323 324 template<typename _Key, typename _Tp, typename _Hash, 325 typename _Pred, typename _Alloc> 326 inline void 327 swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 328 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>&& __y) 329 { __x.swap(__y); } 330 331 332 template<typename _Key, typename _Tp, 333 typename _Hash = std::hash<_Key>, 334 typename _Pred = std::equal_to<_Key>, 335 typename _Alloc = std::allocator<_Key> > 336 class unordered_multimap 337 : public _GLIBCXX_STD_D::unordered_multimap<_Key, _Tp, _Hash, 338 _Pred, _Alloc>, 339 public __gnu_debug::_Safe_sequence<unordered_multimap<_Key, _Tp, _Hash, 340 _Pred, _Alloc> > 341 { 342 typedef _GLIBCXX_STD_D::unordered_multimap<_Key, _Tp, _Hash, 343 _Pred, _Alloc> _Base; 344 typedef __gnu_debug::_Safe_sequence<unordered_multimap> _Safe_base; 345 346 public: 347 typedef typename _Base::size_type size_type; 348 typedef typename _Base::hasher hasher; 349 typedef typename _Base::key_equal key_equal; 350 typedef typename _Base::allocator_type allocator_type; 351 352 typedef typename _Base::key_type key_type; 353 typedef typename _Base::value_type value_type; 354 355 typedef __gnu_debug::_Safe_iterator<typename _Base::iterator, 356 unordered_multimap> iterator; 357 typedef __gnu_debug::_Safe_iterator<typename _Base::const_iterator, 358 unordered_multimap> const_iterator; 359 360 explicit 361 unordered_multimap(size_type __n = 10, 362 const hasher& __hf = hasher(), 363 const key_equal& __eql = key_equal(), 364 const allocator_type& __a = allocator_type()) 365 : _Base(__n, __hf, __eql, __a) { } 366 367 template<typename _InputIterator> 368 unordered_multimap(_InputIterator __f, _InputIterator __l, 369 size_type __n = 10, 370 const hasher& __hf = hasher(), 371 const key_equal& __eql = key_equal(), 372 const allocator_type& __a = allocator_type()) 373 : _Base(__gnu_debug::__check_valid_range(__f, __l), __l, __n, 374 __hf, __eql, __a), _Safe_base() { } 375 376 unordered_multimap(const unordered_multimap& __x) 377 : _Base(__x), _Safe_base() { } 378 379 unordered_multimap(const _Base& __x) 380 : _Base(__x), _Safe_base() { } 381 382 unordered_multimap(unordered_multimap&& __x) 383 : _Base(std::forward<unordered_multimap>(__x)), _Safe_base() { } 384 385 unordered_multimap(initializer_list<value_type> __l, 386 size_type __n = 10, 387 const hasher& __hf = hasher(), 388 const key_equal& __eql = key_equal(), 389 const allocator_type& __a = allocator_type()) 390 : _Base(__l, __n, __hf, __eql, __a), _Safe_base() { } 391 392 unordered_multimap& 393 operator=(const unordered_multimap& __x) 394 { 395 *static_cast<_Base*>(this) = __x; 396 this->_M_invalidate_all(); 397 return *this; 398 } 399 400 unordered_multimap& 401 operator=(unordered_multimap&& __x) 402 { 403 // NB: DR 675. 404 clear(); 405 swap(__x); 406 return *this; 407 } 408 409 unordered_multimap& 410 operator=(initializer_list<value_type> __l) 411 { 412 this->clear(); 413 this->insert(__l); 414 return *this; 415 } 416 417 void 418 swap(unordered_multimap&& __x) 419 { 420 _Base::swap(__x); 421 _Safe_base::_M_swap(__x); 422 } 423 424 void 425 clear() 426 { 427 _Base::clear(); 428 this->_M_invalidate_all(); 429 } 430 431 iterator 432 begin() 433 { return iterator(_Base::begin(), this); } 434 435 const_iterator 436 begin() const 437 { return const_iterator(_Base::begin(), this); } 438 439 iterator 440 end() 441 { return iterator(_Base::end(), this); } 442 443 const_iterator 444 end() const 445 { return const_iterator(_Base::end(), this); } 446 447 const_iterator 448 cbegin() const 449 { return const_iterator(_Base::begin(), this); } 450 451 const_iterator 452 cend() const 453 { return const_iterator(_Base::end(), this); } 454 455 // local versions 456 using _Base::begin; 457 using _Base::end; 458 using _Base::cbegin; 459 using _Base::cend; 460 461 iterator 462 insert(const value_type& __obj) 463 { return iterator(_Base::insert(__obj), this); } 464 465 iterator 466 insert(iterator, const value_type& __obj) 467 { return iterator(_Base::insert(__obj), this); } 468 469 const_iterator 470 insert(const_iterator, const value_type& __obj) 471 { return const_iterator(_Base::insert(__obj), this); } 472 473 void 474 insert(std::initializer_list<value_type> __l) 475 { _Base::insert(__l); } 476 477 template<typename _InputIterator> 478 void 479 insert(_InputIterator __first, _InputIterator __last) 480 { 481 __glibcxx_check_valid_range(__first, __last); 482 _Base::insert(__first, __last); 483 } 484 485 iterator 486 find(const key_type& __key) 487 { return iterator(_Base::find(__key), this); } 488 489 const_iterator 490 find(const key_type& __key) const 491 { return const_iterator(_Base::find(__key), this); } 492 493 std::pair<iterator, iterator> 494 equal_range(const key_type& __key) 495 { 496 typedef typename _Base::iterator _Base_iterator; 497 typedef std::pair<_Base_iterator, _Base_iterator> __pair_type; 498 __pair_type __res = _Base::equal_range(__key); 499 return std::make_pair(iterator(__res.first, this), 500 iterator(__res.second, this)); 501 } 502 503 std::pair<const_iterator, const_iterator> 504 equal_range(const key_type& __key) const 505 { 506 typedef typename _Base::const_iterator _Base_iterator; 507 typedef std::pair<_Base_iterator, _Base_iterator> __pair_type; 508 __pair_type __res = _Base::equal_range(__key); 509 return std::make_pair(const_iterator(__res.first, this), 510 const_iterator(__res.second, this)); 511 } 512 513 size_type 514 erase(const key_type& __key) 515 { 516 size_type __ret(0); 517 iterator __victim(_Base::find(__key), this); 518 if (__victim != end()) 519 { 520 this->erase(__victim); 521 __ret = 1; 522 } 523 return __ret; 524 } 525 526 iterator 527 erase(iterator __it) 528 { 529 __glibcxx_check_erase(__it); 530 __it._M_invalidate(); 531 return iterator(_Base::erase(__it.base()), this); 532 } 533 534 const_iterator 535 erase(const_iterator __it) 536 { 537 __glibcxx_check_erase(__it); 538 __it._M_invalidate(); 539 return const_iterator(_Base::erase(__it.base()), this); 540 } 541 542 iterator 543 erase(iterator __first, iterator __last) 544 { 545 __glibcxx_check_erase_range(__first, __last); 546 for (iterator __tmp = __first; __tmp != __last;) 547 { 548 iterator __victim = __tmp++; 549 __victim._M_invalidate(); 550 } 551 return iterator(_Base::erase(__first.base(), 552 __last.base()), this); 553 } 554 555 const_iterator 556 erase(const_iterator __first, const_iterator __last) 557 { 558 __glibcxx_check_erase_range(__first, __last); 559 for (const_iterator __tmp = __first; __tmp != __last;) 560 { 561 const_iterator __victim = __tmp++; 562 __victim._M_invalidate(); 563 } 564 return const_iterator(_Base::erase(__first.base(), 565 __last.base()), this); 566 } 567 568 _Base& 569 _M_base() { return *this; } 570 571 const _Base& 572 _M_base() const { return *this; } 573 574 private: 575 void 576 _M_invalidate_all() 577 { 578 typedef typename _Base::const_iterator _Base_const_iterator; 579 typedef __gnu_debug::_Not_equal_to<_Base_const_iterator> _Not_equal; 580 this->_M_invalidate_if(_Not_equal(_M_base().end())); 581 } 582 }; 583 584 template<typename _Key, typename _Tp, typename _Hash, 585 typename _Pred, typename _Alloc> 586 inline void 587 swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 588 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 589 { __x.swap(__y); } 590 591 template<typename _Key, typename _Tp, typename _Hash, 592 typename _Pred, typename _Alloc> 593 inline void 594 swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>&& __x, 595 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 596 { __x.swap(__y); } 597 598 template<typename _Key, typename _Tp, typename _Hash, 599 typename _Pred, typename _Alloc> 600 inline void 601 swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 602 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>&& __y) 603 { __x.swap(__y); } 604 605} // namespace __debug 606} // namespace std 607 608#endif 609