1 // Debugging unordered_map/unordered_multimap implementation -*- C++ -*-
3 // Copyright (C) 2003-2014 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
25 /** @file debug/unordered_map
26 * This file is a GNU debug extension to the Standard C++ Library.
29 #ifndef _GLIBCXX_DEBUG_UNORDERED_MAP
30 #define _GLIBCXX_DEBUG_UNORDERED_MAP 1
32 #if __cplusplus < 201103L
33 # include <bits/c++0x_warning.h>
35 # include <unordered_map>
37 #include <debug/safe_unordered_container.h>
38 #include <debug/safe_iterator.h>
39 #include <debug/safe_local_iterator.h>
41 namespace std _GLIBCXX_VISIBILITY(default)
45 /// Class std::unordered_map with safety/checking/debug instrumentation.
46 template<typename _Key, typename _Tp,
47 typename _Hash = std::hash<_Key>,
48 typename _Pred = std::equal_to<_Key>,
49 typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
51 : public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>,
52 public __gnu_debug::_Safe_unordered_container<unordered_map<_Key, _Tp,
53 _Hash, _Pred, _Alloc> >
55 typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash,
57 typedef __gnu_debug::_Safe_unordered_container<unordered_map> _Safe_base;
58 typedef typename _Base::const_iterator _Base_const_iterator;
59 typedef typename _Base::iterator _Base_iterator;
60 typedef typename _Base::const_local_iterator _Base_const_local_iterator;
61 typedef typename _Base::local_iterator _Base_local_iterator;
63 typedef __gnu_cxx::__alloc_traits<typename
64 _Base::allocator_type> _Alloc_traits;
67 typedef typename _Base::size_type size_type;
68 typedef typename _Base::hasher hasher;
69 typedef typename _Base::key_equal key_equal;
70 typedef typename _Base::allocator_type allocator_type;
72 typedef typename _Base::key_type key_type;
73 typedef typename _Base::value_type value_type;
75 typedef __gnu_debug::_Safe_iterator<_Base_iterator,
76 unordered_map> iterator;
77 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
78 unordered_map> const_iterator;
79 typedef __gnu_debug::_Safe_local_iterator<_Base_local_iterator,
80 unordered_map> local_iterator;
81 typedef __gnu_debug::_Safe_local_iterator<_Base_const_local_iterator,
82 unordered_map> const_local_iterator;
85 unordered_map(size_type __n = 10,
86 const hasher& __hf = hasher(),
87 const key_equal& __eql = key_equal(),
88 const allocator_type& __a = allocator_type())
89 : _Base(__n, __hf, __eql, __a) { }
91 template<typename _InputIterator>
92 unordered_map(_InputIterator __first, _InputIterator __last,
94 const hasher& __hf = hasher(),
95 const key_equal& __eql = key_equal(),
96 const allocator_type& __a = allocator_type())
97 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
99 __gnu_debug::__base(__last), __n,
100 __hf, __eql, __a) { }
102 unordered_map(const unordered_map&) = default;
104 unordered_map(const _Base& __x)
107 unordered_map(unordered_map&&) = default;
110 unordered_map(const allocator_type& __a)
114 unordered_map(const unordered_map& __umap,
115 const allocator_type& __a)
116 : _Base(__umap._M_base(), __a)
119 unordered_map(unordered_map&& __umap,
120 const allocator_type& __a)
121 : _Base(std::move(__umap._M_base()), __a)
124 unordered_map(initializer_list<value_type> __l,
126 const hasher& __hf = hasher(),
127 const key_equal& __eql = key_equal(),
128 const allocator_type& __a = allocator_type())
129 : _Base(__l, __n, __hf, __eql, __a) { }
131 ~unordered_map() noexcept { }
134 operator=(const unordered_map& __x)
136 _M_base() = __x._M_base();
137 this->_M_invalidate_all();
142 operator=(unordered_map&& __x)
143 noexcept(_Alloc_traits::_S_nothrow_move())
145 __glibcxx_check_self_move_assign(__x);
146 bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
147 || __x.get_allocator() == this->get_allocator();
148 _M_base() = std::move(__x._M_base());
152 this->_M_invalidate_all();
153 __x._M_invalidate_all();
158 operator=(initializer_list<value_type> __l)
161 this->_M_invalidate_all();
166 swap(unordered_map& __x)
167 noexcept(_Alloc_traits::_S_nothrow_swap())
169 if (!_Alloc_traits::_S_propagate_on_swap())
170 __glibcxx_check_equal_allocs(__x);
172 _Safe_base::_M_swap(__x);
179 this->_M_invalidate_all();
184 { return iterator(_Base::begin(), this); }
187 begin() const noexcept
188 { return const_iterator(_Base::begin(), this); }
192 { return iterator(_Base::end(), this); }
196 { return const_iterator(_Base::end(), this); }
199 cbegin() const noexcept
200 { return const_iterator(_Base::begin(), this); }
203 cend() const noexcept
204 { return const_iterator(_Base::end(), this); }
210 __glibcxx_check_bucket_index(__b);
211 return local_iterator(_Base::begin(__b), this);
217 __glibcxx_check_bucket_index(__b);
218 return local_iterator(_Base::end(__b), this);
222 begin(size_type __b) const
224 __glibcxx_check_bucket_index(__b);
225 return const_local_iterator(_Base::begin(__b), this);
229 end(size_type __b) const
231 __glibcxx_check_bucket_index(__b);
232 return const_local_iterator(_Base::end(__b), this);
236 cbegin(size_type __b) const
238 __glibcxx_check_bucket_index(__b);
239 return const_local_iterator(_Base::cbegin(__b), this);
243 cend(size_type __b) const
245 __glibcxx_check_bucket_index(__b);
246 return const_local_iterator(_Base::cend(__b), this);
250 bucket_size(size_type __b) const
252 __glibcxx_check_bucket_index(__b);
253 return _Base::bucket_size(__b);
257 max_load_factor() const noexcept
258 { return _Base::max_load_factor(); }
261 max_load_factor(float __f)
263 __glibcxx_check_max_load_factor(__f);
264 _Base::max_load_factor(__f);
267 template<typename... _Args>
268 std::pair<iterator, bool>
269 emplace(_Args&&... __args)
271 size_type __bucket_count = this->bucket_count();
272 std::pair<_Base_iterator, bool> __res
273 = _Base::emplace(std::forward<_Args>(__args)...);
274 _M_check_rehashed(__bucket_count);
275 return std::make_pair(iterator(__res.first, this), __res.second);
278 template<typename... _Args>
280 emplace_hint(const_iterator __hint, _Args&&... __args)
282 __glibcxx_check_insert(__hint);
283 size_type __bucket_count = this->bucket_count();
284 _Base_iterator __it = _Base::emplace_hint(__hint.base(),
285 std::forward<_Args>(__args)...);
286 _M_check_rehashed(__bucket_count);
287 return iterator(__it, this);
290 std::pair<iterator, bool>
291 insert(const value_type& __obj)
293 size_type __bucket_count = this->bucket_count();
294 std::pair<_Base_iterator, bool> __res = _Base::insert(__obj);
295 _M_check_rehashed(__bucket_count);
296 return std::make_pair(iterator(__res.first, this), __res.second);
300 insert(const_iterator __hint, const value_type& __obj)
302 __glibcxx_check_insert(__hint);
303 size_type __bucket_count = this->bucket_count();
304 _Base_iterator __it = _Base::insert(__hint.base(), __obj);
305 _M_check_rehashed(__bucket_count);
306 return iterator(__it, this);
309 template<typename _Pair, typename = typename
310 std::enable_if<std::is_constructible<value_type,
311 _Pair&&>::value>::type>
312 std::pair<iterator, bool>
313 insert(_Pair&& __obj)
315 size_type __bucket_count = this->bucket_count();
316 std::pair<_Base_iterator, bool> __res =
317 _Base::insert(std::forward<_Pair>(__obj));
318 _M_check_rehashed(__bucket_count);
319 return std::make_pair(iterator(__res.first, this), __res.second);
322 template<typename _Pair, typename = typename
323 std::enable_if<std::is_constructible<value_type,
324 _Pair&&>::value>::type>
326 insert(const_iterator __hint, _Pair&& __obj)
328 __glibcxx_check_insert(__hint);
329 size_type __bucket_count = this->bucket_count();
330 _Base_iterator __it =
331 _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
332 _M_check_rehashed(__bucket_count);
333 return iterator(__it, this);
337 insert(std::initializer_list<value_type> __l)
339 size_type __bucket_count = this->bucket_count();
341 _M_check_rehashed(__bucket_count);
344 template<typename _InputIterator>
346 insert(_InputIterator __first, _InputIterator __last)
348 __glibcxx_check_valid_range(__first, __last);
349 size_type __bucket_count = this->bucket_count();
350 _Base::insert(__gnu_debug::__base(__first),
351 __gnu_debug::__base(__last));
352 _M_check_rehashed(__bucket_count);
356 find(const key_type& __key)
357 { return iterator(_Base::find(__key), this); }
360 find(const key_type& __key) const
361 { return const_iterator(_Base::find(__key), this); }
363 std::pair<iterator, iterator>
364 equal_range(const key_type& __key)
366 std::pair<_Base_iterator, _Base_iterator> __res =
367 _Base::equal_range(__key);
368 return std::make_pair(iterator(__res.first, this),
369 iterator(__res.second, this));
372 std::pair<const_iterator, const_iterator>
373 equal_range(const key_type& __key) const
375 std::pair<_Base_const_iterator, _Base_const_iterator> __res =
376 _Base::equal_range(__key);
377 return std::make_pair(const_iterator(__res.first, this),
378 const_iterator(__res.second, this));
382 erase(const key_type& __key)
385 _Base_iterator __victim(_Base::find(__key));
386 if (__victim != _Base::end())
388 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
389 { return __it == __victim; });
390 this->_M_invalidate_local_if(
391 [__victim](_Base_const_local_iterator __it)
392 { return __it._M_curr() == __victim._M_cur; });
393 size_type __bucket_count = this->bucket_count();
394 _Base::erase(__victim);
395 _M_check_rehashed(__bucket_count);
402 erase(const_iterator __it)
404 __glibcxx_check_erase(__it);
405 _Base_const_iterator __victim = __it.base();
406 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
407 { return __it == __victim; });
408 this->_M_invalidate_local_if(
409 [__victim](_Base_const_local_iterator __it)
410 { return __it._M_curr() == __victim._M_cur; });
411 size_type __bucket_count = this->bucket_count();
412 _Base_iterator __next = _Base::erase(__it.base());
413 _M_check_rehashed(__bucket_count);
414 return iterator(__next, this);
419 { return erase(const_iterator(__it)); }
422 erase(const_iterator __first, const_iterator __last)
424 __glibcxx_check_erase_range(__first, __last);
425 for (_Base_const_iterator __tmp = __first.base();
426 __tmp != __last.base(); ++__tmp)
428 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
429 _M_message(__gnu_debug::__msg_valid_range)
430 ._M_iterator(__first, "first")
431 ._M_iterator(__last, "last"));
432 this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
433 { return __it == __tmp; });
434 this->_M_invalidate_local_if(
435 [__tmp](_Base_const_local_iterator __it)
436 { return __it._M_curr() == __tmp._M_cur; });
438 size_type __bucket_count = this->bucket_count();
439 _Base_iterator __next = _Base::erase(__first.base(), __last.base());
440 _M_check_rehashed(__bucket_count);
441 return iterator(__next, this);
445 _M_base() noexcept { return *this; }
448 _M_base() const noexcept { return *this; }
452 _M_invalidate_locals()
454 _Base_local_iterator __local_end = _Base::end(0);
455 this->_M_invalidate_local_if(
456 [__local_end](_Base_const_local_iterator __it)
457 { return __it != __local_end; });
463 _Base_iterator __end = _Base::end();
464 this->_M_invalidate_if([__end](_Base_const_iterator __it)
465 { return __it != __end; });
466 _M_invalidate_locals();
470 _M_check_rehashed(size_type __prev_count)
472 if (__prev_count != this->bucket_count())
473 _M_invalidate_locals();
477 template<typename _Key, typename _Tp, typename _Hash,
478 typename _Pred, typename _Alloc>
480 swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
481 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
484 template<typename _Key, typename _Tp, typename _Hash,
485 typename _Pred, typename _Alloc>
487 operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
488 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
489 { return __x._M_base() == __y._M_base(); }
491 template<typename _Key, typename _Tp, typename _Hash,
492 typename _Pred, typename _Alloc>
494 operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
495 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
496 { return !(__x == __y); }
499 /// Class std::unordered_multimap with safety/checking/debug instrumentation.
500 template<typename _Key, typename _Tp,
501 typename _Hash = std::hash<_Key>,
502 typename _Pred = std::equal_to<_Key>,
503 typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
504 class unordered_multimap
505 : public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
507 public __gnu_debug::_Safe_unordered_container<unordered_multimap<_Key,
508 _Tp, _Hash, _Pred, _Alloc> >
510 typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
511 _Pred, _Alloc> _Base;
512 typedef __gnu_debug::_Safe_unordered_container<unordered_multimap>
514 typedef typename _Base::const_iterator _Base_const_iterator;
515 typedef typename _Base::iterator _Base_iterator;
516 typedef typename _Base::const_local_iterator _Base_const_local_iterator;
517 typedef typename _Base::local_iterator _Base_local_iterator;
519 typedef __gnu_cxx::__alloc_traits<typename
520 _Base::allocator_type> _Alloc_traits;
523 typedef typename _Base::size_type size_type;
524 typedef typename _Base::hasher hasher;
525 typedef typename _Base::key_equal key_equal;
526 typedef typename _Base::allocator_type allocator_type;
528 typedef typename _Base::key_type key_type;
529 typedef typename _Base::value_type value_type;
531 typedef __gnu_debug::_Safe_iterator<_Base_iterator,
532 unordered_multimap> iterator;
533 typedef __gnu_debug::_Safe_iterator<_Base_const_iterator,
534 unordered_multimap> const_iterator;
535 typedef __gnu_debug::_Safe_local_iterator<
536 _Base_local_iterator, unordered_multimap> local_iterator;
537 typedef __gnu_debug::_Safe_local_iterator<
538 _Base_const_local_iterator, unordered_multimap> const_local_iterator;
541 unordered_multimap(size_type __n = 10,
542 const hasher& __hf = hasher(),
543 const key_equal& __eql = key_equal(),
544 const allocator_type& __a = allocator_type())
545 : _Base(__n, __hf, __eql, __a) { }
547 template<typename _InputIterator>
548 unordered_multimap(_InputIterator __first, _InputIterator __last,
550 const hasher& __hf = hasher(),
551 const key_equal& __eql = key_equal(),
552 const allocator_type& __a = allocator_type())
553 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
555 __gnu_debug::__base(__last), __n,
556 __hf, __eql, __a) { }
558 unordered_multimap(const unordered_multimap&) = default;
560 unordered_multimap(const _Base& __x)
563 unordered_multimap(unordered_multimap&&) = default;
566 unordered_multimap(const allocator_type& __a)
570 unordered_multimap(const unordered_multimap& __umap,
571 const allocator_type& __a)
572 : _Base(__umap._M_base(), __a)
575 unordered_multimap(unordered_multimap&& __umap,
576 const allocator_type& __a)
577 : _Base(std::move(__umap._M_base()), __a)
580 unordered_multimap(initializer_list<value_type> __l,
582 const hasher& __hf = hasher(),
583 const key_equal& __eql = key_equal(),
584 const allocator_type& __a = allocator_type())
585 : _Base(__l, __n, __hf, __eql, __a) { }
587 ~unordered_multimap() noexcept { }
590 operator=(const unordered_multimap& __x)
592 _M_base() = __x._M_base();
593 this->_M_invalidate_all();
598 operator=(unordered_multimap&& __x)
599 noexcept(_Alloc_traits::_S_nothrow_move())
601 __glibcxx_check_self_move_assign(__x);
602 bool __xfer_memory = _Alloc_traits::_S_propagate_on_move_assign()
603 || __x.get_allocator() == this->get_allocator();
604 _M_base() = std::move(__x._M_base());
608 this->_M_invalidate_all();
609 __x._M_invalidate_all();
614 operator=(initializer_list<value_type> __l)
617 this->_M_invalidate_all();
622 swap(unordered_multimap& __x)
623 noexcept(_Alloc_traits::_S_nothrow_swap())
625 if (!_Alloc_traits::_S_propagate_on_swap())
626 __glibcxx_check_equal_allocs(__x);
628 _Safe_base::_M_swap(__x);
635 this->_M_invalidate_all();
640 { return iterator(_Base::begin(), this); }
643 begin() const noexcept
644 { return const_iterator(_Base::begin(), this); }
648 { return iterator(_Base::end(), this); }
652 { return const_iterator(_Base::end(), this); }
655 cbegin() const noexcept
656 { return const_iterator(_Base::begin(), this); }
659 cend() const noexcept
660 { return const_iterator(_Base::end(), this); }
666 __glibcxx_check_bucket_index(__b);
667 return local_iterator(_Base::begin(__b), this);
673 __glibcxx_check_bucket_index(__b);
674 return local_iterator(_Base::end(__b), this);
678 begin(size_type __b) const
680 __glibcxx_check_bucket_index(__b);
681 return const_local_iterator(_Base::begin(__b), this);
685 end(size_type __b) const
687 __glibcxx_check_bucket_index(__b);
688 return const_local_iterator(_Base::end(__b), this);
692 cbegin(size_type __b) const
694 __glibcxx_check_bucket_index(__b);
695 return const_local_iterator(_Base::cbegin(__b), this);
699 cend(size_type __b) const
701 __glibcxx_check_bucket_index(__b);
702 return const_local_iterator(_Base::cend(__b), this);
706 bucket_size(size_type __b) const
708 __glibcxx_check_bucket_index(__b);
709 return _Base::bucket_size(__b);
713 max_load_factor() const noexcept
714 { return _Base::max_load_factor(); }
717 max_load_factor(float __f)
719 __glibcxx_check_max_load_factor(__f);
720 _Base::max_load_factor(__f);
723 template<typename... _Args>
725 emplace(_Args&&... __args)
727 size_type __bucket_count = this->bucket_count();
729 = _Base::emplace(std::forward<_Args>(__args)...);
730 _M_check_rehashed(__bucket_count);
731 return iterator(__it, this);
734 template<typename... _Args>
736 emplace_hint(const_iterator __hint, _Args&&... __args)
738 __glibcxx_check_insert(__hint);
739 size_type __bucket_count = this->bucket_count();
740 _Base_iterator __it = _Base::emplace_hint(__hint.base(),
741 std::forward<_Args>(__args)...);
742 _M_check_rehashed(__bucket_count);
743 return iterator(__it, this);
747 insert(const value_type& __obj)
749 size_type __bucket_count = this->bucket_count();
750 _Base_iterator __it = _Base::insert(__obj);
751 _M_check_rehashed(__bucket_count);
752 return iterator(__it, this);
756 insert(const_iterator __hint, const value_type& __obj)
758 __glibcxx_check_insert(__hint);
759 size_type __bucket_count = this->bucket_count();
760 _Base_iterator __it = _Base::insert(__hint.base(), __obj);
761 _M_check_rehashed(__bucket_count);
762 return iterator(__it, this);
765 template<typename _Pair, typename = typename
766 std::enable_if<std::is_constructible<value_type,
767 _Pair&&>::value>::type>
769 insert(_Pair&& __obj)
771 size_type __bucket_count = this->bucket_count();
772 _Base_iterator __it = _Base::insert(std::forward<_Pair>(__obj));
773 _M_check_rehashed(__bucket_count);
774 return iterator(__it, this);
777 template<typename _Pair, typename = typename
778 std::enable_if<std::is_constructible<value_type,
779 _Pair&&>::value>::type>
781 insert(const_iterator __hint, _Pair&& __obj)
783 __glibcxx_check_insert(__hint);
784 size_type __bucket_count = this->bucket_count();
785 _Base_iterator __it =
786 _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
787 _M_check_rehashed(__bucket_count);
788 return iterator(__it, this);
792 insert(std::initializer_list<value_type> __l)
793 { _Base::insert(__l); }
795 template<typename _InputIterator>
797 insert(_InputIterator __first, _InputIterator __last)
799 __glibcxx_check_valid_range(__first, __last);
800 size_type __bucket_count = this->bucket_count();
801 _Base::insert(__gnu_debug::__base(__first),
802 __gnu_debug::__base(__last));
803 _M_check_rehashed(__bucket_count);
807 find(const key_type& __key)
808 { return iterator(_Base::find(__key), this); }
811 find(const key_type& __key) const
812 { return const_iterator(_Base::find(__key), this); }
814 std::pair<iterator, iterator>
815 equal_range(const key_type& __key)
817 std::pair<_Base_iterator, _Base_iterator> __res =
818 _Base::equal_range(__key);
819 return std::make_pair(iterator(__res.first, this),
820 iterator(__res.second, this));
823 std::pair<const_iterator, const_iterator>
824 equal_range(const key_type& __key) const
826 std::pair<_Base_const_iterator, _Base_const_iterator> __res =
827 _Base::equal_range(__key);
828 return std::make_pair(const_iterator(__res.first, this),
829 const_iterator(__res.second, this));
833 erase(const key_type& __key)
836 size_type __bucket_count = this->bucket_count();
837 std::pair<_Base_iterator, _Base_iterator> __pair =
838 _Base::equal_range(__key);
839 for (_Base_iterator __victim = __pair.first; __victim != __pair.second;)
841 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
842 { return __it == __victim; });
843 this->_M_invalidate_local_if(
844 [__victim](_Base_const_local_iterator __it)
845 { return __it._M_curr() == __victim._M_cur; });
846 _Base::erase(__victim++);
849 _M_check_rehashed(__bucket_count);
854 erase(const_iterator __it)
856 __glibcxx_check_erase(__it);
857 _Base_const_iterator __victim = __it.base();
858 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
859 { return __it == __victim; });
860 this->_M_invalidate_local_if(
861 [__victim](_Base_const_local_iterator __it)
862 { return __it._M_curr() == __victim._M_cur; });
863 size_type __bucket_count = this->bucket_count();
864 _Base_iterator __next = _Base::erase(__it.base());
865 _M_check_rehashed(__bucket_count);
866 return iterator(__next, this);
871 { return erase(const_iterator(__it)); }
874 erase(const_iterator __first, const_iterator __last)
876 __glibcxx_check_erase_range(__first, __last);
877 for (_Base_const_iterator __tmp = __first.base();
878 __tmp != __last.base(); ++__tmp)
880 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
881 _M_message(__gnu_debug::__msg_valid_range)
882 ._M_iterator(__first, "first")
883 ._M_iterator(__last, "last"));
884 this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
885 { return __it == __tmp; });
886 this->_M_invalidate_local_if(
887 [__tmp](_Base_const_local_iterator __it)
888 { return __it._M_curr() == __tmp._M_cur; });
890 size_type __bucket_count = this->bucket_count();
891 _Base_iterator __next = _Base::erase(__first.base(), __last.base());
892 _M_check_rehashed(__bucket_count);
893 return iterator(__next, this);
897 _M_base() noexcept { return *this; }
900 _M_base() const noexcept { return *this; }
904 _M_invalidate_locals()
906 _Base_local_iterator __local_end = _Base::end(0);
907 this->_M_invalidate_local_if(
908 [__local_end](_Base_const_local_iterator __it)
909 { return __it != __local_end; });
915 _Base_iterator __end = _Base::end();
916 this->_M_invalidate_if([__end](_Base_const_iterator __it)
917 { return __it != __end; });
918 _M_invalidate_locals();
922 _M_check_rehashed(size_type __prev_count)
924 if (__prev_count != this->bucket_count())
925 _M_invalidate_locals();
929 template<typename _Key, typename _Tp, typename _Hash,
930 typename _Pred, typename _Alloc>
932 swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
933 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
936 template<typename _Key, typename _Tp, typename _Hash,
937 typename _Pred, typename _Alloc>
939 operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
940 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
941 { return __x._M_base() == __y._M_base(); }
943 template<typename _Key, typename _Tp, typename _Hash,
944 typename _Pred, typename _Alloc>
946 operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
947 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
948 { return !(__x == __y); }
950 } // namespace __debug