1 // Debugging unordered_map/unordered_multimap implementation -*- C++ -*-
3 // Copyright (C) 2003-2017 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 #pragma GCC system_header
34 #if __cplusplus < 201103L
35 # include <bits/c++0x_warning.h>
37 # include <unordered_map>
39 #include <debug/safe_unordered_container.h>
40 #include <debug/safe_container.h>
41 #include <debug/safe_iterator.h>
42 #include <debug/safe_local_iterator.h>
44 namespace std _GLIBCXX_VISIBILITY(default)
48 /// Class std::unordered_map with safety/checking/debug instrumentation.
49 template<typename _Key, typename _Tp,
50 typename _Hash = std::hash<_Key>,
51 typename _Pred = std::equal_to<_Key>,
52 typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
54 : public __gnu_debug::_Safe_container<
55 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc,
56 __gnu_debug::_Safe_unordered_container>,
57 public _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>
59 typedef _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash,
61 typedef __gnu_debug::_Safe_container<unordered_map,
62 _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
63 typedef typename _Base::const_iterator _Base_const_iterator;
64 typedef typename _Base::iterator _Base_iterator;
65 typedef typename _Base::const_local_iterator
66 _Base_const_local_iterator;
67 typedef typename _Base::local_iterator _Base_local_iterator;
70 typedef typename _Base::size_type size_type;
71 typedef typename _Base::hasher hasher;
72 typedef typename _Base::key_equal key_equal;
73 typedef typename _Base::allocator_type allocator_type;
75 typedef typename _Base::key_type key_type;
76 typedef typename _Base::value_type value_type;
78 typedef __gnu_debug::_Safe_iterator<
79 _Base_iterator, unordered_map> iterator;
80 typedef __gnu_debug::_Safe_iterator<
81 _Base_const_iterator, unordered_map> const_iterator;
82 typedef __gnu_debug::_Safe_local_iterator<
83 _Base_local_iterator, unordered_map> local_iterator;
84 typedef __gnu_debug::_Safe_local_iterator<
85 _Base_const_local_iterator, unordered_map> const_local_iterator;
87 unordered_map() = default;
90 unordered_map(size_type __n,
91 const hasher& __hf = hasher(),
92 const key_equal& __eql = key_equal(),
93 const allocator_type& __a = allocator_type())
94 : _Base(__n, __hf, __eql, __a) { }
96 template<typename _InputIterator>
97 unordered_map(_InputIterator __first, _InputIterator __last,
99 const hasher& __hf = hasher(),
100 const key_equal& __eql = key_equal(),
101 const allocator_type& __a = allocator_type())
102 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
104 __gnu_debug::__base(__last), __n,
105 __hf, __eql, __a) { }
107 unordered_map(const unordered_map&) = default;
109 unordered_map(const _Base& __x)
112 unordered_map(unordered_map&&) = default;
115 unordered_map(const allocator_type& __a)
118 unordered_map(const unordered_map& __umap,
119 const allocator_type& __a)
120 : _Base(__umap, __a) { }
122 unordered_map(unordered_map&& __umap,
123 const allocator_type& __a)
124 : _Safe(std::move(__umap._M_safe()), __a),
125 _Base(std::move(__umap._M_base()), __a) { }
127 unordered_map(initializer_list<value_type> __l,
129 const hasher& __hf = hasher(),
130 const key_equal& __eql = key_equal(),
131 const allocator_type& __a = allocator_type())
132 : _Base(__l, __n, __hf, __eql, __a) { }
134 unordered_map(size_type __n, const allocator_type& __a)
135 : unordered_map(__n, hasher(), key_equal(), __a)
138 unordered_map(size_type __n,
140 const allocator_type& __a)
141 : unordered_map(__n, __hf, key_equal(), __a)
144 template<typename _InputIterator>
145 unordered_map(_InputIterator __first, _InputIterator __last,
147 const allocator_type& __a)
148 : unordered_map(__first, __last, __n, hasher(), key_equal(), __a)
151 template<typename _InputIterator>
152 unordered_map(_InputIterator __first, _InputIterator __last,
155 const allocator_type& __a)
156 : unordered_map(__first, __last, __n, __hf, key_equal(), __a)
159 unordered_map(initializer_list<value_type> __l,
161 const allocator_type& __a)
162 : unordered_map(__l, __n, hasher(), key_equal(), __a)
165 unordered_map(initializer_list<value_type> __l,
168 const allocator_type& __a)
169 : unordered_map(__l, __n, __hf, key_equal(), __a)
172 ~unordered_map() = default;
175 operator=(const unordered_map&) = default;
178 operator=(unordered_map&&) = default;
181 operator=(initializer_list<value_type> __l)
184 this->_M_invalidate_all();
189 swap(unordered_map& __x)
190 noexcept( noexcept(declval<_Base&>().swap(__x)) )
200 this->_M_invalidate_all();
205 { return iterator(_Base::begin(), this); }
208 begin() const noexcept
209 { return const_iterator(_Base::begin(), this); }
213 { return iterator(_Base::end(), this); }
217 { return const_iterator(_Base::end(), this); }
220 cbegin() const noexcept
221 { return const_iterator(_Base::begin(), this); }
224 cend() const noexcept
225 { return const_iterator(_Base::end(), this); }
231 __glibcxx_check_bucket_index(__b);
232 return local_iterator(_Base::begin(__b), this);
238 __glibcxx_check_bucket_index(__b);
239 return local_iterator(_Base::end(__b), this);
243 begin(size_type __b) const
245 __glibcxx_check_bucket_index(__b);
246 return const_local_iterator(_Base::begin(__b), this);
250 end(size_type __b) const
252 __glibcxx_check_bucket_index(__b);
253 return const_local_iterator(_Base::end(__b), this);
257 cbegin(size_type __b) const
259 __glibcxx_check_bucket_index(__b);
260 return const_local_iterator(_Base::cbegin(__b), this);
264 cend(size_type __b) const
266 __glibcxx_check_bucket_index(__b);
267 return const_local_iterator(_Base::cend(__b), this);
271 bucket_size(size_type __b) const
273 __glibcxx_check_bucket_index(__b);
274 return _Base::bucket_size(__b);
278 max_load_factor() const noexcept
279 { return _Base::max_load_factor(); }
282 max_load_factor(float __f)
284 __glibcxx_check_max_load_factor(__f);
285 _Base::max_load_factor(__f);
288 template<typename... _Args>
289 std::pair<iterator, bool>
290 emplace(_Args&&... __args)
292 size_type __bucket_count = this->bucket_count();
293 std::pair<_Base_iterator, bool> __res
294 = _Base::emplace(std::forward<_Args>(__args)...);
295 _M_check_rehashed(__bucket_count);
296 return std::make_pair(iterator(__res.first, this), __res.second);
299 template<typename... _Args>
301 emplace_hint(const_iterator __hint, _Args&&... __args)
303 __glibcxx_check_insert(__hint);
304 size_type __bucket_count = this->bucket_count();
305 _Base_iterator __it = _Base::emplace_hint(__hint.base(),
306 std::forward<_Args>(__args)...);
307 _M_check_rehashed(__bucket_count);
308 return iterator(__it, this);
311 std::pair<iterator, bool>
312 insert(const value_type& __obj)
314 size_type __bucket_count = this->bucket_count();
315 std::pair<_Base_iterator, bool> __res = _Base::insert(__obj);
316 _M_check_rehashed(__bucket_count);
317 return std::make_pair(iterator(__res.first, this), __res.second);
321 insert(const_iterator __hint, const value_type& __obj)
323 __glibcxx_check_insert(__hint);
324 size_type __bucket_count = this->bucket_count();
325 _Base_iterator __it = _Base::insert(__hint.base(), __obj);
326 _M_check_rehashed(__bucket_count);
327 return iterator(__it, this);
330 template<typename _Pair, typename = typename
331 std::enable_if<std::is_constructible<value_type,
332 _Pair&&>::value>::type>
333 std::pair<iterator, bool>
334 insert(_Pair&& __obj)
336 size_type __bucket_count = this->bucket_count();
337 std::pair<_Base_iterator, bool> __res =
338 _Base::insert(std::forward<_Pair>(__obj));
339 _M_check_rehashed(__bucket_count);
340 return std::make_pair(iterator(__res.first, this), __res.second);
343 template<typename _Pair, typename = typename
344 std::enable_if<std::is_constructible<value_type,
345 _Pair&&>::value>::type>
347 insert(const_iterator __hint, _Pair&& __obj)
349 __glibcxx_check_insert(__hint);
350 size_type __bucket_count = this->bucket_count();
351 _Base_iterator __it =
352 _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
353 _M_check_rehashed(__bucket_count);
354 return iterator(__it, this);
358 insert(std::initializer_list<value_type> __l)
360 size_type __bucket_count = this->bucket_count();
362 _M_check_rehashed(__bucket_count);
365 template<typename _InputIterator>
367 insert(_InputIterator __first, _InputIterator __last)
369 typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
370 __glibcxx_check_valid_range2(__first, __last, __dist);
371 size_type __bucket_count = this->bucket_count();
373 if (__dist.second >= __gnu_debug::__dp_sign)
374 _Base::insert(__gnu_debug::__unsafe(__first),
375 __gnu_debug::__unsafe(__last));
377 _Base::insert(__first, __last);
379 _M_check_rehashed(__bucket_count);
382 #if __cplusplus > 201402L
383 template <typename... _Args>
385 try_emplace(const key_type& __k, _Args&&... __args)
387 auto __res = _Base::try_emplace(__k,
388 std::forward<_Args>(__args)...);
389 return { iterator(__res.first, this), __res.second };
392 template <typename... _Args>
394 try_emplace(key_type&& __k, _Args&&... __args)
396 auto __res = _Base::try_emplace(std::move(__k),
397 std::forward<_Args>(__args)...);
398 return { iterator(__res.first, this), __res.second };
401 template <typename... _Args>
403 try_emplace(const_iterator __hint, const key_type& __k,
406 __glibcxx_check_insert(__hint);
407 return iterator(_Base::try_emplace(__hint.base(), __k,
408 std::forward<_Args>(__args)...),
412 template <typename... _Args>
414 try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args)
416 __glibcxx_check_insert(__hint);
417 return iterator(_Base::try_emplace(__hint.base(), std::move(__k),
418 std::forward<_Args>(__args)...),
422 template <typename _Obj>
424 insert_or_assign(const key_type& __k, _Obj&& __obj)
426 auto __res = _Base::insert_or_assign(__k,
427 std::forward<_Obj>(__obj));
428 return { iterator(__res.first, this), __res.second };
431 template <typename _Obj>
433 insert_or_assign(key_type&& __k, _Obj&& __obj)
435 auto __res = _Base::insert_or_assign(std::move(__k),
436 std::forward<_Obj>(__obj));
437 return { iterator(__res.first, this), __res.second };
440 template <typename _Obj>
442 insert_or_assign(const_iterator __hint, const key_type& __k,
445 __glibcxx_check_insert(__hint);
446 return iterator(_Base::insert_or_assign(__hint.base(), __k,
447 std::forward<_Obj>(__obj)),
451 template <typename _Obj>
453 insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj)
455 __glibcxx_check_insert(__hint);
456 return iterator(_Base::insert_or_assign(__hint.base(),
458 std::forward<_Obj>(__obj)),
463 #if __cplusplus > 201402L
464 using node_type = typename _Base::node_type;
466 struct insert_return_type
474 extract(const_iterator __position)
476 __glibcxx_check_erase(__position);
477 _Base_const_iterator __victim = __position.base();
478 this->_M_invalidate_if(
479 [__victim](_Base_const_iterator __it) { return __it == __victim; }
481 this->_M_invalidate_local_if(
482 [__victim](_Base_const_local_iterator __it) {
483 return __it._M_curr() == __victim._M_cur;
485 return _Base::extract(__position.base());
489 extract(const key_type& __key)
491 const auto __position = find(__key);
492 if (__position != end())
493 return extract(__position);
498 insert(node_type&& __nh)
500 auto __ret = _Base::insert(std::move(__nh));
501 iterator __pos = iterator(__ret.position, this);
502 return { __ret.inserted, __pos, std::move(__ret.node) };
506 insert(const_iterator __hint, node_type&& __nh)
508 __glibcxx_check_insert(__hint);
509 return iterator(_Base::insert(__hint.base(), std::move(__nh)), this);
516 find(const key_type& __key)
517 { return iterator(_Base::find(__key), this); }
520 find(const key_type& __key) const
521 { return const_iterator(_Base::find(__key), this); }
523 std::pair<iterator, iterator>
524 equal_range(const key_type& __key)
526 std::pair<_Base_iterator, _Base_iterator> __res =
527 _Base::equal_range(__key);
528 return std::make_pair(iterator(__res.first, this),
529 iterator(__res.second, this));
532 std::pair<const_iterator, const_iterator>
533 equal_range(const key_type& __key) const
535 std::pair<_Base_const_iterator, _Base_const_iterator> __res =
536 _Base::equal_range(__key);
537 return std::make_pair(const_iterator(__res.first, this),
538 const_iterator(__res.second, this));
542 erase(const key_type& __key)
545 _Base_iterator __victim(_Base::find(__key));
546 if (__victim != _Base::end())
548 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
549 { return __it == __victim; });
550 this->_M_invalidate_local_if(
551 [__victim](_Base_const_local_iterator __it)
552 { return __it._M_curr() == __victim._M_cur; });
553 size_type __bucket_count = this->bucket_count();
554 _Base::erase(__victim);
555 _M_check_rehashed(__bucket_count);
562 erase(const_iterator __it)
564 __glibcxx_check_erase(__it);
565 _Base_const_iterator __victim = __it.base();
566 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
567 { return __it == __victim; });
568 this->_M_invalidate_local_if(
569 [__victim](_Base_const_local_iterator __it)
570 { return __it._M_curr() == __victim._M_cur; });
571 size_type __bucket_count = this->bucket_count();
572 _Base_iterator __next = _Base::erase(__it.base());
573 _M_check_rehashed(__bucket_count);
574 return iterator(__next, this);
579 { return erase(const_iterator(__it)); }
582 erase(const_iterator __first, const_iterator __last)
584 __glibcxx_check_erase_range(__first, __last);
585 for (_Base_const_iterator __tmp = __first.base();
586 __tmp != __last.base(); ++__tmp)
588 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
589 _M_message(__gnu_debug::__msg_valid_range)
590 ._M_iterator(__first, "first")
591 ._M_iterator(__last, "last"));
592 this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
593 { return __it == __tmp; });
594 this->_M_invalidate_local_if(
595 [__tmp](_Base_const_local_iterator __it)
596 { return __it._M_curr() == __tmp._M_cur; });
598 size_type __bucket_count = this->bucket_count();
599 _Base_iterator __next = _Base::erase(__first.base(), __last.base());
600 _M_check_rehashed(__bucket_count);
601 return iterator(__next, this);
605 _M_base() noexcept { return *this; }
608 _M_base() const noexcept { return *this; }
612 _M_check_rehashed(size_type __prev_count)
614 if (__prev_count != this->bucket_count())
615 this->_M_invalidate_locals();
619 template<typename _Key, typename _Tp, typename _Hash,
620 typename _Pred, typename _Alloc>
622 swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
623 unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
624 noexcept(noexcept(__x.swap(__y)))
627 template<typename _Key, typename _Tp, typename _Hash,
628 typename _Pred, typename _Alloc>
630 operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
631 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
632 { return __x._M_base() == __y._M_base(); }
634 template<typename _Key, typename _Tp, typename _Hash,
635 typename _Pred, typename _Alloc>
637 operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
638 const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
639 { return !(__x == __y); }
642 /// Class std::unordered_multimap with safety/checking/debug instrumentation.
643 template<typename _Key, typename _Tp,
644 typename _Hash = std::hash<_Key>,
645 typename _Pred = std::equal_to<_Key>,
646 typename _Alloc = std::allocator<std::pair<const _Key, _Tp> > >
647 class unordered_multimap
648 : public __gnu_debug::_Safe_container<
649 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>, _Alloc,
650 __gnu_debug::_Safe_unordered_container>,
651 public _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>
653 typedef _GLIBCXX_STD_C::unordered_multimap<_Key, _Tp, _Hash,
654 _Pred, _Alloc> _Base;
655 typedef __gnu_debug::_Safe_container<unordered_multimap,
656 _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
657 typedef typename _Base::const_iterator _Base_const_iterator;
658 typedef typename _Base::iterator _Base_iterator;
659 typedef typename _Base::const_local_iterator _Base_const_local_iterator;
660 typedef typename _Base::local_iterator _Base_local_iterator;
663 typedef typename _Base::size_type size_type;
664 typedef typename _Base::hasher hasher;
665 typedef typename _Base::key_equal key_equal;
666 typedef typename _Base::allocator_type allocator_type;
668 typedef typename _Base::key_type key_type;
669 typedef typename _Base::value_type value_type;
671 typedef __gnu_debug::_Safe_iterator<
672 _Base_iterator, unordered_multimap> iterator;
673 typedef __gnu_debug::_Safe_iterator<
674 _Base_const_iterator, unordered_multimap> const_iterator;
675 typedef __gnu_debug::_Safe_local_iterator<
676 _Base_local_iterator, unordered_multimap> local_iterator;
677 typedef __gnu_debug::_Safe_local_iterator<
678 _Base_const_local_iterator, unordered_multimap> const_local_iterator;
680 unordered_multimap() = default;
683 unordered_multimap(size_type __n,
684 const hasher& __hf = hasher(),
685 const key_equal& __eql = key_equal(),
686 const allocator_type& __a = allocator_type())
687 : _Base(__n, __hf, __eql, __a) { }
689 template<typename _InputIterator>
690 unordered_multimap(_InputIterator __first, _InputIterator __last,
692 const hasher& __hf = hasher(),
693 const key_equal& __eql = key_equal(),
694 const allocator_type& __a = allocator_type())
695 : _Base(__gnu_debug::__base(__gnu_debug::__check_valid_range(__first,
697 __gnu_debug::__base(__last), __n,
698 __hf, __eql, __a) { }
700 unordered_multimap(const unordered_multimap&) = default;
702 unordered_multimap(const _Base& __x)
705 unordered_multimap(unordered_multimap&&) = default;
708 unordered_multimap(const allocator_type& __a)
711 unordered_multimap(const unordered_multimap& __umap,
712 const allocator_type& __a)
713 : _Base(__umap, __a) { }
715 unordered_multimap(unordered_multimap&& __umap,
716 const allocator_type& __a)
717 : _Safe(std::move(__umap._M_safe()), __a),
718 _Base(std::move(__umap._M_base()), __a) { }
720 unordered_multimap(initializer_list<value_type> __l,
722 const hasher& __hf = hasher(),
723 const key_equal& __eql = key_equal(),
724 const allocator_type& __a = allocator_type())
725 : _Base(__l, __n, __hf, __eql, __a) { }
727 unordered_multimap(size_type __n, const allocator_type& __a)
728 : unordered_multimap(__n, hasher(), key_equal(), __a)
731 unordered_multimap(size_type __n, const hasher& __hf,
732 const allocator_type& __a)
733 : unordered_multimap(__n, __hf, key_equal(), __a)
736 template<typename _InputIterator>
737 unordered_multimap(_InputIterator __first, _InputIterator __last,
739 const allocator_type& __a)
740 : unordered_multimap(__first, __last, __n, hasher(), key_equal(), __a)
743 template<typename _InputIterator>
744 unordered_multimap(_InputIterator __first, _InputIterator __last,
745 size_type __n, const hasher& __hf,
746 const allocator_type& __a)
747 : unordered_multimap(__first, __last, __n, __hf, key_equal(), __a)
750 unordered_multimap(initializer_list<value_type> __l,
752 const allocator_type& __a)
753 : unordered_multimap(__l, __n, hasher(), key_equal(), __a)
756 unordered_multimap(initializer_list<value_type> __l,
757 size_type __n, const hasher& __hf,
758 const allocator_type& __a)
759 : unordered_multimap(__l, __n, __hf, key_equal(), __a)
762 ~unordered_multimap() = default;
765 operator=(const unordered_multimap&) = default;
768 operator=(unordered_multimap&&) = default;
771 operator=(initializer_list<value_type> __l)
773 this->_M_base() = __l;
774 this->_M_invalidate_all();
779 swap(unordered_multimap& __x)
780 noexcept( noexcept(declval<_Base&>().swap(__x)) )
790 this->_M_invalidate_all();
795 { return iterator(_Base::begin(), this); }
798 begin() const noexcept
799 { return const_iterator(_Base::begin(), this); }
803 { return iterator(_Base::end(), this); }
807 { return const_iterator(_Base::end(), this); }
810 cbegin() const noexcept
811 { return const_iterator(_Base::begin(), this); }
814 cend() const noexcept
815 { return const_iterator(_Base::end(), this); }
821 __glibcxx_check_bucket_index(__b);
822 return local_iterator(_Base::begin(__b), this);
828 __glibcxx_check_bucket_index(__b);
829 return local_iterator(_Base::end(__b), this);
833 begin(size_type __b) const
835 __glibcxx_check_bucket_index(__b);
836 return const_local_iterator(_Base::begin(__b), this);
840 end(size_type __b) const
842 __glibcxx_check_bucket_index(__b);
843 return const_local_iterator(_Base::end(__b), this);
847 cbegin(size_type __b) const
849 __glibcxx_check_bucket_index(__b);
850 return const_local_iterator(_Base::cbegin(__b), this);
854 cend(size_type __b) const
856 __glibcxx_check_bucket_index(__b);
857 return const_local_iterator(_Base::cend(__b), this);
861 bucket_size(size_type __b) const
863 __glibcxx_check_bucket_index(__b);
864 return _Base::bucket_size(__b);
868 max_load_factor() const noexcept
869 { return _Base::max_load_factor(); }
872 max_load_factor(float __f)
874 __glibcxx_check_max_load_factor(__f);
875 _Base::max_load_factor(__f);
878 template<typename... _Args>
880 emplace(_Args&&... __args)
882 size_type __bucket_count = this->bucket_count();
884 = _Base::emplace(std::forward<_Args>(__args)...);
885 _M_check_rehashed(__bucket_count);
886 return iterator(__it, this);
889 template<typename... _Args>
891 emplace_hint(const_iterator __hint, _Args&&... __args)
893 __glibcxx_check_insert(__hint);
894 size_type __bucket_count = this->bucket_count();
895 _Base_iterator __it = _Base::emplace_hint(__hint.base(),
896 std::forward<_Args>(__args)...);
897 _M_check_rehashed(__bucket_count);
898 return iterator(__it, this);
902 insert(const value_type& __obj)
904 size_type __bucket_count = this->bucket_count();
905 _Base_iterator __it = _Base::insert(__obj);
906 _M_check_rehashed(__bucket_count);
907 return iterator(__it, this);
911 insert(const_iterator __hint, const value_type& __obj)
913 __glibcxx_check_insert(__hint);
914 size_type __bucket_count = this->bucket_count();
915 _Base_iterator __it = _Base::insert(__hint.base(), __obj);
916 _M_check_rehashed(__bucket_count);
917 return iterator(__it, this);
920 template<typename _Pair, typename = typename
921 std::enable_if<std::is_constructible<value_type,
922 _Pair&&>::value>::type>
924 insert(_Pair&& __obj)
926 size_type __bucket_count = this->bucket_count();
927 _Base_iterator __it = _Base::insert(std::forward<_Pair>(__obj));
928 _M_check_rehashed(__bucket_count);
929 return iterator(__it, this);
932 template<typename _Pair, typename = typename
933 std::enable_if<std::is_constructible<value_type,
934 _Pair&&>::value>::type>
936 insert(const_iterator __hint, _Pair&& __obj)
938 __glibcxx_check_insert(__hint);
939 size_type __bucket_count = this->bucket_count();
940 _Base_iterator __it =
941 _Base::insert(__hint.base(), std::forward<_Pair>(__obj));
942 _M_check_rehashed(__bucket_count);
943 return iterator(__it, this);
947 insert(std::initializer_list<value_type> __l)
948 { _Base::insert(__l); }
950 template<typename _InputIterator>
952 insert(_InputIterator __first, _InputIterator __last)
954 typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
955 __glibcxx_check_valid_range2(__first, __last, __dist);
956 size_type __bucket_count = this->bucket_count();
958 if (__dist.second >= __gnu_debug::__dp_sign)
959 _Base::insert(__gnu_debug::__unsafe(__first),
960 __gnu_debug::__unsafe(__last));
962 _Base::insert(__first, __last);
964 _M_check_rehashed(__bucket_count);
967 #if __cplusplus > 201402L
968 using node_type = typename _Base::node_type;
971 extract(const_iterator __position)
973 __glibcxx_check_erase(__position);
974 _Base_const_iterator __victim = __position.base();
975 this->_M_invalidate_if(
976 [__victim](_Base_const_iterator __it) { return __it == __victim; }
978 this->_M_invalidate_local_if(
979 [__victim](_Base_const_local_iterator __it) {
980 return __it._M_curr() == __victim._M_cur;
982 return _Base::extract(__position.base());
986 extract(const key_type& __key)
988 const auto __position = find(__key);
989 if (__position != end())
990 return extract(__position);
995 insert(node_type&& __nh)
996 { return iterator(_Base::insert(std::move(__nh)), this); }
999 insert(const_iterator __hint, node_type&& __nh)
1001 __glibcxx_check_insert(__hint);
1002 return iterator(_Base::insert(__hint.base(), std::move(__nh)), this);
1009 find(const key_type& __key)
1010 { return iterator(_Base::find(__key), this); }
1013 find(const key_type& __key) const
1014 { return const_iterator(_Base::find(__key), this); }
1016 std::pair<iterator, iterator>
1017 equal_range(const key_type& __key)
1019 std::pair<_Base_iterator, _Base_iterator> __res =
1020 _Base::equal_range(__key);
1021 return std::make_pair(iterator(__res.first, this),
1022 iterator(__res.second, this));
1025 std::pair<const_iterator, const_iterator>
1026 equal_range(const key_type& __key) const
1028 std::pair<_Base_const_iterator, _Base_const_iterator> __res =
1029 _Base::equal_range(__key);
1030 return std::make_pair(const_iterator(__res.first, this),
1031 const_iterator(__res.second, this));
1035 erase(const key_type& __key)
1038 size_type __bucket_count = this->bucket_count();
1039 std::pair<_Base_iterator, _Base_iterator> __pair =
1040 _Base::equal_range(__key);
1041 for (_Base_iterator __victim = __pair.first; __victim != __pair.second;)
1043 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
1044 { return __it == __victim; });
1045 this->_M_invalidate_local_if(
1046 [__victim](_Base_const_local_iterator __it)
1047 { return __it._M_curr() == __victim._M_cur; });
1048 _Base::erase(__victim++);
1051 _M_check_rehashed(__bucket_count);
1056 erase(const_iterator __it)
1058 __glibcxx_check_erase(__it);
1059 _Base_const_iterator __victim = __it.base();
1060 this->_M_invalidate_if([__victim](_Base_const_iterator __it)
1061 { return __it == __victim; });
1062 this->_M_invalidate_local_if(
1063 [__victim](_Base_const_local_iterator __it)
1064 { return __it._M_curr() == __victim._M_cur; });
1065 size_type __bucket_count = this->bucket_count();
1066 _Base_iterator __next = _Base::erase(__it.base());
1067 _M_check_rehashed(__bucket_count);
1068 return iterator(__next, this);
1072 erase(iterator __it)
1073 { return erase(const_iterator(__it)); }
1076 erase(const_iterator __first, const_iterator __last)
1078 __glibcxx_check_erase_range(__first, __last);
1079 for (_Base_const_iterator __tmp = __first.base();
1080 __tmp != __last.base(); ++__tmp)
1082 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::end(),
1083 _M_message(__gnu_debug::__msg_valid_range)
1084 ._M_iterator(__first, "first")
1085 ._M_iterator(__last, "last"));
1086 this->_M_invalidate_if([__tmp](_Base_const_iterator __it)
1087 { return __it == __tmp; });
1088 this->_M_invalidate_local_if(
1089 [__tmp](_Base_const_local_iterator __it)
1090 { return __it._M_curr() == __tmp._M_cur; });
1092 size_type __bucket_count = this->bucket_count();
1093 _Base_iterator __next = _Base::erase(__first.base(), __last.base());
1094 _M_check_rehashed(__bucket_count);
1095 return iterator(__next, this);
1099 _M_base() noexcept { return *this; }
1102 _M_base() const noexcept { return *this; }
1106 _M_check_rehashed(size_type __prev_count)
1108 if (__prev_count != this->bucket_count())
1109 this->_M_invalidate_locals();
1113 template<typename _Key, typename _Tp, typename _Hash,
1114 typename _Pred, typename _Alloc>
1116 swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
1117 unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
1118 noexcept(noexcept(__x.swap(__y)))
1121 template<typename _Key, typename _Tp, typename _Hash,
1122 typename _Pred, typename _Alloc>
1124 operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
1125 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
1126 { return __x._M_base() == __y._M_base(); }
1128 template<typename _Key, typename _Tp, typename _Hash,
1129 typename _Pred, typename _Alloc>
1131 operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x,
1132 const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y)
1133 { return !(__x == __y); }
1135 } // namespace __debug