1 // Debugging unordered_set/unordered_multiset implementation -*- C++ -*-
3 // Copyright (C) 2003-2022 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_set
26 * This file is a GNU debug extension to the Standard C++ Library.
29 #ifndef _GLIBCXX_DEBUG_UNORDERED_SET
30 #define _GLIBCXX_DEBUG_UNORDERED_SET 1
32 #pragma GCC system_header
34 #if __cplusplus < 201103L
35 # include <bits/c++0x_warning.h>
37 # include <bits/c++config.h>
38 namespace std _GLIBCXX_VISIBILITY(default) { namespace __debug {
39 template<typename _Key, typename _Hash, typename _Pred, typename _Allocator>
41 template<typename _Key, typename _Hash, typename _Pred, typename _Allocator>
42 class unordered_multiset;
43 } } // namespace std::__debug
44 # include <unordered_set>
46 #include <debug/safe_unordered_container.h>
47 #include <debug/safe_container.h>
48 #include <debug/safe_iterator.h>
49 #include <debug/safe_local_iterator.h>
51 namespace std _GLIBCXX_VISIBILITY(default)
55 /// Class std::unordered_set with safety/checking/debug instrumentation.
56 template<typename _Value,
57 typename _Hash = std::hash<_Value>,
58 typename _Pred = std::equal_to<_Value>,
59 typename _Alloc = std::allocator<_Value> >
61 : public __gnu_debug::_Safe_container<
62 unordered_set<_Value, _Hash, _Pred, _Alloc>, _Alloc,
63 __gnu_debug::_Safe_unordered_container>,
64 public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc>
66 typedef _GLIBCXX_STD_C::unordered_set<
67 _Value, _Hash, _Pred, _Alloc> _Base;
68 typedef __gnu_debug::_Safe_container<
69 unordered_set, _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
71 typedef typename _Base::const_iterator _Base_const_iterator;
72 typedef typename _Base::iterator _Base_iterator;
73 typedef typename _Base::const_local_iterator _Base_const_local_iterator;
74 typedef typename _Base::local_iterator _Base_local_iterator;
76 template<typename _ItT, typename _SeqT, typename _CatT>
77 friend class ::__gnu_debug::_Safe_iterator;
78 template<typename _ItT, typename _SeqT>
79 friend class ::__gnu_debug::_Safe_local_iterator;
81 // Reference wrapper for base class. See PR libstdc++/90102.
84 _Base_ref(const _Base& __r) : _M_ref(__r) { }
90 typedef typename _Base::size_type size_type;
91 typedef typename _Base::difference_type difference_type;
92 typedef typename _Base::hasher hasher;
93 typedef typename _Base::key_equal key_equal;
94 typedef typename _Base::allocator_type allocator_type;
96 typedef typename _Base::key_type key_type;
97 typedef typename _Base::value_type value_type;
99 typedef typename _Base::pointer pointer;
100 typedef typename _Base::const_pointer const_pointer;
101 typedef typename _Base::reference reference;
102 typedef typename _Base::const_reference const_reference;
103 typedef __gnu_debug::_Safe_iterator<
104 _Base_iterator, unordered_set> iterator;
105 typedef __gnu_debug::_Safe_iterator<
106 _Base_const_iterator, unordered_set> const_iterator;
107 typedef __gnu_debug::_Safe_local_iterator<
108 _Base_local_iterator, unordered_set> local_iterator;
109 typedef __gnu_debug::_Safe_local_iterator<
110 _Base_const_local_iterator, unordered_set> const_local_iterator;
112 unordered_set() = default;
115 unordered_set(size_type __n,
116 const hasher& __hf = hasher(),
117 const key_equal& __eql = key_equal(),
118 const allocator_type& __a = allocator_type())
119 : _Base(__n, __hf, __eql, __a) { }
121 template<typename _InputIterator>
122 unordered_set(_InputIterator __first, _InputIterator __last,
124 const hasher& __hf = hasher(),
125 const key_equal& __eql = key_equal(),
126 const allocator_type& __a = allocator_type())
127 : _Base(__gnu_debug::__base(
128 __glibcxx_check_valid_constructor_range(__first, __last)),
129 __gnu_debug::__base(__last), __n,
130 __hf, __eql, __a) { }
132 unordered_set(const unordered_set&) = default;
134 unordered_set(_Base_ref __x)
135 : _Base(__x._M_ref) { }
137 unordered_set(unordered_set&&) = default;
140 unordered_set(const allocator_type& __a)
143 unordered_set(const unordered_set& __uset,
144 const allocator_type& __a)
145 : _Base(__uset, __a) { }
147 unordered_set(unordered_set&& __uset,
148 const allocator_type& __a)
149 noexcept( noexcept(_Base(std::move(__uset), __a)) )
150 : _Safe(std::move(__uset), __a),
151 _Base(std::move(__uset), __a) { }
153 unordered_set(initializer_list<value_type> __l,
155 const hasher& __hf = hasher(),
156 const key_equal& __eql = key_equal(),
157 const allocator_type& __a = allocator_type())
158 : _Base(__l, __n, __hf, __eql, __a) { }
160 unordered_set(size_type __n, const allocator_type& __a)
161 : unordered_set(__n, hasher(), key_equal(), __a)
164 unordered_set(size_type __n, const hasher& __hf,
165 const allocator_type& __a)
166 : unordered_set(__n, __hf, key_equal(), __a)
169 template<typename _InputIterator>
170 unordered_set(_InputIterator __first, _InputIterator __last,
172 const allocator_type& __a)
173 : unordered_set(__first, __last, __n, hasher(), key_equal(), __a)
176 template<typename _InputIterator>
177 unordered_set(_InputIterator __first, _InputIterator __last,
178 size_type __n, const hasher& __hf,
179 const allocator_type& __a)
180 : unordered_set(__first, __last, __n, __hf, key_equal(), __a)
183 unordered_set(initializer_list<value_type> __l,
185 const allocator_type& __a)
186 : unordered_set(__l, __n, hasher(), key_equal(), __a)
189 unordered_set(initializer_list<value_type> __l,
190 size_type __n, const hasher& __hf,
191 const allocator_type& __a)
192 : unordered_set(__l, __n, __hf, key_equal(), __a)
195 ~unordered_set() = default;
198 operator=(const unordered_set&) = default;
201 operator=(unordered_set&&) = default;
204 operator=(initializer_list<value_type> __l)
206 _Base::operator=(__l);
207 this->_M_invalidate_all();
211 using _Base::get_allocator;
214 using _Base::max_size;
217 swap(unordered_set& __x)
218 noexcept( noexcept(declval<_Base&>().swap(__x)) )
228 this->_M_invalidate_all();
233 { return { _Base::begin(), this }; }
236 begin() const noexcept
237 { return { _Base::begin(), this }; }
241 { return { _Base::end(), this }; }
245 { return { _Base::end(), this }; }
248 cbegin() const noexcept
249 { return { _Base::cbegin(), this }; }
252 cend() const noexcept
253 { return { _Base::cend(), this }; }
259 __glibcxx_check_bucket_index(__b);
260 return { _Base::begin(__b), this };
266 __glibcxx_check_bucket_index(__b);
267 return { _Base::end(__b), this };
271 begin(size_type __b) const
273 __glibcxx_check_bucket_index(__b);
274 return { _Base::begin(__b), this };
278 end(size_type __b) const
280 __glibcxx_check_bucket_index(__b);
281 return { _Base::end(__b), this };
285 cbegin(size_type __b) const
287 __glibcxx_check_bucket_index(__b);
288 return { _Base::cbegin(__b), this };
292 cend(size_type __b) const
294 __glibcxx_check_bucket_index(__b);
295 return { _Base::cend(__b), this };
298 using _Base::bucket_count;
299 using _Base::max_bucket_count;
302 bucket_size(size_type __b) const
304 __glibcxx_check_bucket_index(__b);
305 return _Base::bucket_size(__b);
309 using _Base::load_factor;
312 max_load_factor() const noexcept
313 { return _Base::max_load_factor(); }
316 max_load_factor(float __f)
318 __glibcxx_check_max_load_factor(__f);
319 _Base::max_load_factor(__f);
323 using _Base::reserve;
325 template<typename... _Args>
326 std::pair<iterator, bool>
327 emplace(_Args&&... __args)
329 size_type __bucket_count = this->bucket_count();
330 auto __res = _Base::emplace(std::forward<_Args>(__args)...);
331 _M_check_rehashed(__bucket_count);
332 return { { __res.first, this }, __res.second };
335 template<typename... _Args>
337 emplace_hint(const_iterator __hint, _Args&&... __args)
339 __glibcxx_check_insert(__hint);
340 size_type __bucket_count = this->bucket_count();
341 auto __it = _Base::emplace_hint(__hint.base(),
342 std::forward<_Args>(__args)...);
343 _M_check_rehashed(__bucket_count);
344 return { __it, this };
347 std::pair<iterator, bool>
348 insert(const value_type& __obj)
350 size_type __bucket_count = this->bucket_count();
351 auto __res = _Base::insert(__obj);
352 _M_check_rehashed(__bucket_count);
353 return { { __res.first, this }, __res.second };
357 insert(const_iterator __hint, const value_type& __obj)
359 __glibcxx_check_insert(__hint);
360 size_type __bucket_count = this->bucket_count();
361 auto __it = _Base::insert(__hint.base(), __obj);
362 _M_check_rehashed(__bucket_count);
363 return { __it, this };
366 std::pair<iterator, bool>
367 insert(value_type&& __obj)
369 size_type __bucket_count = this->bucket_count();
370 auto __res = _Base::insert(std::move(__obj));
371 _M_check_rehashed(__bucket_count);
372 return { { __res.first, this }, __res.second };
376 insert(const_iterator __hint, value_type&& __obj)
378 __glibcxx_check_insert(__hint);
379 size_type __bucket_count = this->bucket_count();
380 auto __it = _Base::insert(__hint.base(), std::move(__obj));
381 _M_check_rehashed(__bucket_count);
382 return { __it, this };
386 insert(std::initializer_list<value_type> __l)
388 size_type __bucket_count = this->bucket_count();
390 _M_check_rehashed(__bucket_count);
393 template<typename _InputIterator>
395 insert(_InputIterator __first, _InputIterator __last)
397 typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
398 __glibcxx_check_valid_range2(__first, __last, __dist);
399 size_type __bucket_count = this->bucket_count();
401 if (__dist.second >= __gnu_debug::__dp_sign)
402 _Base::insert(__gnu_debug::__unsafe(__first),
403 __gnu_debug::__unsafe(__last));
405 _Base::insert(__first, __last);
407 _M_check_rehashed(__bucket_count);
410 #if __cplusplus > 201402L
411 using node_type = typename _Base::node_type;
412 using insert_return_type = _Node_insert_return<iterator, node_type>;
415 extract(const_iterator __position)
417 __glibcxx_check_erase(__position);
418 return _M_extract(__position.base());
422 extract(const key_type& __key)
424 const auto __position = _Base::find(__key);
425 if (__position != _Base::end())
426 return _M_extract(__position);
431 insert(node_type&& __nh)
433 auto __ret = _Base::insert(std::move(__nh));
435 { { __ret.position, this }, __ret.inserted, std::move(__ret.node) };
439 insert(const_iterator __hint, node_type&& __nh)
441 __glibcxx_check_insert(__hint);
442 return { _Base::insert(__hint.base(), std::move(__nh)), this };
445 template<typename _H2, typename _P2>
447 merge(unordered_set<_Value, _H2, _P2, _Alloc>& __source)
450 = _Safe::_S_uc_guard(std::__detail::_Identity{}, __source);
451 _Base::merge(__source);
454 template<typename _H2, typename _P2>
456 merge(unordered_set<_Value, _H2, _P2, _Alloc>&& __source)
459 template<typename _H2, typename _P2>
461 merge(unordered_multiset<_Value, _H2, _P2, _Alloc>& __source)
464 = _Safe::_S_umc_guard(std::__detail::_Identity{}, __source);
465 _Base::merge(__source);
468 template<typename _H2, typename _P2>
470 merge(unordered_multiset<_Value, _H2, _P2, _Alloc>&& __source)
474 using _Base::hash_function;
478 find(const key_type& __key)
479 { return { _Base::find(__key), this }; }
481 #if __cplusplus > 201703L
482 template<typename _Kt,
483 typename = std::__has_is_transparent_t<_Hash, _Kt>,
484 typename = std::__has_is_transparent_t<_Pred, _Kt>>
487 { return { _Base::find(__k), this }; }
491 find(const key_type& __key) const
492 { return { _Base::find(__key), this }; }
494 #if __cplusplus > 201703L
495 template<typename _Kt,
496 typename = std::__has_is_transparent_t<_Hash, _Kt>,
497 typename = std::__has_is_transparent_t<_Pred, _Kt>>
499 find(const _Kt& __k) const
500 { return { _Base::find(__k), this }; }
505 #if __cplusplus > 201703L
506 using _Base::contains;
509 std::pair<iterator, iterator>
510 equal_range(const key_type& __key)
512 auto __res = _Base::equal_range(__key);
513 return { { __res.first, this }, { __res.second, this } };
516 #if __cplusplus > 201703L
517 template<typename _Kt,
518 typename = std::__has_is_transparent_t<_Hash, _Kt>,
519 typename = std::__has_is_transparent_t<_Pred, _Kt>>
520 std::pair<iterator, iterator>
521 equal_range(const _Kt& __k)
523 auto __res = _Base::equal_range(__k);
524 return { { __res.first, this }, { __res.second, this } };
528 std::pair<const_iterator, const_iterator>
529 equal_range(const key_type& __key) const
531 auto __res = _Base::equal_range(__key);
532 return { { __res.first, this }, { __res.second, this } };
535 #if __cplusplus > 201703L
536 template<typename _Kt,
537 typename = std::__has_is_transparent_t<_Hash, _Kt>,
538 typename = std::__has_is_transparent_t<_Pred, _Kt>>
539 std::pair<const_iterator, const_iterator>
540 equal_range(const _Kt& __k) const
542 auto __res = _Base::equal_range(__k);
543 return { { __res.first, this }, { __res.second, this } };
548 erase(const key_type& __key)
551 auto __victim = _Base::find(__key);
552 if (__victim != _Base::end())
561 erase(const_iterator __it)
563 __glibcxx_check_erase(__it);
564 return { _M_erase(__it.base()), this };
568 erase(_Base_const_iterator __it)
570 __glibcxx_check_erase2(__it);
571 return _M_erase(__it);
577 __glibcxx_check_erase(__it);
578 return { _M_erase(__it.base()), this };
582 erase(const_iterator __first, const_iterator __last)
584 __glibcxx_check_erase_range(__first, __last);
585 for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp)
587 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(),
588 _M_message(__gnu_debug::__msg_valid_range)
589 ._M_iterator(__first, "first")
590 ._M_iterator(__last, "last"));
591 _M_invalidate(__tmp);
594 size_type __bucket_count = this->bucket_count();
595 auto __next = _Base::erase(__first.base(), __last.base());
596 _M_check_rehashed(__bucket_count);
597 return { __next, this };
601 _M_base() noexcept { return *this; }
604 _M_base() const noexcept { return *this; }
608 _M_check_rehashed(size_type __prev_count)
610 if (__prev_count != this->bucket_count())
611 this->_M_invalidate_all();
615 _M_invalidate(_Base_const_iterator __victim)
617 this->_M_invalidate_if(
618 [__victim](_Base_const_iterator __it) { return __it == __victim; });
619 this->_M_invalidate_local_if(
620 [__victim](_Base_const_local_iterator __it)
621 { return __it == __victim; });
625 _M_erase(_Base_const_iterator __victim)
627 _M_invalidate(__victim);
628 size_type __bucket_count = this->bucket_count();
629 _Base_iterator __next = _Base::erase(__victim);
630 _M_check_rehashed(__bucket_count);
634 #if __cplusplus > 201402L
636 _M_extract(_Base_const_iterator __victim)
638 _M_invalidate(__victim);
639 return _Base::extract(__victim);
644 #if __cpp_deduction_guides >= 201606
646 template<typename _InputIterator,
648 hash<typename iterator_traits<_InputIterator>::value_type>,
650 equal_to<typename iterator_traits<_InputIterator>::value_type>,
651 typename _Allocator =
652 allocator<typename iterator_traits<_InputIterator>::value_type>,
653 typename = _RequireInputIter<_InputIterator>,
654 typename = _RequireNotAllocatorOrIntegral<_Hash>,
655 typename = _RequireNotAllocator<_Pred>,
656 typename = _RequireAllocator<_Allocator>>
657 unordered_set(_InputIterator, _InputIterator,
658 unordered_set<int>::size_type = {},
659 _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator())
660 -> unordered_set<typename iterator_traits<_InputIterator>::value_type,
661 _Hash, _Pred, _Allocator>;
663 template<typename _Tp, typename _Hash = hash<_Tp>,
664 typename _Pred = equal_to<_Tp>,
665 typename _Allocator = allocator<_Tp>,
666 typename = _RequireNotAllocatorOrIntegral<_Hash>,
667 typename = _RequireNotAllocator<_Pred>,
668 typename = _RequireAllocator<_Allocator>>
669 unordered_set(initializer_list<_Tp>,
670 unordered_set<int>::size_type = {},
671 _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator())
672 -> unordered_set<_Tp, _Hash, _Pred, _Allocator>;
674 template<typename _InputIterator, typename _Allocator,
675 typename = _RequireInputIter<_InputIterator>,
676 typename = _RequireAllocator<_Allocator>>
677 unordered_set(_InputIterator, _InputIterator,
678 unordered_set<int>::size_type, _Allocator)
679 -> unordered_set<typename iterator_traits<_InputIterator>::value_type,
681 typename iterator_traits<_InputIterator>::value_type>,
683 typename iterator_traits<_InputIterator>::value_type>,
686 template<typename _InputIterator, typename _Hash, typename _Allocator,
687 typename = _RequireInputIter<_InputIterator>,
688 typename = _RequireNotAllocatorOrIntegral<_Hash>,
689 typename = _RequireAllocator<_Allocator>>
690 unordered_set(_InputIterator, _InputIterator,
691 unordered_set<int>::size_type,
693 -> unordered_set<typename iterator_traits<_InputIterator>::value_type,
696 typename iterator_traits<_InputIterator>::value_type>,
699 template<typename _Tp, typename _Allocator,
700 typename = _RequireAllocator<_Allocator>>
701 unordered_set(initializer_list<_Tp>,
702 unordered_set<int>::size_type, _Allocator)
703 -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
705 template<typename _Tp, typename _Hash, typename _Allocator,
706 typename = _RequireNotAllocatorOrIntegral<_Hash>,
707 typename = _RequireAllocator<_Allocator>>
708 unordered_set(initializer_list<_Tp>,
709 unordered_set<int>::size_type, _Hash, _Allocator)
710 -> unordered_set<_Tp, _Hash, equal_to<_Tp>, _Allocator>;
714 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
716 swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
717 unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
718 noexcept(noexcept(__x.swap(__y)))
721 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
723 operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
724 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
725 { return __x._M_base() == __y._M_base(); }
727 #if __cpp_impl_three_way_comparison < 201907L
728 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
730 operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
731 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
732 { return !(__x == __y); }
735 /// Class std::unordered_multiset with safety/checking/debug instrumentation.
736 template<typename _Value,
737 typename _Hash = std::hash<_Value>,
738 typename _Pred = std::equal_to<_Value>,
739 typename _Alloc = std::allocator<_Value> >
740 class unordered_multiset
741 : public __gnu_debug::_Safe_container<
742 unordered_multiset<_Value, _Hash, _Pred, _Alloc>, _Alloc,
743 __gnu_debug::_Safe_unordered_container>,
744 public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>
746 typedef _GLIBCXX_STD_C::unordered_multiset<
747 _Value, _Hash, _Pred, _Alloc> _Base;
748 typedef __gnu_debug::_Safe_container<unordered_multiset,
749 _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
750 typedef typename _Base::const_iterator _Base_const_iterator;
751 typedef typename _Base::iterator _Base_iterator;
752 typedef typename _Base::const_local_iterator
753 _Base_const_local_iterator;
754 typedef typename _Base::local_iterator _Base_local_iterator;
756 template<typename _ItT, typename _SeqT, typename _CatT>
757 friend class ::__gnu_debug::_Safe_iterator;
758 template<typename _ItT, typename _SeqT>
759 friend class ::__gnu_debug::_Safe_local_iterator;
761 // Reference wrapper for base class. See PR libstdc++/90102.
764 _Base_ref(const _Base& __r) : _M_ref(__r) { }
770 typedef typename _Base::size_type size_type;
771 typedef typename _Base::difference_type difference_type;
772 typedef typename _Base::hasher hasher;
773 typedef typename _Base::key_equal key_equal;
774 typedef typename _Base::allocator_type allocator_type;
776 typedef typename _Base::key_type key_type;
777 typedef typename _Base::value_type value_type;
779 typedef typename _Base::pointer pointer;
780 typedef typename _Base::const_pointer const_pointer;
781 typedef typename _Base::reference reference;
782 typedef typename _Base::const_reference const_reference;
783 typedef __gnu_debug::_Safe_iterator<
784 _Base_iterator, unordered_multiset> iterator;
785 typedef __gnu_debug::_Safe_iterator<
786 _Base_const_iterator, unordered_multiset> const_iterator;
787 typedef __gnu_debug::_Safe_local_iterator<
788 _Base_local_iterator, unordered_multiset> local_iterator;
789 typedef __gnu_debug::_Safe_local_iterator<
790 _Base_const_local_iterator, unordered_multiset> const_local_iterator;
792 unordered_multiset() = default;
795 unordered_multiset(size_type __n,
796 const hasher& __hf = hasher(),
797 const key_equal& __eql = key_equal(),
798 const allocator_type& __a = allocator_type())
799 : _Base(__n, __hf, __eql, __a) { }
801 template<typename _InputIterator>
802 unordered_multiset(_InputIterator __first, _InputIterator __last,
804 const hasher& __hf = hasher(),
805 const key_equal& __eql = key_equal(),
806 const allocator_type& __a = allocator_type())
807 : _Base(__gnu_debug::__base(
808 __glibcxx_check_valid_constructor_range(__first, __last)),
809 __gnu_debug::__base(__last), __n,
810 __hf, __eql, __a) { }
812 unordered_multiset(const unordered_multiset&) = default;
814 unordered_multiset(_Base_ref __x)
815 : _Base(__x._M_ref) { }
817 unordered_multiset(unordered_multiset&&) = default;
820 unordered_multiset(const allocator_type& __a)
823 unordered_multiset(const unordered_multiset& __uset,
824 const allocator_type& __a)
825 : _Base(__uset, __a) { }
827 unordered_multiset(unordered_multiset&& __uset,
828 const allocator_type& __a)
829 noexcept( noexcept(_Base(std::move(__uset), __a)) )
830 : _Safe(std::move(__uset), __a),
831 _Base(std::move(__uset), __a) { }
833 unordered_multiset(initializer_list<value_type> __l,
835 const hasher& __hf = hasher(),
836 const key_equal& __eql = key_equal(),
837 const allocator_type& __a = allocator_type())
838 : _Base(__l, __n, __hf, __eql, __a) { }
840 unordered_multiset(size_type __n, const allocator_type& __a)
841 : unordered_multiset(__n, hasher(), key_equal(), __a)
844 unordered_multiset(size_type __n, const hasher& __hf,
845 const allocator_type& __a)
846 : unordered_multiset(__n, __hf, key_equal(), __a)
849 template<typename _InputIterator>
850 unordered_multiset(_InputIterator __first, _InputIterator __last,
852 const allocator_type& __a)
853 : unordered_multiset(__first, __last, __n, hasher(), key_equal(), __a)
856 template<typename _InputIterator>
857 unordered_multiset(_InputIterator __first, _InputIterator __last,
858 size_type __n, const hasher& __hf,
859 const allocator_type& __a)
860 : unordered_multiset(__first, __last, __n, __hf, key_equal(), __a)
863 unordered_multiset(initializer_list<value_type> __l,
865 const allocator_type& __a)
866 : unordered_multiset(__l, __n, hasher(), key_equal(), __a)
869 unordered_multiset(initializer_list<value_type> __l,
870 size_type __n, const hasher& __hf,
871 const allocator_type& __a)
872 : unordered_multiset(__l, __n, __hf, key_equal(), __a)
875 ~unordered_multiset() = default;
878 operator=(const unordered_multiset&) = default;
881 operator=(unordered_multiset&&) = default;
884 operator=(initializer_list<value_type> __l)
886 _Base::operator=(__l);
887 this->_M_invalidate_all();
891 using _Base::get_allocator;
894 using _Base::max_size;
897 swap(unordered_multiset& __x)
898 noexcept( noexcept(declval<_Base&>().swap(__x)) )
908 this->_M_invalidate_all();
913 { return { _Base::begin(), this }; }
916 begin() const noexcept
917 { return { _Base::begin(), this }; }
921 { return { _Base::end(), this }; }
925 { return { _Base::end(), this }; }
928 cbegin() const noexcept
929 { return { _Base::cbegin(), this }; }
932 cend() const noexcept
933 { return { _Base::cend(), this }; }
939 __glibcxx_check_bucket_index(__b);
940 return { _Base::begin(__b), this };
946 __glibcxx_check_bucket_index(__b);
947 return { _Base::end(__b), this };
951 begin(size_type __b) const
953 __glibcxx_check_bucket_index(__b);
954 return { _Base::begin(__b), this };
958 end(size_type __b) const
960 __glibcxx_check_bucket_index(__b);
961 return { _Base::end(__b), this };
965 cbegin(size_type __b) const
967 __glibcxx_check_bucket_index(__b);
968 return { _Base::cbegin(__b), this };
972 cend(size_type __b) const
974 __glibcxx_check_bucket_index(__b);
975 return { _Base::cend(__b), this };
978 using _Base::bucket_count;
979 using _Base::max_bucket_count;
982 bucket_size(size_type __b) const
984 __glibcxx_check_bucket_index(__b);
985 return _Base::bucket_size(__b);
989 using _Base::load_factor;
992 max_load_factor() const noexcept
993 { return _Base::max_load_factor(); }
996 max_load_factor(float __f)
998 __glibcxx_check_max_load_factor(__f);
999 _Base::max_load_factor(__f);
1002 using _Base::rehash;
1003 using _Base::reserve;
1005 template<typename... _Args>
1007 emplace(_Args&&... __args)
1009 size_type __bucket_count = this->bucket_count();
1010 auto __it = _Base::emplace(std::forward<_Args>(__args)...);
1011 _M_check_rehashed(__bucket_count);
1012 return { __it, this };
1015 template<typename... _Args>
1017 emplace_hint(const_iterator __hint, _Args&&... __args)
1019 __glibcxx_check_insert(__hint);
1020 size_type __bucket_count = this->bucket_count();
1021 auto __it = _Base::emplace_hint(__hint.base(),
1022 std::forward<_Args>(__args)...);
1023 _M_check_rehashed(__bucket_count);
1024 return { __it, this };
1028 insert(const value_type& __obj)
1030 size_type __bucket_count = this->bucket_count();
1031 auto __it = _Base::insert(__obj);
1032 _M_check_rehashed(__bucket_count);
1033 return { __it, this };
1037 insert(const_iterator __hint, const value_type& __obj)
1039 __glibcxx_check_insert(__hint);
1040 size_type __bucket_count = this->bucket_count();
1041 auto __it = _Base::insert(__hint.base(), __obj);
1042 _M_check_rehashed(__bucket_count);
1043 return { __it, this };
1047 insert(value_type&& __obj)
1049 size_type __bucket_count = this->bucket_count();
1050 auto __it = _Base::insert(std::move(__obj));
1051 _M_check_rehashed(__bucket_count);
1052 return { __it, this };
1056 insert(const_iterator __hint, value_type&& __obj)
1058 __glibcxx_check_insert(__hint);
1059 size_type __bucket_count = this->bucket_count();
1060 auto __it = _Base::insert(__hint.base(), std::move(__obj));
1061 _M_check_rehashed(__bucket_count);
1062 return { __it, this };
1066 insert(std::initializer_list<value_type> __l)
1068 size_type __bucket_count = this->bucket_count();
1070 _M_check_rehashed(__bucket_count);
1073 template<typename _InputIterator>
1075 insert(_InputIterator __first, _InputIterator __last)
1077 typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
1078 __glibcxx_check_valid_range2(__first, __last, __dist);
1079 size_type __bucket_count = this->bucket_count();
1081 if (__dist.second >= __gnu_debug::__dp_sign)
1082 _Base::insert(__gnu_debug::__unsafe(__first),
1083 __gnu_debug::__unsafe(__last));
1085 _Base::insert(__first, __last);
1087 _M_check_rehashed(__bucket_count);
1090 #if __cplusplus > 201402L
1091 using node_type = typename _Base::node_type;
1094 extract(const_iterator __position)
1096 __glibcxx_check_erase(__position);
1097 return _M_extract(__position.base());
1101 extract(const key_type& __key)
1103 const auto __position = _Base::find(__key);
1104 if (__position != _Base::end())
1105 return _M_extract(__position);
1110 insert(node_type&& __nh)
1111 { return { _Base::insert(std::move(__nh)), this }; }
1114 insert(const_iterator __hint, node_type&& __nh)
1116 __glibcxx_check_insert(__hint);
1117 return { _Base::insert(__hint.base(), std::move(__nh)), this };
1120 template<typename _H2, typename _P2>
1122 merge(unordered_multiset<_Value, _H2, _P2, _Alloc>& __source)
1125 = _Safe::_S_umc_guard(std::__detail::_Identity{}, __source);
1126 _Base::merge(__source);
1129 template<typename _H2, typename _P2>
1131 merge(unordered_multiset<_Value, _H2, _P2, _Alloc>&& __source)
1132 { merge(__source); }
1134 template<typename _H2, typename _P2>
1136 merge(unordered_set<_Value, _H2, _P2, _Alloc>& __source)
1139 = _Safe::_S_uc_guard(std::__detail::_Identity{}, __source);
1140 _Base::merge(__source);
1143 template<typename _H2, typename _P2>
1145 merge(unordered_set<_Value, _H2, _P2, _Alloc>&& __source)
1146 { merge(__source); }
1149 using _Base::hash_function;
1150 using _Base::key_eq;
1153 find(const key_type& __key)
1154 { return { _Base::find(__key), this }; }
1156 #if __cplusplus > 201703L
1157 template<typename _Kt,
1158 typename = std::__has_is_transparent_t<_Hash, _Kt>,
1159 typename = std::__has_is_transparent_t<_Pred, _Kt>>
1161 find(const _Kt& __k)
1162 { return { _Base::find(__k), this }; }
1166 find(const key_type& __key) const
1167 { return { _Base::find(__key), this }; }
1169 #if __cplusplus > 201703L
1170 template<typename _Kt,
1171 typename = std::__has_is_transparent_t<_Hash, _Kt>,
1172 typename = std::__has_is_transparent_t<_Pred, _Kt>>
1174 find(const _Kt& __k) const
1175 { return { _Base::find(__k), this }; }
1180 #if __cplusplus > 201703L
1181 using _Base::contains;
1184 std::pair<iterator, iterator>
1185 equal_range(const key_type& __key)
1187 auto __res = _Base::equal_range(__key);
1188 return { { __res.first, this }, { __res.second, this } };
1191 #if __cplusplus > 201703L
1192 template<typename _Kt,
1193 typename = std::__has_is_transparent_t<_Hash, _Kt>,
1194 typename = std::__has_is_transparent_t<_Pred, _Kt>>
1195 std::pair<iterator, iterator>
1196 equal_range(const _Kt& __k)
1198 auto __res = _Base::equal_range(__k);
1199 return { { __res.first, this }, { __res.second, this } };
1203 std::pair<const_iterator, const_iterator>
1204 equal_range(const key_type& __key) const
1206 auto __res = _Base::equal_range(__key);
1207 return { { __res.first, this }, { __res.second, this } };
1210 #if __cplusplus > 201703L
1211 template<typename _Kt,
1212 typename = std::__has_is_transparent_t<_Hash, _Kt>,
1213 typename = std::__has_is_transparent_t<_Pred, _Kt>>
1214 std::pair<const_iterator, const_iterator>
1215 equal_range(const _Kt& __k) const
1217 auto __res = _Base::equal_range(__k);
1218 return { { __res.first, this }, { __res.second, this } };
1223 erase(const key_type& __key)
1226 auto __pair = _Base::equal_range(__key);
1227 for (auto __victim = __pair.first; __victim != __pair.second;)
1229 _M_invalidate(__victim);
1230 __victim = _Base::erase(__victim);
1238 erase(const_iterator __it)
1240 __glibcxx_check_erase(__it);
1241 return { _M_erase(__it.base()), this };
1245 erase(_Base_const_iterator __it)
1247 __glibcxx_check_erase2(__it);
1248 return _M_erase(__it);
1252 erase(iterator __it)
1254 __glibcxx_check_erase(__it);
1255 return { _M_erase(__it.base()), this };
1259 erase(const_iterator __first, const_iterator __last)
1261 __glibcxx_check_erase_range(__first, __last);
1262 for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp)
1264 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(),
1265 _M_message(__gnu_debug::__msg_valid_range)
1266 ._M_iterator(__first, "first")
1267 ._M_iterator(__last, "last"));
1268 _M_invalidate(__tmp);
1270 return { _Base::erase(__first.base(), __last.base()), this };
1274 _M_base() noexcept { return *this; }
1277 _M_base() const noexcept { return *this; }
1281 _M_check_rehashed(size_type __prev_count)
1283 if (__prev_count != this->bucket_count())
1284 this->_M_invalidate_all();
1288 _M_invalidate(_Base_const_iterator __victim)
1290 this->_M_invalidate_if(
1291 [__victim](_Base_const_iterator __it) { return __it == __victim; });
1292 this->_M_invalidate_local_if(
1293 [__victim](_Base_const_local_iterator __it)
1294 { return __it == __victim; });
1298 _M_erase(_Base_const_iterator __victim)
1300 _M_invalidate(__victim);
1301 size_type __bucket_count = this->bucket_count();
1302 _Base_iterator __next = _Base::erase(__victim);
1303 _M_check_rehashed(__bucket_count);
1307 #if __cplusplus > 201402L
1309 _M_extract(_Base_const_iterator __victim)
1311 _M_invalidate(__victim);
1312 return _Base::extract(__victim);
1317 #if __cpp_deduction_guides >= 201606
1319 template<typename _InputIterator,
1321 hash<typename iterator_traits<_InputIterator>::value_type>,
1323 equal_to<typename iterator_traits<_InputIterator>::value_type>,
1324 typename _Allocator =
1325 allocator<typename iterator_traits<_InputIterator>::value_type>,
1326 typename = _RequireInputIter<_InputIterator>,
1327 typename = _RequireNotAllocatorOrIntegral<_Hash>,
1328 typename = _RequireNotAllocator<_Pred>,
1329 typename = _RequireAllocator<_Allocator>>
1330 unordered_multiset(_InputIterator, _InputIterator,
1331 unordered_multiset<int>::size_type = {},
1332 _Hash = _Hash(), _Pred = _Pred(),
1333 _Allocator = _Allocator())
1334 -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type,
1335 _Hash, _Pred, _Allocator>;
1337 template<typename _Tp, typename _Hash = hash<_Tp>,
1338 typename _Pred = equal_to<_Tp>,
1339 typename _Allocator = allocator<_Tp>,
1340 typename = _RequireNotAllocatorOrIntegral<_Hash>,
1341 typename = _RequireNotAllocator<_Pred>,
1342 typename = _RequireAllocator<_Allocator>>
1343 unordered_multiset(initializer_list<_Tp>,
1344 unordered_multiset<int>::size_type = {},
1345 _Hash = _Hash(), _Pred = _Pred(),
1346 _Allocator = _Allocator())
1347 -> unordered_multiset<_Tp, _Hash, _Pred, _Allocator>;
1349 template<typename _InputIterator, typename _Allocator,
1350 typename = _RequireInputIter<_InputIterator>,
1351 typename = _RequireAllocator<_Allocator>>
1352 unordered_multiset(_InputIterator, _InputIterator,
1353 unordered_multiset<int>::size_type, _Allocator)
1354 -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type,
1356 iterator_traits<_InputIterator>::value_type>,
1358 iterator_traits<_InputIterator>::value_type>,
1361 template<typename _InputIterator, typename _Hash, typename _Allocator,
1362 typename = _RequireInputIter<_InputIterator>,
1363 typename = _RequireNotAllocatorOrIntegral<_Hash>,
1364 typename = _RequireAllocator<_Allocator>>
1365 unordered_multiset(_InputIterator, _InputIterator,
1366 unordered_multiset<int>::size_type,
1368 -> unordered_multiset<typename
1369 iterator_traits<_InputIterator>::value_type,
1373 iterator_traits<_InputIterator>::value_type>,
1376 template<typename _Tp, typename _Allocator,
1377 typename = _RequireAllocator<_Allocator>>
1378 unordered_multiset(initializer_list<_Tp>,
1379 unordered_multiset<int>::size_type, _Allocator)
1380 -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
1382 template<typename _Tp, typename _Hash, typename _Allocator,
1383 typename = _RequireNotAllocatorOrIntegral<_Hash>,
1384 typename = _RequireAllocator<_Allocator>>
1385 unordered_multiset(initializer_list<_Tp>,
1386 unordered_multiset<int>::size_type, _Hash, _Allocator)
1387 -> unordered_multiset<_Tp, _Hash, equal_to<_Tp>, _Allocator>;
1391 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
1393 swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
1394 unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
1395 noexcept(noexcept(__x.swap(__y)))
1398 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
1400 operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
1401 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
1402 { return __x._M_base() == __y._M_base(); }
1404 #if __cpp_impl_three_way_comparison < 201907L
1405 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
1407 operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
1408 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
1409 { return !(__x == __y); }
1412 } // namespace __debug