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