|
libstdc++
|
00001 // Debugging unordered_map/unordered_multimap 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_map 00027 * This file is a GNU debug extension to the Standard C++ Library. 00028 */ 00029 00030 #ifndef _GLIBCXX_DEBUG_UNORDERED_MAP 00031 #define _GLIBCXX_DEBUG_UNORDERED_MAP 1 00032 00033 #ifndef __GXX_EXPERIMENTAL_CXX0X__ 00034 # include <bits/c++0x_warning.h> 00035 #else 00036 # include <unordered_map> 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_map with safety/checking/debug instrumentation. 00047 template<typename _Key, typename _Tp, 00048 typename _Hash = std::hash<_Key>, 00049 typename _Pred = std::equal_to<_Key>, 00050 typename _Alloc = std::allocator<_Key> > 00051 class unordered_map 00052 : public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>, 00053 public __gnu_debug::_Safe_unordered_container<unordered_map<_Key, _Tp, 00054 _Hash, _Pred, _Alloc> > 00055 { 00056 typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, 00057 _Pred, _Alloc> _Base; 00058 typedef __gnu_debug::_Safe_unordered_container<unordered_map> _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_map> iterator; 00075 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, 00076 unordered_map> const_iterator; 00077 typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator, 00078 unordered_map> local_iterator; 00079 typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator, 00080 unordered_map> const_local_iterator; 00081 00082 explicit 00083 unordered_map(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_map(_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_map(const unordered_map& __x) = default; 00101 00102 unordered_map(const _Base& __x) 00103 : _Base(__x) { } 00104 00105 unordered_map(unordered_map&& __x) = default; 00106 00107 unordered_map(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_map() noexcept { } 00115 00116 unordered_map& 00117 operator=(const unordered_map& __x) 00118 { 00119 *static_cast<_Base*>(this) = __x; 00120 this->_M_invalidate_all(); 00121 return *this; 00122 } 00123 00124 unordered_map& 00125 operator=(unordered_map&& __x) 00126 { 00127 // NB: DR 1204. 00128 // NB: DR 675. 00129 clear(); 00130 swap(__x); 00131 return *this; 00132 } 00133 00134 unordered_map& 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_map& __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 std::pair<_Base_iterator, bool> __res = _Base::insert(__obj); 00233 _M_check_rehashed(__bucket_count); 00234 return std::make_pair(iterator(__res.first, this), __res.second); 00235 } 00236 00237 iterator 00238 insert(const_iterator __hint, const value_type& __obj) 00239 { 00240 __glibcxx_check_insert(__hint); 00241 size_type __bucket_count = this->bucket_count(); 00242 _Base_iterator __it = _Base::insert(__hint.base(), __obj); 00243 _M_check_rehashed(__bucket_count); 00244 return iterator(__it, this); 00245 } 00246 00247 template<typename _Pair, typename = typename 00248 std::enable_if<std::is_constructible<value_type, 00249 _Pair&&>::value>::type> 00250 std::pair<iterator, bool> 00251 insert(_Pair&& __obj) 00252 { 00253 size_type __bucket_count = this->bucket_count(); 00254 std::pair<_Base_iterator, bool> __res = 00255 _Base::insert(std::forward<_Pair>(__obj)); 00256 _M_check_rehashed(__bucket_count); 00257 return std::make_pair(iterator(__res.first, this), __res.second); 00258 } 00259 00260 template<typename _Pair, typename = typename 00261 std::enable_if<std::is_constructible<value_type, 00262 _Pair&&>::value>::type> 00263 iterator 00264 insert(const_iterator __hint, _Pair&& __obj) 00265 { 00266 __glibcxx_check_insert(__hint); 00267 size_type __bucket_count = this->bucket_count(); 00268 _Base_iterator __it = 00269 _Base::insert(__hint.base(), std::forward<_Pair>(__obj)); 00270 _M_check_rehashed(__bucket_count); 00271 return iterator(__it, this); 00272 } 00273 00274 void 00275 insert(std::initializer_list<value_type> __l) 00276 { 00277 size_type __bucket_count = this->bucket_count(); 00278 _Base::insert(__l); 00279 _M_check_rehashed(__bucket_count); 00280 } 00281 00282 template<typename _InputIterator> 00283 void 00284 insert(_InputIterator __first, _InputIterator __last) 00285 { 00286 __glibcxx_check_valid_range(__first, __last); 00287 size_type __bucket_count = this->bucket_count(); 00288 _Base::insert(__gnu_debug::__base(__first), 00289 __gnu_debug::__base(__last)); 00290 _M_check_rehashed(__bucket_count); 00291 } 00292 00293 iterator 00294 find(const key_type& __key) 00295 { return iterator(_Base::find(__key), this); } 00296 00297 const_iterator 00298 find(const key_type& __key) const 00299 { return const_iterator(_Base::find(__key), this); } 00300 00301 std::pair<iterator, iterator> 00302 equal_range(const key_type& __key) 00303 { 00304 std::pair<_Base_iterator, _Base_iterator> __res = 00305 _Base::equal_range(__key); 00306 return std::make_pair(iterator(__res.first, this), 00307 iterator(__res.second, this)); 00308 } 00309 00310 std::pair<const_iterator, const_iterator> 00311 equal_range(const key_type& __key) const 00312 { 00313 std::pair<_Base_const_iterator, _Base_const_iterator> __res = 00314 _Base::equal_range(__key); 00315 return std::make_pair(const_iterator(__res.first, this), 00316 const_iterator(__res.second, this)); 00317 } 00318 00319 size_type 00320 erase(const key_type& __key) 00321 { 00322 size_type __ret(0); 00323 _Base_iterator __victim(_Base::find(__key)); 00324 if (__victim != _Base::end()) 00325 { 00326 this->_M_invalidate_if([__victim](_Base_const_iterator __it) 00327 { return __it == __victim; }); 00328 _Base_local_iterator __local_victim = _S_to_local(__victim); 00329 this->_M_invalidate_local_if( 00330 [__local_victim](_Base_const_local_iterator __it) 00331 { return __it == __local_victim; }); 00332 size_type __bucket_count = this->bucket_count(); 00333 _Base::erase(__victim); 00334 _M_check_rehashed(__bucket_count); 00335 __ret = 1; 00336 } 00337 return __ret; 00338 } 00339 00340 iterator 00341 erase(const_iterator __it) 00342 { 00343 __glibcxx_check_erase(__it); 00344 _Base_const_iterator __victim = __it.base(); 00345 this->_M_invalidate_if([__victim](_Base_const_iterator __it) 00346 { return __it == __victim; }); 00347 _Base_const_local_iterator __local_victim = _S_to_local(__victim); 00348 this->_M_invalidate_local_if( 00349 [__local_victim](_Base_const_local_iterator __it) 00350 { return __it == __local_victim; }); 00351 size_type __bucket_count = this->bucket_count(); 00352 _Base_iterator __next = _Base::erase(__it.base()); 00353 _M_check_rehashed(__bucket_count); 00354 return iterator(__next, this); 00355 } 00356 00357 iterator 00358 erase(iterator __it) 00359 { return erase(const_iterator(__it)); } 00360 00361 iterator 00362 erase(const_iterator __first, const_iterator __last) 00363 { 00364 __glibcxx_check_erase_range(__first, __last); 00365 for (_Base_const_iterator __tmp = __first.base(); 00366 __tmp != __last.base(); ++__tmp) 00367 { 00368 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(), 00369 _M_message(__gnu_debug::__msg_valid_range) 00370 ._M_iterator(__first, "first") 00371 ._M_iterator(__last, "last")); 00372 this->_M_invalidate_if([__tmp](_Base_const_iterator __it) 00373 { return __it == __tmp; }); 00374 _Base_const_local_iterator __local_tmp = _S_to_local(__tmp); 00375 this->_M_invalidate_local_if( 00376 [__local_tmp](_Base_const_local_iterator __it) 00377 { return __it == __local_tmp; }); 00378 } 00379 size_type __bucket_count = this->bucket_count(); 00380 _Base_iterator __next = _Base::erase(__first.base(), __last.base()); 00381 _M_check_rehashed(__bucket_count); 00382 return iterator(__next, this); 00383 } 00384 00385 _Base& 00386 _M_base() noexcept { return *this; } 00387 00388 const _Base& 00389 _M_base() const noexcept { return *this; } 00390 00391 private: 00392 void 00393 _M_invalidate_locals() 00394 { 00395 _Base_local_iterator __local_end = _Base::end(0); 00396 this->_M_invalidate_local_if( 00397 [__local_end](_Base_const_local_iterator __it) 00398 { return __it != __local_end; }); 00399 } 00400 00401 void 00402 _M_invalidate_all() 00403 { 00404 _Base_iterator __end = _Base::end(); 00405 this->_M_invalidate_if([__end](_Base_const_iterator __it) 00406 { return __it != __end; }); 00407 _M_invalidate_locals(); 00408 } 00409 00410 void 00411 _M_check_rehashed(size_type __prev_count) 00412 { 00413 if (__prev_count != this->bucket_count()) 00414 _M_invalidate_locals(); 00415 } 00416 00417 static _Base_local_iterator 00418 _S_to_local(_Base_iterator __it) 00419 { 00420 // The returned local iterator will not be incremented so we don't 00421 // need to compute __it's node bucket 00422 return _Base_local_iterator(__it._M_cur, 0, 0); 00423 } 00424 00425 static _Base_const_local_iterator 00426 _S_to_local(_Base_const_iterator __it) 00427 { 00428 // The returned local iterator will not be incremented so we don't 00429 // need to compute __it's node bucket 00430 return _Base_const_local_iterator(__it._M_cur, 0, 0); 00431 } 00432 }; 00433 00434 template<typename _Key, typename _Tp, typename _Hash, 00435 typename _Pred, typename _Alloc> 00436 inline void 00437 swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 00438 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 00439 { __x.swap(__y); } 00440 00441 template<typename _Key, typename _Tp, typename _Hash, 00442 typename _Pred, typename _Alloc> 00443 inline bool 00444 operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 00445 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 00446 { return __x._M_equal(__y); } 00447 00448 template<typename _Key, typename _Tp, typename _Hash, 00449 typename _Pred, typename _Alloc> 00450 inline bool 00451 operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 00452 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 00453 { return !(__x == __y); } 00454 00455 00456 /// Class std::unordered_multimap with safety/checking/debug instrumentation. 00457 template<typename _Key, typename _Tp, 00458 typename _Hash = std::hash<_Key>, 00459 typename _Pred = std::equal_to<_Key>, 00460 typename _Alloc = std::allocator<_Key> > 00461 class unordered_multimap 00462 : public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, 00463 _Pred, _Alloc>, 00464 public __gnu_debug::_Safe_unordered_container<unordered_multimap<_Key, 00465 _Tp, _Hash, _Pred, _Alloc> > 00466 { 00467 typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, 00468 _Pred, _Alloc> _Base; 00469 typedef __gnu_debug::_Safe_unordered_container<unordered_multimap> 00470 _Safe_base; 00471 typedef typename _Base::const_iterator _Base_const_iterator; 00472 typedef typename _Base::iterator _Base_iterator; 00473 typedef typename _Base::const_local_iterator _Base_const_local_iterator; 00474 typedef typename _Base::local_iterator _Base_local_iterator; 00475 00476 public: 00477 typedef typename _Base::size_type size_type; 00478 typedef typename _Base::hasher hasher; 00479 typedef typename _Base::key_equal key_equal; 00480 typedef typename _Base::allocator_type allocator_type; 00481 00482 typedef typename _Base::key_type key_type; 00483 typedef typename _Base::value_type value_type; 00484 00485 typedef __gnu_debug::_Safe_iterator<_Base_iterator, 00486 unordered_multimap> iterator; 00487 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator, 00488 unordered_multimap> const_iterator; 00489 typedef __gnu_debug::_Safe_local_iterator< 00490 _Base_local_iterator, unordered_multimap> local_iterator; 00491 typedef __gnu_debug::_Safe_local_iterator< 00492 _Base_const_local_iterator, unordered_multimap> const_local_iterator; 00493 00494 explicit 00495 unordered_multimap(size_type __n = 10, 00496 const hasher& __hf = hasher(), 00497 const key_equal& __eql = key_equal(), 00498 const allocator_type& __a = allocator_type()) 00499 : _Base(__n, __hf, __eql, __a) { } 00500 00501 template<typename _InputIterator> 00502 unordered_multimap(_InputIterator __first, _InputIterator __last, 00503 size_type __n = 0, 00504 const hasher& __hf = hasher(), 00505 const key_equal& __eql = key_equal(), 00506 const allocator_type& __a = allocator_type()) 00507 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first, 00508 __last)), 00509 __gnu_debug::__base(__last), __n, 00510 __hf, __eql, __a) { } 00511 00512 unordered_multimap(const unordered_multimap& __x) = default; 00513 00514 unordered_multimap(const _Base& __x) 00515 : _Base(__x) { } 00516 00517 unordered_multimap(unordered_multimap&& __x) = default; 00518 00519 unordered_multimap(initializer_list<value_type> __l, 00520 size_type __n = 0, 00521 const hasher& __hf = hasher(), 00522 const key_equal& __eql = key_equal(), 00523 const allocator_type& __a = allocator_type()) 00524 : _Base(__l, __n, __hf, __eql, __a) { } 00525 00526 ~unordered_multimap() noexcept { } 00527 00528 unordered_multimap& 00529 operator=(const unordered_multimap& __x) 00530 { 00531 *static_cast<_Base*>(this) = __x; 00532 this->_M_invalidate_all(); 00533 return *this; 00534 } 00535 00536 unordered_multimap& 00537 operator=(unordered_multimap&& __x) 00538 { 00539 // NB: DR 1204. 00540 // NB: DR 675. 00541 clear(); 00542 swap(__x); 00543 return *this; 00544 } 00545 00546 unordered_multimap& 00547 operator=(initializer_list<value_type> __l) 00548 { 00549 this->clear(); 00550 this->insert(__l); 00551 return *this; 00552 } 00553 00554 void 00555 swap(unordered_multimap& __x) 00556 { 00557 _Base::swap(__x); 00558 _Safe_base::_M_swap(__x); 00559 } 00560 00561 void 00562 clear() noexcept 00563 { 00564 _Base::clear(); 00565 this->_M_invalidate_all(); 00566 } 00567 00568 iterator 00569 begin() noexcept 00570 { return iterator(_Base::begin(), this); } 00571 00572 const_iterator 00573 begin() const noexcept 00574 { return const_iterator(_Base::begin(), this); } 00575 00576 iterator 00577 end() noexcept 00578 { return iterator(_Base::end(), this); } 00579 00580 const_iterator 00581 end() const noexcept 00582 { return const_iterator(_Base::end(), this); } 00583 00584 const_iterator 00585 cbegin() const noexcept 00586 { return const_iterator(_Base::begin(), this); } 00587 00588 const_iterator 00589 cend() const noexcept 00590 { return const_iterator(_Base::end(), this); } 00591 00592 // local versions 00593 local_iterator 00594 begin(size_type __b) 00595 { return local_iterator(_Base::begin(__b), __b, this); } 00596 00597 local_iterator 00598 end(size_type __b) 00599 { return local_iterator(_Base::end(__b), __b, this); } 00600 00601 const_local_iterator 00602 begin(size_type __b) const 00603 { return const_local_iterator(_Base::begin(__b), __b, this); } 00604 00605 const_local_iterator 00606 end(size_type __b) const 00607 { return const_local_iterator(_Base::end(__b), __b, this); } 00608 00609 const_local_iterator 00610 cbegin(size_type __b) const 00611 { return const_local_iterator(_Base::cbegin(__b), __b, this); } 00612 00613 const_local_iterator 00614 cend(size_type __b) const 00615 { return const_local_iterator(_Base::cend(__b), __b, this); } 00616 00617 template<typename... _Args> 00618 iterator 00619 emplace(_Args&&... __args) 00620 { 00621 size_type __bucket_count = this->bucket_count(); 00622 _Base_iterator __it 00623 = _Base::emplace(std::forward<_Args>(__args)...); 00624 _M_check_rehashed(__bucket_count); 00625 return iterator(__it, this); 00626 } 00627 00628 template<typename... _Args> 00629 iterator 00630 emplace_hint(const_iterator __hint, _Args&&... __args) 00631 { 00632 __glibcxx_check_insert(__hint); 00633 size_type __bucket_count = this->bucket_count(); 00634 _Base_iterator __it = _Base::emplace_hint(__hint.base(), 00635 std::forward<_Args>(__args)...); 00636 _M_check_rehashed(__bucket_count); 00637 return iterator(__it, this); 00638 } 00639 00640 iterator 00641 insert(const value_type& __obj) 00642 { 00643 size_type __bucket_count = this->bucket_count(); 00644 _Base_iterator __it = _Base::insert(__obj); 00645 _M_check_rehashed(__bucket_count); 00646 return iterator(__it, this); 00647 } 00648 00649 iterator 00650 insert(const_iterator __hint, const value_type& __obj) 00651 { 00652 __glibcxx_check_insert(__hint); 00653 size_type __bucket_count = this->bucket_count(); 00654 _Base_iterator __it = _Base::insert(__hint.base(), __obj); 00655 _M_check_rehashed(__bucket_count); 00656 return iterator(__it, this); 00657 } 00658 00659 template<typename _Pair, typename = typename 00660 std::enable_if<std::is_constructible<value_type, 00661 _Pair&&>::value>::type> 00662 iterator 00663 insert(_Pair&& __obj) 00664 { 00665 size_type __bucket_count = this->bucket_count(); 00666 _Base_iterator __it = _Base::insert(std::forward<_Pair>(__obj)); 00667 _M_check_rehashed(__bucket_count); 00668 return iterator(__it, this); 00669 } 00670 00671 template<typename _Pair, typename = typename 00672 std::enable_if<std::is_constructible<value_type, 00673 _Pair&&>::value>::type> 00674 iterator 00675 insert(const_iterator __hint, _Pair&& __obj) 00676 { 00677 __glibcxx_check_insert(__hint); 00678 size_type __bucket_count = this->bucket_count(); 00679 _Base_iterator __it = 00680 _Base::insert(__hint.base(), std::forward<_Pair>(__obj)); 00681 _M_check_rehashed(__bucket_count); 00682 return iterator(__it, this); 00683 } 00684 00685 void 00686 insert(std::initializer_list<value_type> __l) 00687 { _Base::insert(__l); } 00688 00689 template<typename _InputIterator> 00690 void 00691 insert(_InputIterator __first, _InputIterator __last) 00692 { 00693 __glibcxx_check_valid_range(__first, __last); 00694 size_type __bucket_count = this->bucket_count(); 00695 _Base::insert(__gnu_debug::__base(__first), 00696 __gnu_debug::__base(__last)); 00697 _M_check_rehashed(__bucket_count); 00698 } 00699 00700 iterator 00701 find(const key_type& __key) 00702 { return iterator(_Base::find(__key), this); } 00703 00704 const_iterator 00705 find(const key_type& __key) const 00706 { return const_iterator(_Base::find(__key), this); } 00707 00708 std::pair<iterator, iterator> 00709 equal_range(const key_type& __key) 00710 { 00711 std::pair<_Base_iterator, _Base_iterator> __res = 00712 _Base::equal_range(__key); 00713 return std::make_pair(iterator(__res.first, this), 00714 iterator(__res.second, this)); 00715 } 00716 00717 std::pair<const_iterator, const_iterator> 00718 equal_range(const key_type& __key) const 00719 { 00720 std::pair<_Base_const_iterator, _Base_const_iterator> __res = 00721 _Base::equal_range(__key); 00722 return std::make_pair(const_iterator(__res.first, this), 00723 const_iterator(__res.second, this)); 00724 } 00725 00726 size_type 00727 erase(const key_type& __key) 00728 { 00729 size_type __ret(0); 00730 size_type __bucket_count = this->bucket_count(); 00731 std::pair<_Base_iterator, _Base_iterator> __pair = 00732 _Base::equal_range(__key); 00733 for (_Base_iterator __victim = __pair.first; __victim != __pair.second;) 00734 { 00735 this->_M_invalidate_if([__victim](_Base_const_iterator __it) 00736 { return __it == __victim; }); 00737 _Base_local_iterator __local_victim = _S_to_local(__victim); 00738 this->_M_invalidate_local_if( 00739 [__local_victim](_Base_const_local_iterator __it) 00740 { return __it == __local_victim; }); 00741 _Base::erase(__victim++); 00742 ++__ret; 00743 } 00744 _M_check_rehashed(__bucket_count); 00745 return __ret; 00746 } 00747 00748 iterator 00749 erase(const_iterator __it) 00750 { 00751 __glibcxx_check_erase(__it); 00752 _Base_const_iterator __victim = __it.base(); 00753 this->_M_invalidate_if([__victim](_Base_const_iterator __it) 00754 { return __it == __victim; }); 00755 _Base_const_local_iterator __local_victim = _S_to_local(__victim); 00756 this->_M_invalidate_local_if( 00757 [__local_victim](_Base_const_local_iterator __it) 00758 { return __it == __local_victim; }); 00759 size_type __bucket_count = this->bucket_count(); 00760 _Base_iterator __next = _Base::erase(__it.base()); 00761 _M_check_rehashed(__bucket_count); 00762 return iterator(__next, this); 00763 } 00764 00765 iterator 00766 erase(iterator __it) 00767 { return erase(const_iterator(__it)); } 00768 00769 iterator 00770 erase(const_iterator __first, const_iterator __last) 00771 { 00772 __glibcxx_check_erase_range(__first, __last); 00773 for (_Base_const_iterator __tmp = __first.base(); 00774 __tmp != __last.base(); ++__tmp) 00775 { 00776 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(), 00777 _M_message(__gnu_debug::__msg_valid_range) 00778 ._M_iterator(__first, "first") 00779 ._M_iterator(__last, "last")); 00780 this->_M_invalidate_if([__tmp](_Base_const_iterator __it) 00781 { return __it == __tmp; }); 00782 _Base_const_local_iterator __local_tmp = _S_to_local(__tmp); 00783 this->_M_invalidate_local_if( 00784 [__local_tmp](_Base_const_local_iterator __it) 00785 { return __it == __local_tmp; }); 00786 } 00787 size_type __bucket_count = this->bucket_count(); 00788 _Base_iterator __next = _Base::erase(__first.base(), __last.base()); 00789 _M_check_rehashed(__bucket_count); 00790 return iterator(__next, this); 00791 } 00792 00793 _Base& 00794 _M_base() noexcept { return *this; } 00795 00796 const _Base& 00797 _M_base() const noexcept { return *this; } 00798 00799 private: 00800 void 00801 _M_invalidate_locals() 00802 { 00803 _Base_local_iterator __local_end = _Base::end(0); 00804 this->_M_invalidate_local_if( 00805 [__local_end](_Base_const_local_iterator __it) 00806 { return __it != __local_end; }); 00807 } 00808 00809 void 00810 _M_invalidate_all() 00811 { 00812 _Base_iterator __end = _Base::end(); 00813 this->_M_invalidate_if([__end](_Base_const_iterator __it) 00814 { return __it != __end; }); 00815 _M_invalidate_locals(); 00816 } 00817 00818 void 00819 _M_check_rehashed(size_type __prev_count) 00820 { 00821 if (__prev_count != this->bucket_count()) 00822 _M_invalidate_locals(); 00823 } 00824 00825 static _Base_local_iterator 00826 _S_to_local(_Base_iterator __it) 00827 { 00828 // The returned local iterator will not be incremented so we don't 00829 // need to compute __it's node bucket 00830 return _Base_local_iterator(__it._M_cur, 0, 0); 00831 } 00832 00833 static _Base_const_local_iterator 00834 _S_to_local(_Base_const_iterator __it) 00835 { 00836 // The returned local iterator will not be incremented so we don't 00837 // need to compute __it's node bucket 00838 return _Base_const_local_iterator(__it._M_cur, 0, 0); 00839 } 00840 }; 00841 00842 template<typename _Key, typename _Tp, typename _Hash, 00843 typename _Pred, typename _Alloc> 00844 inline void 00845 swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 00846 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 00847 { __x.swap(__y); } 00848 00849 template<typename _Key, typename _Tp, typename _Hash, 00850 typename _Pred, typename _Alloc> 00851 inline bool 00852 operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 00853 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 00854 { return __x._M_equal(__y); } 00855 00856 template<typename _Key, typename _Tp, typename _Hash, 00857 typename _Pred, typename _Alloc> 00858 inline bool 00859 operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, 00860 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) 00861 { return !(__x == __y); } 00862 00863 } // namespace __debug 00864 } // namespace std 00865 00866 #endif // __GXX_EXPERIMENTAL_CXX0X__ 00867 00868 #endif