1 // Debugging unordered_map/unordered_multimap implementation -*- C++ -*-
3 // Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4 // Free Software Foundation, Inc.
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 // <http://www.gnu.org/licenses/>.
26 /** @file debug/unordered_map
27 * This file is a GNU debug extension to the Standard C++ Library.
30 #ifndef _GLIBCXX_DEBUG_UNORDERED_MAP
31 #define _GLIBCXX_DEBUG_UNORDERED_MAP 1
33 #ifndef __GXX_EXPERIMENTAL_CXX0X__
34 # include <bits/c++0x_warning.h>
36 # include <unordered_map>
38 #include <debug/safe_unordered_container.h>
39 #include <debug/safe_iterator.h>
40 #include <debug/safe_local_iterator.h>
42 namespace std _GLIBCXX_VISIBILITY(default)
46 /// Class std::unordered_map with safety/checking/debug instrumentation.
47 template<typename _Key, typename _Tp,
48 typename _Hash = std::hash<_Key>,
49 typename _Pred = std::equal_to<_Key>,
50 typename _Alloc = std::allocator<_Key> >
52 : public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>,
53 public __gnu_debug::_Safe_unordered_container<unordered_map<_Key, _Tp,
54 _Hash, _Pred, _Alloc> >
56 typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash,
58 typedef __gnu_debug::_Safe_unordered_container<unordered_map> _Safe_base;
59 typedef typename _Base::const_iterator _Base_const_iterator;
60 typedef typename _Base::iterator _Base_iterator;
61 typedef typename _Base::const_local_iterator _Base_const_local_iterator;
62 typedef typename _Base::local_iterator _Base_local_iterator;
65 typedef typename _Base::size_type size_type;
66 typedef typename _Base::hasher hasher;
67 typedef typename _Base::key_equal key_equal;
68 typedef typename _Base::allocator_type allocator_type;
70 typedef typename _Base::key_type key_type;
71 typedef typename _Base::value_type value_type;
73 typedef __gnu_debug::_Safe_iterator<_Base_iterator,
74 unordered_map> iterator;
75 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
76 unordered_map> const_iterator;
77 typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator,
78 unordered_map> local_iterator;
79 typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator,
80 unordered_map> const_local_iterator;
83 unordered_map(size_type __n = 10,
84 const hasher& __hf = hasher(),
85 const key_equal& __eql = key_equal(),
86 const allocator_type& __a = allocator_type())
87 : _Base(__n, __hf, __eql, __a) { }
89 template<typename _InputIterator>
90 unordered_map(_InputIterator __first, _InputIterator __last,
92 const hasher& __hf = hasher(),
93 const key_equal& __eql = key_equal(),
94 const allocator_type& __a = allocator_type())
95 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
97 __gnu_debug::__base(__last), __n,
100 unordered_map(const unordered_map& __x)
103 unordered_map(const _Base& __x)
106 unordered_map(unordered_map&& __x)
107 : _Base(std::move(__x)) { }
109 unordered_map(initializer_list<value_type> __l,
111 const hasher& __hf = hasher(),
112 const key_equal& __eql = key_equal(),
113 const allocator_type& __a = allocator_type())
114 : _Base(__l, __n, __hf, __eql, __a) { }
116 ~unordered_map() noexcept { }
119 operator=(const unordered_map& __x)
121 *static_cast<_Base*>(this) = __x;
122 this->_M_invalidate_all();
127 operator=(unordered_map&& __x)
131 __glibcxx_check_self_move_assign(__x);
138 operator=(initializer_list<value_type> __l)
146 swap(unordered_map& __x)
149 _Safe_base::_M_swap(__x);
156 this->_M_invalidate_all();
161 { return iterator(_Base::begin(), this); }
164 begin() const noexcept
165 { return const_iterator(_Base::begin(), this); }
169 { return iterator(_Base::end(), this); }
173 { return const_iterator(_Base::end(), this); }
176 cbegin() const noexcept
177 { return const_iterator(_Base::begin(), this); }
180 cend() const noexcept
181 { return const_iterator(_Base::end(), this); }
187 __glibcxx_check_bucket_index(__b);
188 return local_iterator(_Base::begin(__b), __b, this);
194 __glibcxx_check_bucket_index(__b);
195 return local_iterator(_Base::end(__b), __b, this);
199 begin(size_type __b) const
201 __glibcxx_check_bucket_index(__b);
202 return const_local_iterator(_Base::begin(__b), __b, this);
206 end(size_type __b) const
208 __glibcxx_check_bucket_index(__b);
209 return const_local_iterator(_Base::end(__b), __b, this);
213 cbegin(size_type __b) const
215 __glibcxx_check_bucket_index(__b);
216 return const_local_iterator(_Base::cbegin(__b), __b, this);
220 cend(size_type __b) const
222 __glibcxx_check_bucket_index(__b);
223 return const_local_iterator(_Base::cend(__b), __b, this);
227 bucket_size(size_type __b) const
229 __glibcxx_check_bucket_index(__b);
230 return _Base::bucket_size(__b);
234 max_load_factor() const noexcept
235 { return _Base::max_load_factor(); }
238 max_load_factor(float __f)
240 __glibcxx_check_max_load_factor(__f);
241 _Base::max_load_factor(__f);
244 template<typename... _Args>
245 std::pair<iterator, bool>
246 emplace(_Args&&... __args)
248 size_type __bucket_count = this->bucket_count();
249 std::pair<_Base_iterator, bool> __res
250 = _Base::emplace(std::forward<_Args>(__args)...);
251 _M_check_rehashed(__bucket_count);
252 return std::make_pair(iterator(__res.first, this), __res.second);
255 template<typename... _Args>
257 emplace_hint(const_iterator __hint, _Args&&... __args)
259 __glibcxx_check_insert(__hint);
260 size_type __bucket_count = this->bucket_count();
261 _Base_iterator __it = _Base::emplace_hint(__hint.base(),
262 std::forward<_Args>(__args)...);
263 _M_check_rehashed(__bucket_count);
264 return iterator(__it, this);
267 std::pair<iterator, bool>
268 insert(const value_type& __obj)
270 size_type __bucket_count = this->bucket_count();
271 std::pair<_Base_iterator, bool> __res = _Base::insert(__obj);
272 _M_check_rehashed(__bucket_count);
273 return std::make_pair(iterator(__res.first, this), __res.second);
277 insert(const_iterator __hint, const value_type& __obj)
279 __glibcxx_check_insert(__hint);
280 size_type __bucket_count = this->bucket_count();
281 _Base_iterator __it = _Base::insert(__hint.base(), __obj);
282 _M_check_rehashed(__bucket_count);
283 return iterator(__it, this);
286 template<typename _Pair, typename = typename
287 std::enable_if<std::is_constructible<value_type,
288 _Pair&&>::value>::type>
289 std::pair<iterator, bool>
290 insert(_Pair&& __obj)
292 size_type __bucket_count = this->bucket_count();
293 std::pair<_Base_iterator, bool> __res =
294 _Base::insert(std::forward<_Pair>(__obj));
295 _M_check_rehashed(__bucket_count);
296 return std::make_pair(iterator(__res.first, this), __res.second);
299 template<typename _Pair, typename = typename
300 std::enable_if<std::is_constructible<value_type,
301 _Pair&&>::value>::type>
303 insert(const_iterator __hint, _Pair&& __obj)
305 __glibcxx_check_insert(__hint);
306 size_type __bucket_count = this->bucket_count();
307 _Base_iterator __it =
308 _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
309 _M_check_rehashed(__bucket_count);
310 return iterator(__it, this);
314 insert(std::initializer_list<value_type> __l)
316 size_type __bucket_count = this->bucket_count();
318 _M_check_rehashed(__bucket_count);
321 template<typename _InputIterator>
323 insert(_InputIterator __first, _InputIterator __last)
325 __glibcxx_check_valid_range(__first, __last);
326 size_type __bucket_count = this->bucket_count();
327 _Base::insert(__gnu_debug::__base(__first),
328 __gnu_debug::__base(__last));
329 _M_check_rehashed(__bucket_count);
333 find(const key_type& __key)
334 { return iterator(_Base::find(__key), this); }
337 find(const key_type& __key) const
338 { return const_iterator(_Base::find(__key), this); }
340 std::pair<iterator, iterator>
341 equal_range(const key_type& __key)
343 std::pair<_Base_iterator, _Base_iterator> __res =
344 _Base::equal_range(__key);
345 return std::make_pair(iterator(__res.first, this),
346 iterator(__res.second, this));
349 std::pair<const_iterator, const_iterator>
350 equal_range(const key_type& __key) const
352 std::pair<_Base_const_iterator, _Base_const_iterator> __res =
353 _Base::equal_range(__key);
354 return std::make_pair(const_iterator(__res.first, this),
355 const_iterator(__res.second, this));
359 erase(const key_type& __key)
362 _Base_iterator __victim(_Base::find(__key));
363 if (__victim != _Base::end())
365 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
366 { return __it == __victim; });
367 _Base_local_iterator __local_victim = _S_to_local(__victim);
368 this->_M_invalidate_local_if(
369 [__local_victim](_Base_const_local_iterator __it)
370 { return __it == __local_victim; });
371 size_type __bucket_count = this->bucket_count();
372 _Base::erase(__victim);
373 _M_check_rehashed(__bucket_count);
380 erase(const_iterator __it)
382 __glibcxx_check_erase(__it);
383 _Base_const_iterator __victim = __it.base();
384 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
385 { return __it == __victim; });
386 _Base_const_local_iterator __local_victim = _S_to_local(__victim);
387 this->_M_invalidate_local_if(
388 [__local_victim](_Base_const_local_iterator __it)
389 { return __it == __local_victim; });
390 size_type __bucket_count = this->bucket_count();
391 _Base_iterator __next = _Base::erase(__it.base());
392 _M_check_rehashed(__bucket_count);
393 return iterator(__next, this);
398 { return erase(const_iterator(__it)); }
401 erase(const_iterator __first, const_iterator __last)
403 __glibcxx_check_erase_range(__first, __last);
404 for (_Base_const_iterator __tmp = __first.base();
405 __tmp != __last.base(); ++__tmp)
407 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
408 _M_message(__gnu_debug::__msg_valid_range)
409 ._M_iterator(__first, "first")
410 ._M_iterator(__last, "last"));
411 this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
412 { return __it == __tmp; });
413 _Base_const_local_iterator __local_tmp = _S_to_local(__tmp);
414 this->_M_invalidate_local_if(
415 [__local_tmp](_Base_const_local_iterator __it)
416 { return __it == __local_tmp; });
418 size_type __bucket_count = this->bucket_count();
419 _Base_iterator __next = _Base::erase(__first.base(), __last.base());
420 _M_check_rehashed(__bucket_count);
421 return iterator(__next, this);
425 _M_base() noexcept { return *this; }
428 _M_base() const noexcept { return *this; }
432 _M_invalidate_locals()
434 _Base_local_iterator __local_end = _Base::end(0);
435 this->_M_invalidate_local_if(
436 [__local_end](_Base_const_local_iterator __it)
437 { return __it != __local_end; });
443 _Base_iterator __end = _Base::end();
444 this->_M_invalidate_if([__end](_Base_const_iterator __it)
445 { return __it != __end; });
446 _M_invalidate_locals();
450 _M_check_rehashed(size_type __prev_count)
452 if (__prev_count != this->bucket_count())
453 _M_invalidate_locals();
456 static _Base_local_iterator
457 _S_to_local(_Base_iterator __it)
459 // The returned local iterator will not be incremented so we don't
460 // need to compute __it's node bucket
461 return _Base_local_iterator(__it._M_cur, 0, 0);
464 static _Base_const_local_iterator
465 _S_to_local(_Base_const_iterator __it)
467 // The returned local iterator will not be incremented so we don't
468 // need to compute __it's node bucket
469 return _Base_const_local_iterator(__it._M_cur, 0, 0);
473 template<typename _Key, typename _Tp, typename _Hash,
474 typename _Pred, typename _Alloc>
476 swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
477 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
480 template<typename _Key, typename _Tp, typename _Hash,
481 typename _Pred, typename _Alloc>
483 operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
484 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
485 { return __x._M_equal(__y); }
487 template<typename _Key, typename _Tp, typename _Hash,
488 typename _Pred, typename _Alloc>
490 operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
491 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
492 { return !(__x == __y); }
495 /// Class std::unordered_multimap with safety/checking/debug instrumentation.
496 template<typename _Key, typename _Tp,
497 typename _Hash = std::hash<_Key>,
498 typename _Pred = std::equal_to<_Key>,
499 typename _Alloc = std::allocator<_Key> >
500 class unordered_multimap
501 : public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
503 public __gnu_debug::_Safe_unordered_container<unordered_multimap<_Key,
504 _Tp, _Hash, _Pred, _Alloc> >
506 typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
507 _Pred, _Alloc> _Base;
508 typedef __gnu_debug::_Safe_unordered_container<unordered_multimap>
510 typedef typename _Base::const_iterator _Base_const_iterator;
511 typedef typename _Base::iterator _Base_iterator;
512 typedef typename _Base::const_local_iterator _Base_const_local_iterator;
513 typedef typename _Base::local_iterator _Base_local_iterator;
516 typedef typename _Base::size_type size_type;
517 typedef typename _Base::hasher hasher;
518 typedef typename _Base::key_equal key_equal;
519 typedef typename _Base::allocator_type allocator_type;
521 typedef typename _Base::key_type key_type;
522 typedef typename _Base::value_type value_type;
524 typedef __gnu_debug::_Safe_iterator<_Base_iterator,
525 unordered_multimap> iterator;
526 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
527 unordered_multimap> const_iterator;
528 typedef __gnu_debug::_Safe_local_iterator<
529 _Base_local_iterator, unordered_multimap> local_iterator;
530 typedef __gnu_debug::_Safe_local_iterator<
531 _Base_const_local_iterator, unordered_multimap> const_local_iterator;
534 unordered_multimap(size_type __n = 10,
535 const hasher& __hf = hasher(),
536 const key_equal& __eql = key_equal(),
537 const allocator_type& __a = allocator_type())
538 : _Base(__n, __hf, __eql, __a) { }
540 template<typename _InputIterator>
541 unordered_multimap(_InputIterator __first, _InputIterator __last,
543 const hasher& __hf = hasher(),
544 const key_equal& __eql = key_equal(),
545 const allocator_type& __a = allocator_type())
546 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
548 __gnu_debug::__base(__last), __n,
549 __hf, __eql, __a) { }
551 unordered_multimap(const unordered_multimap& __x)
554 unordered_multimap(const _Base& __x)
557 unordered_multimap(unordered_multimap&& __x)
558 : _Base(std::move(__x)) { }
560 unordered_multimap(initializer_list<value_type> __l,
562 const hasher& __hf = hasher(),
563 const key_equal& __eql = key_equal(),
564 const allocator_type& __a = allocator_type())
565 : _Base(__l, __n, __hf, __eql, __a) { }
567 ~unordered_multimap() noexcept { }
570 operator=(const unordered_multimap& __x)
572 *static_cast<_Base*>(this) = __x;
573 this->_M_invalidate_all();
578 operator=(unordered_multimap&& __x)
582 __glibcxx_check_self_move_assign(__x);
589 operator=(initializer_list<value_type> __l)
597 swap(unordered_multimap& __x)
600 _Safe_base::_M_swap(__x);
607 this->_M_invalidate_all();
612 { return iterator(_Base::begin(), this); }
615 begin() const noexcept
616 { return const_iterator(_Base::begin(), this); }
620 { return iterator(_Base::end(), this); }
624 { return const_iterator(_Base::end(), this); }
627 cbegin() const noexcept
628 { return const_iterator(_Base::begin(), this); }
631 cend() const noexcept
632 { return const_iterator(_Base::end(), this); }
638 __glibcxx_check_bucket_index(__b);
639 return local_iterator(_Base::begin(__b), __b, this);
645 __glibcxx_check_bucket_index(__b);
646 return local_iterator(_Base::end(__b), __b, this);
650 begin(size_type __b) const
652 __glibcxx_check_bucket_index(__b);
653 return const_local_iterator(_Base::begin(__b), __b, this);
657 end(size_type __b) const
659 __glibcxx_check_bucket_index(__b);
660 return const_local_iterator(_Base::end(__b), __b, this);
664 cbegin(size_type __b) const
666 __glibcxx_check_bucket_index(__b);
667 return const_local_iterator(_Base::cbegin(__b), __b, this);
671 cend(size_type __b) const
673 __glibcxx_check_bucket_index(__b);
674 return const_local_iterator(_Base::cend(__b), __b, this);
678 bucket_size(size_type __b) const
680 __glibcxx_check_bucket_index(__b);
681 return _Base::bucket_size(__b);
685 max_load_factor() const noexcept
686 { return _Base::max_load_factor(); }
689 max_load_factor(float __f)
691 __glibcxx_check_max_load_factor(__f);
692 _Base::max_load_factor(__f);
695 template<typename... _Args>
697 emplace(_Args&&... __args)
699 size_type __bucket_count = this->bucket_count();
701 = _Base::emplace(std::forward<_Args>(__args)...);
702 _M_check_rehashed(__bucket_count);
703 return iterator(__it, this);
706 template<typename... _Args>
708 emplace_hint(const_iterator __hint, _Args&&... __args)
710 __glibcxx_check_insert(__hint);
711 size_type __bucket_count = this->bucket_count();
712 _Base_iterator __it = _Base::emplace_hint(__hint.base(),
713 std::forward<_Args>(__args)...);
714 _M_check_rehashed(__bucket_count);
715 return iterator(__it, this);
719 insert(const value_type& __obj)
721 size_type __bucket_count = this->bucket_count();
722 _Base_iterator __it = _Base::insert(__obj);
723 _M_check_rehashed(__bucket_count);
724 return iterator(__it, this);
728 insert(const_iterator __hint, const value_type& __obj)
730 __glibcxx_check_insert(__hint);
731 size_type __bucket_count = this->bucket_count();
732 _Base_iterator __it = _Base::insert(__hint.base(), __obj);
733 _M_check_rehashed(__bucket_count);
734 return iterator(__it, this);
737 template<typename _Pair, typename = typename
738 std::enable_if<std::is_constructible<value_type,
739 _Pair&&>::value>::type>
741 insert(_Pair&& __obj)
743 size_type __bucket_count = this->bucket_count();
744 _Base_iterator __it = _Base::insert(std::forward<_Pair>(__obj));
745 _M_check_rehashed(__bucket_count);
746 return iterator(__it, this);
749 template<typename _Pair, typename = typename
750 std::enable_if<std::is_constructible<value_type,
751 _Pair&&>::value>::type>
753 insert(const_iterator __hint, _Pair&& __obj)
755 __glibcxx_check_insert(__hint);
756 size_type __bucket_count = this->bucket_count();
757 _Base_iterator __it =
758 _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
759 _M_check_rehashed(__bucket_count);
760 return iterator(__it, this);
764 insert(std::initializer_list<value_type> __l)
765 { _Base::insert(__l); }
767 template<typename _InputIterator>
769 insert(_InputIterator __first, _InputIterator __last)
771 __glibcxx_check_valid_range(__first, __last);
772 size_type __bucket_count = this->bucket_count();
773 _Base::insert(__gnu_debug::__base(__first),
774 __gnu_debug::__base(__last));
775 _M_check_rehashed(__bucket_count);
779 find(const key_type& __key)
780 { return iterator(_Base::find(__key), this); }
783 find(const key_type& __key) const
784 { return const_iterator(_Base::find(__key), this); }
786 std::pair<iterator, iterator>
787 equal_range(const key_type& __key)
789 std::pair<_Base_iterator, _Base_iterator> __res =
790 _Base::equal_range(__key);
791 return std::make_pair(iterator(__res.first, this),
792 iterator(__res.second, this));
795 std::pair<const_iterator, const_iterator>
796 equal_range(const key_type& __key) const
798 std::pair<_Base_const_iterator, _Base_const_iterator> __res =
799 _Base::equal_range(__key);
800 return std::make_pair(const_iterator(__res.first, this),
801 const_iterator(__res.second, this));
805 erase(const key_type& __key)
808 size_type __bucket_count = this->bucket_count();
809 std::pair<_Base_iterator, _Base_iterator> __pair =
810 _Base::equal_range(__key);
811 for (_Base_iterator __victim = __pair.first; __victim != __pair.second;)
813 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
814 { return __it == __victim; });
815 _Base_local_iterator __local_victim = _S_to_local(__victim);
816 this->_M_invalidate_local_if(
817 [__local_victim](_Base_const_local_iterator __it)
818 { return __it == __local_victim; });
819 _Base::erase(__victim++);
822 _M_check_rehashed(__bucket_count);
827 erase(const_iterator __it)
829 __glibcxx_check_erase(__it);
830 _Base_const_iterator __victim = __it.base();
831 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
832 { return __it == __victim; });
833 _Base_const_local_iterator __local_victim = _S_to_local(__victim);
834 this->_M_invalidate_local_if(
835 [__local_victim](_Base_const_local_iterator __it)
836 { return __it == __local_victim; });
837 size_type __bucket_count = this->bucket_count();
838 _Base_iterator __next = _Base::erase(__it.base());
839 _M_check_rehashed(__bucket_count);
840 return iterator(__next, this);
845 { return erase(const_iterator(__it)); }
848 erase(const_iterator __first, const_iterator __last)
850 __glibcxx_check_erase_range(__first, __last);
851 for (_Base_const_iterator __tmp = __first.base();
852 __tmp != __last.base(); ++__tmp)
854 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
855 _M_message(__gnu_debug::__msg_valid_range)
856 ._M_iterator(__first, "first")
857 ._M_iterator(__last, "last"));
858 this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
859 { return __it == __tmp; });
860 _Base_const_local_iterator __local_tmp = _S_to_local(__tmp);
861 this->_M_invalidate_local_if(
862 [__local_tmp](_Base_const_local_iterator __it)
863 { return __it == __local_tmp; });
865 size_type __bucket_count = this->bucket_count();
866 _Base_iterator __next = _Base::erase(__first.base(), __last.base());
867 _M_check_rehashed(__bucket_count);
868 return iterator(__next, this);
872 _M_base() noexcept { return *this; }
875 _M_base() const noexcept { return *this; }
879 _M_invalidate_locals()
881 _Base_local_iterator __local_end = _Base::end(0);
882 this->_M_invalidate_local_if(
883 [__local_end](_Base_const_local_iterator __it)
884 { return __it != __local_end; });
890 _Base_iterator __end = _Base::end();
891 this->_M_invalidate_if([__end](_Base_const_iterator __it)
892 { return __it != __end; });
893 _M_invalidate_locals();
897 _M_check_rehashed(size_type __prev_count)
899 if (__prev_count != this->bucket_count())
900 _M_invalidate_locals();
903 static _Base_local_iterator
904 _S_to_local(_Base_iterator __it)
906 // The returned local iterator will not be incremented so we don't
907 // need to compute __it's node bucket
908 return _Base_local_iterator(__it._M_cur, 0, 0);
911 static _Base_const_local_iterator
912 _S_to_local(_Base_const_iterator __it)
914 // The returned local iterator will not be incremented so we don't
915 // need to compute __it's node bucket
916 return _Base_const_local_iterator(__it._M_cur, 0, 0);
920 template<typename _Key, typename _Tp, typename _Hash,
921 typename _Pred, typename _Alloc>
923 swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
924 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
927 template<typename _Key, typename _Tp, typename _Hash,
928 typename _Pred, typename _Alloc>
930 operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
931 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
932 { return __x._M_equal(__y); }
934 template<typename _Key, typename _Tp, typename _Hash,
935 typename _Pred, typename _Alloc>
937 operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
938 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
939 { return !(__x == __y); }
941 } // namespace __debug
944 #endif // __GXX_EXPERIMENTAL_CXX0X__