|
libstdc++
|
00001 // Debugging unordered_set/unordered_multiset implementation -*- C++ -*- 00002 00003 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013 00004 // Free Software Foundation, Inc. 00005 // 00006 // This file is part of the GNU ISO C++ Library. This library is free 00007 // software; you can redistribute it and/or modify it under the 00008 // terms of the GNU General Public License as published by the 00009 // Free Software Foundation; either version 3, or (at your option) 00010 // any later version. 00011 00012 // This library is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 00017 // Under Section 7 of GPL version 3, you are granted additional 00018 // permissions described in the GCC Runtime Library Exception, version 00019 // 3.1, as published by the Free Software Foundation. 00020 00021 // You should have received a copy of the GNU General Public License and 00022 // a copy of the GCC Runtime Library Exception along with this program; 00023 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 00024 // <http://www.gnu.org/licenses/>. 00025 00026 /** @file debug/unordered_set 00027 * This file is a GNU debug extension to the Standard C++ Library. 00028 */ 00029 00030 #ifndef _GLIBCXX_DEBUG_UNORDERED_SET 00031 #define _GLIBCXX_DEBUG_UNORDERED_SET 1 00032 00033 #ifndef __GXX_EXPERIMENTAL_CXX0X__ 00034 # include <bits/c++0x_warning.h> 00035 #else 00036 # include <unordered_set> 00037 00038 #include <debug/safe_unordered_container.h> 00039 #include <debug/safe_iterator.h> 00040 #include <debug/safe_local_iterator.h> 00041 00042 namespace std _GLIBCXX_VISIBILITY(default) 00043 { 00044 namespace __debug 00045 { 00046 /// Class std::unordered_set with safety/checking/debug instrumentation. 00047 template<typename _Value, 00048 typename _Hash = std::hash<_Value>, 00049 typename _Pred = std::equal_to<_Value>, 00050 typename _Alloc = std::allocator<_Value> > 00051 class unordered_set 00052 : public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc>, 00053 public __gnu_debug::_Safe_unordered_container<unordered_set<_Value, _Hash, 00054 _Pred, _Alloc> > 00055 { 00056 typedef _GLIBCXX_STD_C::unordered_set<_Value, _Hash, 00057 _Pred, _Alloc> _Base; 00058 typedef __gnu_debug::_Safe_unordered_container<unordered_set> _Safe_base; 00059 typedef typename _Base::const_iterator _Base_const_iterator; 00060 typedef typename _Base::iterator _Base_iterator; 00061 typedef typename _Base::const_local_iterator _Base_const_local_iterator; 00062 typedef typename _Base::local_iterator _Base_local_iterator; 00063 00064 public: 00065 typedef typename _Base::size_type size_type; 00066 typedef typename _Base::hasher hasher; 00067 typedef typename _Base::key_equal key_equal; 00068 typedef typename _Base::allocator_type allocator_type; 00069 00070 typedef typename _Base::key_type key_type; 00071 typedef typename _Base::value_type value_type; 00072 00073 typedef __gnu_debug::_Safe_iterator<_Base_iterator, 00074 unordered_set> iterator; 00075 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, 00076 unordered_set> const_iterator; 00077 typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator, 00078 unordered_set> local_iterator; 00079 typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator, 00080 unordered_set> const_local_iterator; 00081 00082 explicit 00083 unordered_set(size_type __n = 10, 00084 const hasher& __hf = hasher(), 00085 const key_equal& __eql = key_equal(), 00086 const allocator_type& __a = allocator_type()) 00087 : _Base(__n, __hf, __eql, __a) { } 00088 00089 template<typename _InputIterator> 00090 unordered_set(_InputIterator __first, _InputIterator __last, 00091 size_type __n = 0, 00092 const hasher& __hf = hasher(), 00093 const key_equal& __eql = key_equal(), 00094 const allocator_type& __a = allocator_type()) 00095 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, 00096 __last)), 00097 __gnu_debug::__base(__last), __n, 00098 __hf, __eql, __a) { } 00099 00100 unordered_set(const unordered_set& __x) = default; 00101 00102 unordered_set(const _Base& __x) 00103 : _Base(__x) { } 00104 00105 unordered_set(unordered_set&& __x) = default; 00106 00107 unordered_set(initializer_list<value_type> __l, 00108 size_type __n = 0, 00109 const hasher& __hf = hasher(), 00110 const key_equal& __eql = key_equal(), 00111 const allocator_type& __a = allocator_type()) 00112 : _Base(__l, __n, __hf, __eql, __a) { } 00113 00114 ~unordered_set() noexcept { } 00115 00116 unordered_set& 00117 operator=(const unordered_set& __x) 00118 { 00119 *static_cast<_Base*>(this) = __x; 00120 this->_M_invalidate_all(); 00121 return *this; 00122 } 00123 00124 unordered_set& 00125 operator=(unordered_set&& __x) 00126 { 00127 // NB: DR 1204. 00128 // NB: DR 675. 00129 clear(); 00130 swap(__x); 00131 return *this; 00132 } 00133 00134 unordered_set& 00135 operator=(initializer_list<value_type> __l) 00136 { 00137 this->clear(); 00138 this->insert(__l); 00139 return *this; 00140 } 00141 00142 void 00143 swap(unordered_set& __x) 00144 { 00145 _Base::swap(__x); 00146 _Safe_base::_M_swap(__x); 00147 } 00148 00149 void 00150 clear() noexcept 00151 { 00152 _Base::clear(); 00153 this->_M_invalidate_all(); 00154 } 00155 00156 iterator 00157 begin() noexcept 00158 { return iterator(_Base::begin(), this); } 00159 00160 const_iterator 00161 begin() const noexcept 00162 { return const_iterator(_Base::begin(), this); } 00163 00164 iterator 00165 end() noexcept 00166 { return iterator(_Base::end(), this); } 00167 00168 const_iterator 00169 end() const noexcept 00170 { return const_iterator(_Base::end(), this); } 00171 00172 const_iterator 00173 cbegin() const noexcept 00174 { return const_iterator(_Base::begin(), this); } 00175 00176 const_iterator 00177 cend() const noexcept 00178 { return const_iterator(_Base::end(), this); } 00179 00180 // local versions 00181 local_iterator 00182 begin(size_type __b) 00183 { return local_iterator(_Base::begin(__b), __b, this); } 00184 00185 local_iterator 00186 end(size_type __b) 00187 { return local_iterator(_Base::end(__b), __b, this); } 00188 00189 const_local_iterator 00190 begin(size_type __b) const 00191 { return const_local_iterator(_Base::begin(__b), __b, this); } 00192 00193 const_local_iterator 00194 end(size_type __b) const 00195 { return const_local_iterator(_Base::end(__b), __b, this); } 00196 00197 const_local_iterator 00198 cbegin(size_type __b) const 00199 { return const_local_iterator(_Base::cbegin(__b), __b, this); } 00200 00201 const_local_iterator 00202 cend(size_type __b) const 00203 { return const_local_iterator(_Base::cend(__b), __b, this); } 00204 00205 template<typename... _Args> 00206 std::pair<iterator, bool> 00207 emplace(_Args&&... __args) 00208 { 00209 size_type __bucket_count = this->bucket_count(); 00210 std::pair<_Base_iterator, bool> __res 00211 = _Base::emplace(std::forward<_Args>(__args)...); 00212 _M_check_rehashed(__bucket_count); 00213 return std::make_pair(iterator(__res.first, this), __res.second); 00214 } 00215 00216 template<typename... _Args> 00217 iterator 00218 emplace_hint(const_iterator __hint, _Args&&... __args) 00219 { 00220 __glibcxx_check_insert(__hint); 00221 size_type __bucket_count = this->bucket_count(); 00222 _Base_iterator __it = _Base::emplace_hint(__hint.base(), 00223 std::forward<_Args>(__args)...); 00224 _M_check_rehashed(__bucket_count); 00225 return iterator(__it, this); 00226 } 00227 00228 std::pair<iterator, bool> 00229 insert(const value_type& __obj) 00230 { 00231 size_type __bucket_count = this->bucket_count(); 00232 typedef std::pair<_Base_iterator, bool> __pair_type; 00233 __pair_type __res = _Base::insert(__obj); 00234 _M_check_rehashed(__bucket_count); 00235 return std::make_pair(iterator(__res.first, this), __res.second); 00236 } 00237 00238 iterator 00239 insert(const_iterator __hint, const value_type& __obj) 00240 { 00241 __glibcxx_check_insert(__hint); 00242 size_type __bucket_count = this->bucket_count(); 00243 _Base_iterator __it = _Base::insert(__hint.base(), __obj); 00244 _M_check_rehashed(__bucket_count); 00245 return iterator(__it, this); 00246 } 00247 00248 std::pair<iterator, bool> 00249 insert(value_type&& __obj) 00250 { 00251 size_type __bucket_count = this->bucket_count(); 00252 typedef std::pair<typename _Base::iterator, bool> __pair_type; 00253 __pair_type __res = _Base::insert(std::move(__obj)); 00254 _M_check_rehashed(__bucket_count); 00255 return std::make_pair(iterator(__res.first, this), __res.second); 00256 } 00257 00258 iterator 00259 insert(const_iterator __hint, value_type&& __obj) 00260 { 00261 __glibcxx_check_insert(__hint); 00262 size_type __bucket_count = this->bucket_count(); 00263 _Base_iterator __it = _Base::insert(__hint.base(), std::move(__obj)); 00264 _M_check_rehashed(__bucket_count); 00265 return iterator(__it, this); 00266 } 00267 00268 void 00269 insert(std::initializer_list<value_type> __l) 00270 { 00271 size_type __bucket_count = this->bucket_count(); 00272 _Base::insert(__l); 00273 _M_check_rehashed(__bucket_count); 00274 } 00275 00276 template<typename _InputIterator> 00277 void 00278 insert(_InputIterator __first, _InputIterator __last) 00279 { 00280 __glibcxx_check_valid_range(__first, __last); 00281 size_type __bucket_count = this->bucket_count(); 00282 _Base::insert(__gnu_debug::__base(__first), 00283 __gnu_debug::__base(__last)); 00284 _M_check_rehashed(__bucket_count); 00285 } 00286 00287 iterator 00288 find(const key_type& __key) 00289 { return iterator(_Base::find(__key), this); } 00290 00291 const_iterator 00292 find(const key_type& __key) const 00293 { return const_iterator(_Base::find(__key), this); } 00294 00295 std::pair<iterator, iterator> 00296 equal_range(const key_type& __key) 00297 { 00298 typedef std::pair<_Base_iterator, _Base_iterator> __pair_type; 00299 __pair_type __res = _Base::equal_range(__key); 00300 return std::make_pair(iterator(__res.first, this), 00301 iterator(__res.second, this)); 00302 } 00303 00304 std::pair<const_iterator, const_iterator> 00305 equal_range(const key_type& __key) const 00306 { 00307 std::pair<_Base_const_iterator, _Base_const_iterator> 00308 __res = _Base::equal_range(__key); 00309 return std::make_pair(const_iterator(__res.first, this), 00310 const_iterator(__res.second, this)); 00311 } 00312 00313 size_type 00314 erase(const key_type& __key) 00315 { 00316 size_type __ret(0); 00317 _Base_iterator __victim(_Base::find(__key)); 00318 if (__victim != _Base::end()) 00319 { 00320 this->_M_invalidate_if( 00321 [__victim](_Base_const_iterator __it) 00322 { return __it == __victim; }); 00323 _Base_local_iterator __local_victim = _S_to_local(__victim); 00324 this->_M_invalidate_local_if( 00325 [__local_victim](_Base_const_local_iterator __it) 00326 { return __it == __local_victim; }); 00327 size_type __bucket_count = this->bucket_count(); 00328 _Base::erase(__victim); 00329 _M_check_rehashed(__bucket_count); 00330 __ret = 1; 00331 } 00332 return __ret; 00333 } 00334 00335 iterator 00336 erase(const_iterator __it) 00337 { 00338 __glibcxx_check_erase(__it); 00339 _Base_const_iterator __victim = __it.base(); 00340 this->_M_invalidate_if( 00341 [__victim](_Base_const_iterator __it) 00342 { return __it == __victim; }); 00343 _Base_const_local_iterator __local_victim = _S_to_local(__victim); 00344 this->_M_invalidate_local_if( 00345 [__local_victim](_Base_const_local_iterator __it) 00346 { return __it == __local_victim; }); 00347 size_type __bucket_count = this->bucket_count(); 00348 _Base_iterator __next = _Base::erase(__it.base()); 00349 _M_check_rehashed(__bucket_count); 00350 return iterator(__next, this); 00351 } 00352 00353 iterator 00354 erase(iterator __it) 00355 { return erase(const_iterator(__it)); } 00356 00357 iterator 00358 erase(const_iterator __first, const_iterator __last) 00359 { 00360 __glibcxx_check_erase_range(__first, __last); 00361 for (_Base_const_iterator __tmp = __first.base(); 00362 __tmp != __last.base(); ++__tmp) 00363 { 00364 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(), 00365 _M_message(__gnu_debug::__msg_valid_range) 00366 ._M_iterator(__first, "first") 00367 ._M_iterator(__last, "last")); 00368 this->_M_invalidate_if( 00369 [__tmp](_Base_const_iterator __it) 00370 { return __it == __tmp; }); 00371 _Base_const_local_iterator __local_tmp = _S_to_local(__tmp); 00372 this->_M_invalidate_local_if( 00373 [__local_tmp](_Base_const_local_iterator __it) 00374 { return __it == __local_tmp; }); 00375 } 00376 size_type __bucket_count = this->bucket_count(); 00377 _Base_iterator __next = _Base::erase(__first.base(), 00378 __last.base()); 00379 _M_check_rehashed(__bucket_count); 00380 return iterator(__next, this); 00381 } 00382 00383 _Base& 00384 _M_base() noexcept { return *this; } 00385 00386 const _Base& 00387 _M_base() const noexcept { return *this; } 00388 00389 private: 00390 void 00391 _M_invalidate_locals() 00392 { 00393 _Base_local_iterator __local_end = _Base::end(0); 00394 this->_M_invalidate_local_if( 00395 [__local_end](_Base_const_local_iterator __it) 00396 { return __it != __local_end; }); 00397 } 00398 00399 void 00400 _M_invalidate_all() 00401 { 00402 _Base_iterator __end = _Base::end(); 00403 this->_M_invalidate_if( 00404 [__end](_Base_const_iterator __it) 00405 { return __it != __end; }); 00406 _M_invalidate_locals(); 00407 } 00408 00409 void 00410 _M_check_rehashed(size_type __prev_count) 00411 { 00412 if (__prev_count != this->bucket_count()) 00413 _M_invalidate_locals(); 00414 } 00415 00416 static _Base_local_iterator 00417 _S_to_local(_Base_iterator __it) 00418 { 00419 // The returned local iterator will not be incremented so we don't 00420 // need to compute __it's node bucket 00421 return _Base_local_iterator(__it._M_cur, 0, 0); 00422 } 00423 00424 static _Base_const_local_iterator 00425 _S_to_local(_Base_const_iterator __it) 00426 { 00427 // The returned local iterator will not be incremented so we don't 00428 // need to compute __it's node bucket 00429 return _Base_const_local_iterator(__it._M_cur, 0, 0); 00430 } 00431 }; 00432 00433 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 00434 inline void 00435 swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, 00436 unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) 00437 { __x.swap(__y); } 00438 00439 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 00440 inline bool 00441 operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, 00442 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) 00443 { return __x._M_equal(__y); } 00444 00445 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 00446 inline bool 00447 operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, 00448 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) 00449 { return !(__x == __y); } 00450 00451 00452 /// Class std::unordered_multiset with safety/checking/debug instrumentation. 00453 template<typename _Value, 00454 typename _Hash = std::hash<_Value>, 00455 typename _Pred = std::equal_to<_Value>, 00456 typename _Alloc = std::allocator<_Value> > 00457 class unordered_multiset 00458 : public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>, 00459 public __gnu_debug::_Safe_unordered_container< 00460 unordered_multiset<_Value, _Hash, _Pred, _Alloc> > 00461 { 00462 typedef _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, 00463 _Pred, _Alloc> _Base; 00464 typedef __gnu_debug::_Safe_unordered_container<unordered_multiset> 00465 _Safe_base; 00466 typedef typename _Base::const_iterator _Base_const_iterator; 00467 typedef typename _Base::iterator _Base_iterator; 00468 typedef typename _Base::const_local_iterator _Base_const_local_iterator; 00469 typedef typename _Base::local_iterator _Base_local_iterator; 00470 00471 public: 00472 typedef typename _Base::size_type size_type; 00473 typedef typename _Base::hasher hasher; 00474 typedef typename _Base::key_equal key_equal; 00475 typedef typename _Base::allocator_type allocator_type; 00476 00477 typedef typename _Base::key_type key_type; 00478 typedef typename _Base::value_type value_type; 00479 00480 typedef __gnu_debug::_Safe_iterator<_Base_iterator, 00481 unordered_multiset> iterator; 00482 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, 00483 unordered_multiset> const_iterator; 00484 typedef __gnu_debug::_Safe_local_iterator< 00485 _Base_local_iterator, unordered_multiset> local_iterator; 00486 typedef __gnu_debug::_Safe_local_iterator< 00487 _Base_const_local_iterator, unordered_multiset> const_local_iterator; 00488 00489 explicit 00490 unordered_multiset(size_type __n = 10, 00491 const hasher& __hf = hasher(), 00492 const key_equal& __eql = key_equal(), 00493 const allocator_type& __a = allocator_type()) 00494 : _Base(__n, __hf, __eql, __a) { } 00495 00496 template<typename _InputIterator> 00497 unordered_multiset(_InputIterator __first, _InputIterator __last, 00498 size_type __n = 0, 00499 const hasher& __hf = hasher(), 00500 const key_equal& __eql = key_equal(), 00501 const allocator_type& __a = allocator_type()) 00502 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, 00503 __last)), 00504 __gnu_debug::__base(__last), __n, 00505 __hf, __eql, __a) { } 00506 00507 unordered_multiset(const unordered_multiset& __x) = default; 00508 00509 unordered_multiset(const _Base& __x) 00510 : _Base(__x) { } 00511 00512 unordered_multiset(unordered_multiset&& __x) = default; 00513 00514 unordered_multiset(initializer_list<value_type> __l, 00515 size_type __n = 0, 00516 const hasher& __hf = hasher(), 00517 const key_equal& __eql = key_equal(), 00518 const allocator_type& __a = allocator_type()) 00519 : _Base(__l, __n, __hf, __eql, __a) { } 00520 00521 ~unordered_multiset() noexcept { } 00522 00523 unordered_multiset& 00524 operator=(const unordered_multiset& __x) 00525 { 00526 *static_cast<_Base*>(this) = __x; 00527 this->_M_invalidate_all(); 00528 return *this; 00529 } 00530 00531 unordered_multiset& 00532 operator=(unordered_multiset&& __x) 00533 { 00534 // NB: DR 1204. 00535 // NB: DR 675. 00536 clear(); 00537 swap(__x); 00538 return *this; 00539 } 00540 00541 unordered_multiset& 00542 operator=(initializer_list<value_type> __l) 00543 { 00544 this->clear(); 00545 this->insert(__l); 00546 return *this; 00547 } 00548 00549 void 00550 swap(unordered_multiset& __x) 00551 { 00552 _Base::swap(__x); 00553 _Safe_base::_M_swap(__x); 00554 } 00555 00556 void 00557 clear() noexcept 00558 { 00559 _Base::clear(); 00560 this->_M_invalidate_all(); 00561 } 00562 00563 iterator 00564 begin() noexcept 00565 { return iterator(_Base::begin(), this); } 00566 00567 const_iterator 00568 begin() const noexcept 00569 { return const_iterator(_Base::begin(), this); } 00570 00571 iterator 00572 end() noexcept 00573 { return iterator(_Base::end(), this); } 00574 00575 const_iterator 00576 end() const noexcept 00577 { return const_iterator(_Base::end(), this); } 00578 00579 const_iterator 00580 cbegin() const noexcept 00581 { return const_iterator(_Base::begin(), this); } 00582 00583 const_iterator 00584 cend() const noexcept 00585 { return const_iterator(_Base::end(), this); } 00586 00587 // local versions 00588 local_iterator 00589 begin(size_type __b) 00590 { return local_iterator(_Base::begin(__b), __b, this); } 00591 00592 local_iterator 00593 end(size_type __b) 00594 { return local_iterator(_Base::end(__b), __b, this); } 00595 00596 const_local_iterator 00597 begin(size_type __b) const 00598 { return const_local_iterator(_Base::begin(__b), __b, this); } 00599 00600 const_local_iterator 00601 end(size_type __b) const 00602 { return const_local_iterator(_Base::end(__b), __b, this); } 00603 00604 const_local_iterator 00605 cbegin(size_type __b) const 00606 { return const_local_iterator(_Base::cbegin(__b), __b, this); } 00607 00608 const_local_iterator 00609 cend(size_type __b) const 00610 { return const_local_iterator(_Base::cend(__b), __b, this); } 00611 00612 template<typename... _Args> 00613 iterator 00614 emplace(_Args&&... __args) 00615 { 00616 size_type __bucket_count = this->bucket_count(); 00617 _Base_iterator __it 00618 = _Base::emplace(std::forward<_Args>(__args)...); 00619 _M_check_rehashed(__bucket_count); 00620 return iterator(__it, this); 00621 } 00622 00623 template<typename... _Args> 00624 iterator 00625 emplace_hint(const_iterator __hint, _Args&&... __args) 00626 { 00627 __glibcxx_check_insert(__hint); 00628 size_type __bucket_count = this->bucket_count(); 00629 _Base_iterator __it = _Base::emplace_hint(__hint.base(), 00630 std::forward<_Args>(__args)...); 00631 _M_check_rehashed(__bucket_count); 00632 return iterator(__it, this); 00633 } 00634 00635 iterator 00636 insert(const value_type& __obj) 00637 { 00638 size_type __bucket_count = this->bucket_count(); 00639 _Base_iterator __it = _Base::insert(__obj); 00640 _M_check_rehashed(__bucket_count); 00641 return iterator(__it, this); 00642 } 00643 00644 iterator 00645 insert(const_iterator __hint, const value_type& __obj) 00646 { 00647 __glibcxx_check_insert(__hint); 00648 size_type __bucket_count = this->bucket_count(); 00649 _Base_iterator __it = _Base::insert(__hint.base(), __obj); 00650 _M_check_rehashed(__bucket_count); 00651 return iterator(__it, this); 00652 } 00653 00654 iterator 00655 insert(value_type&& __obj) 00656 { 00657 size_type __bucket_count = this->bucket_count(); 00658 _Base_iterator __it = _Base::insert(std::move(__obj)); 00659 _M_check_rehashed(__bucket_count); 00660 return iterator(__it, this); 00661 } 00662 00663 iterator 00664 insert(const_iterator __hint, value_type&& __obj) 00665 { 00666 __glibcxx_check_insert(__hint); 00667 size_type __bucket_count = this->bucket_count(); 00668 _Base_iterator __it = _Base::insert(__hint.base(), std::move(__obj)); 00669 _M_check_rehashed(__bucket_count); 00670 return iterator(__it, this); 00671 } 00672 00673 void 00674 insert(std::initializer_list<value_type> __l) 00675 { 00676 size_type __bucket_count = this->bucket_count(); 00677 _Base::insert(__l); 00678 _M_check_rehashed(__bucket_count); 00679 } 00680 00681 template<typename _InputIterator> 00682 void 00683 insert(_InputIterator __first, _InputIterator __last) 00684 { 00685 __glibcxx_check_valid_range(__first, __last); 00686 size_type __bucket_count = this->bucket_count(); 00687 _Base::insert(__gnu_debug::__base(__first), 00688 __gnu_debug::__base(__last)); 00689 _M_check_rehashed(__bucket_count); 00690 } 00691 00692 iterator 00693 find(const key_type& __key) 00694 { return iterator(_Base::find(__key), this); } 00695 00696 const_iterator 00697 find(const key_type& __key) const 00698 { return const_iterator(_Base::find(__key), this); } 00699 00700 std::pair<iterator, iterator> 00701 equal_range(const key_type& __key) 00702 { 00703 typedef std::pair<_Base_iterator, _Base_iterator> __pair_type; 00704 __pair_type __res = _Base::equal_range(__key); 00705 return std::make_pair(iterator(__res.first, this), 00706 iterator(__res.second, this)); 00707 } 00708 00709 std::pair<const_iterator, const_iterator> 00710 equal_range(const key_type& __key) const 00711 { 00712 std::pair<_Base_const_iterator, _Base_const_iterator> 00713 __res = _Base::equal_range(__key); 00714 return std::make_pair(const_iterator(__res.first, this), 00715 const_iterator(__res.second, this)); 00716 } 00717 00718 size_type 00719 erase(const key_type& __key) 00720 { 00721 size_type __ret(0); 00722 std::pair<_Base_iterator, _Base_iterator> __pair = 00723 _Base::equal_range(__key); 00724 for (_Base_iterator __victim = __pair.first; __victim != __pair.second;) 00725 { 00726 this->_M_invalidate_if([__victim](_Base_const_iterator __it) 00727 { return __it == __victim; }); 00728 _Base_local_iterator __local_victim = _S_to_local(__victim); 00729 this->_M_invalidate_local_if( 00730 [__local_victim](_Base_const_local_iterator __it) 00731 { return __it == __local_victim; }); 00732 _Base::erase(__victim++); 00733 ++__ret; 00734 } 00735 return __ret; 00736 } 00737 00738 iterator 00739 erase(const_iterator __it) 00740 { 00741 __glibcxx_check_erase(__it); 00742 _Base_const_iterator __victim = __it.base(); 00743 this->_M_invalidate_if([__victim](_Base_const_iterator __it) 00744 { return __it == __victim; }); 00745 _Base_const_local_iterator __local_victim = _S_to_local(__victim); 00746 this->_M_invalidate_local_if( 00747 [__local_victim](_Base_const_local_iterator __it) 00748 { return __it == __local_victim; }); 00749 return iterator(_Base::erase(__it.base()), this); 00750 } 00751 00752 iterator 00753 erase(iterator __it) 00754 { return erase(const_iterator(__it)); } 00755 00756 iterator 00757 erase(const_iterator __first, const_iterator __last) 00758 { 00759 __glibcxx_check_erase_range(__first, __last); 00760 for (_Base_const_iterator __tmp = __first.base(); 00761 __tmp != __last.base(); ++__tmp) 00762 { 00763 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(), 00764 _M_message(__gnu_debug::__msg_valid_range) 00765 ._M_iterator(__first, "first") 00766 ._M_iterator(__last, "last")); 00767 this->_M_invalidate_if([__tmp](_Base_const_iterator __it) 00768 { return __it == __tmp; }); 00769 _Base_const_local_iterator __local_tmp = _S_to_local(__tmp); 00770 this->_M_invalidate_local_if( 00771 [__local_tmp](_Base_const_local_iterator __it) 00772 { return __it == __local_tmp; }); 00773 } 00774 return iterator(_Base::erase(__first.base(), 00775 __last.base()), this); 00776 } 00777 00778 _Base& 00779 _M_base() noexcept { return *this; } 00780 00781 const _Base& 00782 _M_base() const noexcept { return *this; } 00783 00784 private: 00785 void 00786 _M_invalidate_locals() 00787 { 00788 _Base_local_iterator __local_end = _Base::end(0); 00789 this->_M_invalidate_local_if( 00790 [__local_end](_Base_const_local_iterator __it) 00791 { return __it != __local_end; }); 00792 } 00793 00794 void 00795 _M_invalidate_all() 00796 { 00797 _Base_iterator __end = _Base::end(); 00798 this->_M_invalidate_if([__end](_Base_const_iterator __it) 00799 { return __it != __end; }); 00800 _M_invalidate_locals(); 00801 } 00802 00803 void 00804 _M_check_rehashed(size_type __prev_count) 00805 { 00806 if (__prev_count != this->bucket_count()) 00807 _M_invalidate_locals(); 00808 } 00809 00810 static _Base_local_iterator 00811 _S_to_local(_Base_iterator __it) 00812 { 00813 // The returned local iterator will not be incremented so we don't 00814 // need to compute __it's node bucket 00815 return _Base_local_iterator(__it._M_cur, 0, 0); 00816 } 00817 00818 static _Base_const_local_iterator 00819 _S_to_local(_Base_const_iterator __it) 00820 { 00821 // The returned local iterator will not be incremented so we don't 00822 // need to compute __it's node bucket 00823 return _Base_const_local_iterator(__it._M_cur, 0, 0); 00824 } 00825 }; 00826 00827 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 00828 inline void 00829 swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, 00830 unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) 00831 { __x.swap(__y); } 00832 00833 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 00834 inline bool 00835 operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, 00836 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) 00837 { return __x._M_equal(__y); } 00838 00839 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc> 00840 inline bool 00841 operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, 00842 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) 00843 { return !(__x == __y); } 00844 00845 } // namespace __debug 00846 } // namespace std 00847 00848 #endif // __GXX_EXPERIMENTAL_CXX0X__ 00849 00850 #endif