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