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