1 // Debugging unordered_set/unordered_multiset implementation -*- C++ -*-
3 // Copyright (C) 2003-2026 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 #ifdef _GLIBCXX_SYSHDR
33 #pragma GCC system_header
36 #if __cplusplus < 201103L
37 # include <bits/c++0x_warning.h>
39 # include <bits/c++config.h>
40 namespace std _GLIBCXX_VISIBILITY(default) { namespace __debug {
41 template<typename _Key, typename _Hash, typename _Pred, typename _Allocator>
43 template<typename _Key, typename _Hash, typename _Pred, typename _Allocator>
44 class unordered_multiset;
45 } } // namespace std::__debug
46 # include <unordered_set>
48 #include <debug/safe_unordered_container.h>
49 #include <debug/safe_container.h>
50 #include <debug/safe_iterator.h>
51 #include <debug/safe_local_iterator.h>
53 namespace std _GLIBCXX_VISIBILITY(default)
57 /// Class std::unordered_set with safety/checking/debug instrumentation.
58 template<typename _Value,
59 typename _Hash = std::hash<_Value>,
60 typename _Pred = std::equal_to<_Value>,
61 typename _Alloc = std::allocator<_Value> >
63 : public __gnu_debug::_Safe_container<
64 unordered_set<_Value, _Hash, _Pred, _Alloc>, _Alloc,
65 __gnu_debug::_Safe_unordered_container>,
66 public _GLIBCXX_STD_C::unordered_set<_Value, _Hash, _Pred, _Alloc>
68 typedef _GLIBCXX_STD_C::unordered_set<
69 _Value, _Hash, _Pred, _Alloc> _Base;
70 typedef __gnu_debug::_Safe_container<
71 unordered_set, _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
73 typedef typename _Base::const_iterator _Base_const_iterator;
74 typedef typename _Base::iterator _Base_iterator;
75 typedef typename _Base::const_local_iterator _Base_const_local_iterator;
76 typedef typename _Base::local_iterator _Base_local_iterator;
78 template<typename _ItT, typename _SeqT, typename _CatT>
79 friend class ::__gnu_debug::_Safe_iterator;
80 template<typename _ItT, typename _SeqT>
81 friend class ::__gnu_debug::_Safe_local_iterator;
83 // Reference wrapper for base class. See PR libstdc++/90102.
86 _Base_ref(const _Base& __r) : _M_ref(__r) { }
92 typedef typename _Base::size_type size_type;
93 typedef typename _Base::difference_type difference_type;
94 typedef typename _Base::hasher hasher;
95 typedef typename _Base::key_equal key_equal;
96 typedef typename _Base::allocator_type allocator_type;
98 typedef typename _Base::key_type key_type;
99 typedef typename _Base::value_type value_type;
101 typedef typename _Base::pointer pointer;
102 typedef typename _Base::const_pointer const_pointer;
103 typedef typename _Base::reference reference;
104 typedef typename _Base::const_reference const_reference;
105 typedef __gnu_debug::_Safe_iterator<
106 _Base_iterator, unordered_set> iterator;
107 typedef __gnu_debug::_Safe_iterator<
108 _Base_const_iterator, unordered_set> const_iterator;
109 typedef __gnu_debug::_Safe_local_iterator<
110 _Base_local_iterator, unordered_set> local_iterator;
111 typedef __gnu_debug::_Safe_local_iterator<
112 _Base_const_local_iterator, unordered_set> const_local_iterator;
114 unordered_set() = default;
117 unordered_set(size_type __n,
118 const hasher& __hf = hasher(),
119 const key_equal& __eql = key_equal(),
120 const allocator_type& __a = allocator_type())
121 : _Base(__n, __hf, __eql, __a) { }
123 template<typename _InputIterator>
124 unordered_set(_InputIterator __first, _InputIterator __last,
126 const hasher& __hf = hasher(),
127 const key_equal& __eql = key_equal(),
128 const allocator_type& __a = allocator_type())
129 : _Base(__gnu_debug::__base(
130 __glibcxx_check_valid_constructor_range(__first, __last)),
131 __gnu_debug::__base(__last), __n,
132 __hf, __eql, __a) { }
134 unordered_set(const unordered_set&) = default;
136 unordered_set(_Base_ref __x)
137 : _Base(__x._M_ref) { }
139 unordered_set(unordered_set&&) = default;
142 unordered_set(const allocator_type& __a)
145 unordered_set(const unordered_set& __uset,
146 const allocator_type& __a)
147 : _Base(__uset, __a) { }
149 unordered_set(unordered_set&& __uset,
150 const allocator_type& __a)
151 noexcept( noexcept(_Base(std::move(__uset), __a)) )
152 : _Safe(std::move(__uset), __a),
153 _Base(std::move(__uset), __a) { }
155 unordered_set(initializer_list<value_type> __l,
157 const hasher& __hf = hasher(),
158 const key_equal& __eql = key_equal(),
159 const allocator_type& __a = allocator_type())
160 : _Base(__l, __n, __hf, __eql, __a) { }
162 unordered_set(size_type __n, const allocator_type& __a)
163 : unordered_set(__n, hasher(), key_equal(), __a)
166 unordered_set(size_type __n, const hasher& __hf,
167 const allocator_type& __a)
168 : unordered_set(__n, __hf, key_equal(), __a)
171 template<typename _InputIterator>
172 unordered_set(_InputIterator __first, _InputIterator __last,
173 const allocator_type& __a)
174 : unordered_set(__first, __last, 0, hasher(), key_equal(), __a)
177 template<typename _InputIterator>
178 unordered_set(_InputIterator __first, _InputIterator __last,
180 const allocator_type& __a)
181 : unordered_set(__first, __last, __n, hasher(), key_equal(), __a)
184 template<typename _InputIterator>
185 unordered_set(_InputIterator __first, _InputIterator __last,
186 size_type __n, const hasher& __hf,
187 const allocator_type& __a)
188 : unordered_set(__first, __last, __n, __hf, key_equal(), __a)
191 unordered_set(initializer_list<value_type> __l,
192 const allocator_type& __a)
193 : unordered_set(__l, 0, hasher(), key_equal(), __a)
196 unordered_set(initializer_list<value_type> __l,
198 const allocator_type& __a)
199 : unordered_set(__l, __n, hasher(), key_equal(), __a)
202 unordered_set(initializer_list<value_type> __l,
203 size_type __n, const hasher& __hf,
204 const allocator_type& __a)
205 : unordered_set(__l, __n, __hf, key_equal(), __a)
208 #if __glibcxx_containers_ranges // C++ >= 23
209 template<__detail::__container_compatible_range<value_type> _Rg>
210 unordered_set(from_range_t, _Rg&& __rg,
212 const hasher& __hf = hasher(),
213 const key_equal& __eql = key_equal(),
214 const allocator_type& __a = allocator_type())
215 : _Base(from_range, std::forward<_Rg>(__rg), __n, __hf, __eql, __a)
218 template<__detail::__container_compatible_range<value_type> _Rg>
219 unordered_set(from_range_t, _Rg&& __rg, const allocator_type& __a)
220 : _Base(from_range, std::forward<_Rg>(__rg), __a)
223 template<__detail::__container_compatible_range<value_type> _Rg>
224 unordered_set(from_range_t, _Rg&& __rg, size_type __n,
225 const allocator_type& __a)
226 : _Base(from_range, std::forward<_Rg>(__rg), __n, __a)
229 template<__detail::__container_compatible_range<value_type> _Rg>
230 unordered_set(from_range_t, _Rg&& __rg, size_type __n,
231 const hasher& __hf, const allocator_type& __a)
232 : _Base(from_range, std::forward<_Rg>(__rg), __n, __hf, __a)
236 ~unordered_set() = default;
239 operator=(const unordered_set&) = default;
242 operator=(unordered_set&&) = default;
245 operator=(initializer_list<value_type> __l)
247 _Base::operator=(__l);
248 this->_M_invalidate_all();
252 using _Base::get_allocator;
255 using _Base::max_size;
258 swap(unordered_set& __x)
259 noexcept( noexcept(declval<_Base&>().swap(__x)) )
269 this->_M_invalidate_all();
274 { return { _Base::begin(), this }; }
277 begin() const noexcept
278 { return { _Base::begin(), this }; }
282 { return { _Base::end(), this }; }
286 { return { _Base::end(), this }; }
289 cbegin() const noexcept
290 { return { _Base::cbegin(), this }; }
293 cend() const noexcept
294 { return { _Base::cend(), this }; }
300 __glibcxx_check_bucket_index(__b);
301 return { _Base::begin(__b), this };
307 __glibcxx_check_bucket_index(__b);
308 return { _Base::end(__b), this };
312 begin(size_type __b) const
314 __glibcxx_check_bucket_index(__b);
315 return { _Base::begin(__b), this };
319 end(size_type __b) const
321 __glibcxx_check_bucket_index(__b);
322 return { _Base::end(__b), this };
326 cbegin(size_type __b) const
328 __glibcxx_check_bucket_index(__b);
329 return { _Base::cbegin(__b), this };
333 cend(size_type __b) const
335 __glibcxx_check_bucket_index(__b);
336 return { _Base::cend(__b), this };
339 using _Base::bucket_count;
340 using _Base::max_bucket_count;
343 bucket_size(size_type __b) const
345 __glibcxx_check_bucket_index(__b);
346 return _Base::bucket_size(__b);
350 using _Base::load_factor;
353 max_load_factor() const noexcept
354 { return _Base::max_load_factor(); }
357 max_load_factor(float __f)
359 __glibcxx_check_max_load_factor(__f);
360 _Base::max_load_factor(__f);
364 using _Base::reserve;
366 template<typename... _Args>
367 std::pair<iterator, bool>
368 emplace(_Args&&... __args)
370 size_type __bucket_count = this->bucket_count();
371 auto __res = _Base::emplace(std::forward<_Args>(__args)...);
372 _M_check_rehashed(__bucket_count);
373 return { { __res.first, this }, __res.second };
376 template<typename... _Args>
378 emplace_hint(const_iterator __hint, _Args&&... __args)
380 __glibcxx_check_insert(__hint);
381 size_type __bucket_count = this->bucket_count();
382 auto __it = _Base::emplace_hint(__hint.base(),
383 std::forward<_Args>(__args)...);
384 _M_check_rehashed(__bucket_count);
385 return { __it, this };
388 std::pair<iterator, bool>
389 insert(const value_type& __obj)
391 size_type __bucket_count = this->bucket_count();
392 auto __res = _Base::insert(__obj);
393 _M_check_rehashed(__bucket_count);
394 return { { __res.first, this }, __res.second };
398 insert(const_iterator __hint, const value_type& __obj)
400 __glibcxx_check_insert(__hint);
401 size_type __bucket_count = this->bucket_count();
402 auto __it = _Base::insert(__hint.base(), __obj);
403 _M_check_rehashed(__bucket_count);
404 return { __it, this };
407 std::pair<iterator, bool>
408 insert(value_type&& __obj)
410 size_type __bucket_count = this->bucket_count();
411 auto __res = _Base::insert(std::move(__obj));
412 _M_check_rehashed(__bucket_count);
413 return { { __res.first, this }, __res.second };
416 # ifdef __glibcxx_associative_heterogeneous_insertion
417 template <__heterogeneous_hash_key<unordered_set> _Kt>
418 std::pair<iterator, bool>
421 size_type __bucket_count = this->bucket_count();
422 auto __res = _Base::insert(std::forward<_Kt>(__obj));
423 _M_check_rehashed(__bucket_count);
424 return { { __res.first, this }, __res.second };
429 insert(const_iterator __hint, value_type&& __obj)
431 __glibcxx_check_insert(__hint);
432 size_type __bucket_count = this->bucket_count();
433 auto __it = _Base::insert(__hint.base(), std::move(__obj));
434 _M_check_rehashed(__bucket_count);
435 return { __it, this };
438 # ifdef __glibcxx_associative_heterogeneous_insertion
439 template <__heterogeneous_hash_key<unordered_set> _Kt>
441 insert(const_iterator __hint, _Kt&& __obj)
443 __glibcxx_check_insert(__hint);
444 size_type __bucket_count = this->bucket_count();
445 auto __it = _Base::insert(
446 __hint.base(), std::forward<_Kt>(__obj));
447 _M_check_rehashed(__bucket_count);
448 return { __it, this };
453 insert(std::initializer_list<value_type> __l)
455 size_type __bucket_count = this->bucket_count();
457 _M_check_rehashed(__bucket_count);
460 template<typename _InputIterator>
462 insert(_InputIterator __first, _InputIterator __last)
464 typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
465 __glibcxx_check_valid_range2(__first, __last, __dist);
466 size_type __bucket_count = this->bucket_count();
468 if (__dist.second >= __gnu_debug::__dp_sign)
469 _Base::insert(__gnu_debug::__unsafe(__first),
470 __gnu_debug::__unsafe(__last));
472 _Base::insert(__first, __last);
474 _M_check_rehashed(__bucket_count);
477 #ifdef __glibcxx_node_extract // >= C++17 && HOSTED
478 using node_type = typename _Base::node_type;
479 using insert_return_type = _Node_insert_return<iterator, node_type>;
482 extract(const_iterator __position)
484 __glibcxx_check_erase(__position);
485 return _M_extract(__position.base());
489 extract(const key_type& __key)
491 const auto __position = _Base::find(__key);
492 if (__position != _Base::end())
493 return _M_extract(__position);
497 # ifdef __glibcxx_associative_heterogeneous_erasure
498 template <__heterogeneous_hash_key<unordered_set> _Kt>
502 const auto __position = _Base::find(__key);
503 if (__position != _Base::end())
504 return _M_extract(__position);
510 insert(node_type&& __nh)
512 auto __ret = _Base::insert(std::move(__nh));
514 { { __ret.position, this }, __ret.inserted, std::move(__ret.node) };
518 insert(const_iterator __hint, node_type&& __nh)
520 __glibcxx_check_insert(__hint);
521 return { _Base::insert(__hint.base(), std::move(__nh)), this };
524 template<typename _H2, typename _P2>
526 merge(unordered_set<_Value, _H2, _P2, _Alloc>& __source)
529 = _Safe::_S_uc_guard(std::__detail::_Identity{}, __source);
530 _Base::merge(__source);
533 template<typename _H2, typename _P2>
535 merge(unordered_set<_Value, _H2, _P2, _Alloc>&& __source)
538 template<typename _H2, typename _P2>
540 merge(unordered_multiset<_Value, _H2, _P2, _Alloc>& __source)
543 = _Safe::_S_umc_guard(std::__detail::_Identity{}, __source);
544 _Base::merge(__source);
547 template<typename _H2, typename _P2>
549 merge(unordered_multiset<_Value, _H2, _P2, _Alloc>&& __source)
553 using _Base::hash_function;
557 find(const key_type& __key)
558 { return { _Base::find(__key), this }; }
560 #ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
561 template<typename _Kt,
562 typename = std::__has_is_transparent_t<_Hash, _Kt>,
563 typename = std::__has_is_transparent_t<_Pred, _Kt>>
566 { return { _Base::find(__k), this }; }
570 find(const key_type& __key) const
571 { return { _Base::find(__key), this }; }
573 #ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
574 template<typename _Kt,
575 typename = std::__has_is_transparent_t<_Hash, _Kt>,
576 typename = std::__has_is_transparent_t<_Pred, _Kt>>
578 find(const _Kt& __k) const
579 { return { _Base::find(__k), this }; }
584 #if __cplusplus > 201703L
585 using _Base::contains;
588 std::pair<iterator, iterator>
589 equal_range(const key_type& __key)
591 auto __res = _Base::equal_range(__key);
592 return { { __res.first, this }, { __res.second, this } };
595 #ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
596 template<typename _Kt,
597 typename = std::__has_is_transparent_t<_Hash, _Kt>,
598 typename = std::__has_is_transparent_t<_Pred, _Kt>>
599 std::pair<iterator, iterator>
600 equal_range(const _Kt& __k)
602 auto __res = _Base::equal_range(__k);
603 return { { __res.first, this }, { __res.second, this } };
607 std::pair<const_iterator, const_iterator>
608 equal_range(const key_type& __key) const
610 auto __res = _Base::equal_range(__key);
611 return { { __res.first, this }, { __res.second, this } };
614 #ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
615 template<typename _Kt,
616 typename = std::__has_is_transparent_t<_Hash, _Kt>,
617 typename = std::__has_is_transparent_t<_Pred, _Kt>>
618 std::pair<const_iterator, const_iterator>
619 equal_range(const _Kt& __k) const
621 auto __res = _Base::equal_range(__k);
622 return { { __res.first, this }, { __res.second, this } };
627 erase(const key_type& __key)
630 auto __victim = _Base::find(__key);
631 if (__victim != _Base::end())
639 # ifdef __glibcxx_associative_heterogeneous_erasure
640 template <__heterogeneous_hash_key<unordered_set> _Kt>
644 auto __victim = _Base::find(__key);
645 if (__victim != _Base::end())
646 return _M_erase(__victim), 1;
652 erase(const_iterator __it)
654 __glibcxx_check_erase(__it);
655 return { _M_erase(__it.base()), this };
659 erase(_Base_const_iterator __it)
661 __glibcxx_check_erase2(__it);
662 return _M_erase(__it);
668 __glibcxx_check_erase(__it);
669 return { _M_erase(__it.base()), this };
673 erase(const_iterator __first, const_iterator __last)
675 __glibcxx_check_erase_range(__first, __last);
677 __gnu_cxx::__scoped_lock sentry(_M_self()->_M_get_mutex());
678 for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp)
680 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(),
681 _M_message(__gnu_debug::__msg_valid_range)
682 ._M_iterator(__first, "first")
683 ._M_iterator(__last, "last"));
684 this->_M_invalidate(__tmp, sentry);
688 auto __next = _Base::erase(__first.base(), __last.base());
689 return { __next, this };
693 _M_base() noexcept { return *this; }
696 _M_base() const noexcept { return *this; }
700 _M_self() const noexcept
704 _M_check_rehashed(size_type __prev_count)
706 if (__prev_count != this->bucket_count())
707 this->_M_invalidate_all();
711 _M_erase(_Base_const_iterator __victim)
713 this->_M_invalidate(__victim);
714 return _Base::erase(__victim);
717 #ifdef __glibcxx_node_extract // >= C++17 && HOSTED
719 _M_extract(_Base_const_iterator __victim)
721 this->_M_invalidate(__victim);
722 return _Base::extract(__victim);
727 #if __cpp_deduction_guides >= 201606
729 template<typename _InputIterator,
731 hash<typename iterator_traits<_InputIterator>::value_type>,
733 equal_to<typename iterator_traits<_InputIterator>::value_type>,
734 typename _Allocator =
735 allocator<typename iterator_traits<_InputIterator>::value_type>,
736 typename = _RequireInputIter<_InputIterator>,
737 typename = _RequireNotAllocatorOrIntegral<_Hash>,
738 typename = _RequireNotAllocator<_Pred>,
739 typename = _RequireAllocator<_Allocator>>
740 unordered_set(_InputIterator, _InputIterator,
741 unordered_set<int>::size_type = {},
742 _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator())
743 -> unordered_set<typename iterator_traits<_InputIterator>::value_type,
744 _Hash, _Pred, _Allocator>;
746 template<typename _Tp, typename _Hash = hash<_Tp>,
747 typename _Pred = equal_to<_Tp>,
748 typename _Allocator = allocator<_Tp>,
749 typename = _RequireNotAllocatorOrIntegral<_Hash>,
750 typename = _RequireNotAllocator<_Pred>,
751 typename = _RequireAllocator<_Allocator>>
752 unordered_set(initializer_list<_Tp>,
753 unordered_set<int>::size_type = {},
754 _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator())
755 -> unordered_set<_Tp, _Hash, _Pred, _Allocator>;
757 template<typename _InputIterator, typename _Allocator,
758 typename = _RequireInputIter<_InputIterator>,
759 typename = _RequireAllocator<_Allocator>>
760 unordered_set(_InputIterator, _InputIterator,
761 unordered_set<int>::size_type, _Allocator)
762 -> unordered_set<typename iterator_traits<_InputIterator>::value_type,
764 typename iterator_traits<_InputIterator>::value_type>,
766 typename iterator_traits<_InputIterator>::value_type>,
769 template<typename _InputIterator, typename _Allocator,
770 typename = _RequireInputIter<_InputIterator>,
771 typename = _RequireAllocator<_Allocator>>
772 unordered_set(_InputIterator, _InputIterator, _Allocator)
773 -> unordered_set<typename iterator_traits<_InputIterator>::value_type,
775 typename iterator_traits<_InputIterator>::value_type>,
777 typename iterator_traits<_InputIterator>::value_type>,
780 template<typename _InputIterator, typename _Hash, typename _Allocator,
781 typename = _RequireInputIter<_InputIterator>,
782 typename = _RequireNotAllocatorOrIntegral<_Hash>,
783 typename = _RequireAllocator<_Allocator>>
784 unordered_set(_InputIterator, _InputIterator,
785 unordered_set<int>::size_type,
787 -> unordered_set<typename iterator_traits<_InputIterator>::value_type,
790 typename iterator_traits<_InputIterator>::value_type>,
793 template<typename _Tp, typename _Allocator,
794 typename = _RequireAllocator<_Allocator>>
795 unordered_set(initializer_list<_Tp>,
796 unordered_set<int>::size_type, _Allocator)
797 -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
799 template<typename _Tp, typename _Allocator,
800 typename = _RequireAllocator<_Allocator>>
801 unordered_set(initializer_list<_Tp>, _Allocator)
802 -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
804 template<typename _Tp, typename _Hash, typename _Allocator,
805 typename = _RequireNotAllocatorOrIntegral<_Hash>,
806 typename = _RequireAllocator<_Allocator>>
807 unordered_set(initializer_list<_Tp>,
808 unordered_set<int>::size_type, _Hash, _Allocator)
809 -> unordered_set<_Tp, _Hash, equal_to<_Tp>, _Allocator>;
813 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
815 swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
816 unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
817 noexcept(noexcept(__x.swap(__y)))
820 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
822 operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
823 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
824 { return __x._M_base() == __y._M_base(); }
826 #if __cpp_impl_three_way_comparison < 201907L
827 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
829 operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x,
830 const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y)
831 { return !(__x == __y); }
834 /// Class std::unordered_multiset with safety/checking/debug instrumentation.
835 template<typename _Value,
836 typename _Hash = std::hash<_Value>,
837 typename _Pred = std::equal_to<_Value>,
838 typename _Alloc = std::allocator<_Value> >
839 class unordered_multiset
840 : public __gnu_debug::_Safe_container<
841 unordered_multiset<_Value, _Hash, _Pred, _Alloc>, _Alloc,
842 __gnu_debug::_Safe_unordered_container>,
843 public _GLIBCXX_STD_C::unordered_multiset<_Value, _Hash, _Pred, _Alloc>
845 typedef _GLIBCXX_STD_C::unordered_multiset<
846 _Value, _Hash, _Pred, _Alloc> _Base;
847 typedef __gnu_debug::_Safe_container<unordered_multiset,
848 _Alloc, __gnu_debug::_Safe_unordered_container> _Safe;
849 typedef typename _Base::const_iterator _Base_const_iterator;
850 typedef typename _Base::iterator _Base_iterator;
851 typedef typename _Base::const_local_iterator
852 _Base_const_local_iterator;
853 typedef typename _Base::local_iterator _Base_local_iterator;
855 template<typename _ItT, typename _SeqT, typename _CatT>
856 friend class ::__gnu_debug::_Safe_iterator;
857 template<typename _ItT, typename _SeqT>
858 friend class ::__gnu_debug::_Safe_local_iterator;
860 // Reference wrapper for base class. See PR libstdc++/90102.
863 _Base_ref(const _Base& __r) : _M_ref(__r) { }
869 typedef typename _Base::size_type size_type;
870 typedef typename _Base::difference_type difference_type;
871 typedef typename _Base::hasher hasher;
872 typedef typename _Base::key_equal key_equal;
873 typedef typename _Base::allocator_type allocator_type;
875 typedef typename _Base::key_type key_type;
876 typedef typename _Base::value_type value_type;
878 typedef typename _Base::pointer pointer;
879 typedef typename _Base::const_pointer const_pointer;
880 typedef typename _Base::reference reference;
881 typedef typename _Base::const_reference const_reference;
882 typedef __gnu_debug::_Safe_iterator<
883 _Base_iterator, unordered_multiset> iterator;
884 typedef __gnu_debug::_Safe_iterator<
885 _Base_const_iterator, unordered_multiset> const_iterator;
886 typedef __gnu_debug::_Safe_local_iterator<
887 _Base_local_iterator, unordered_multiset> local_iterator;
888 typedef __gnu_debug::_Safe_local_iterator<
889 _Base_const_local_iterator, unordered_multiset> const_local_iterator;
891 unordered_multiset() = default;
894 unordered_multiset(size_type __n,
895 const hasher& __hf = hasher(),
896 const key_equal& __eql = key_equal(),
897 const allocator_type& __a = allocator_type())
898 : _Base(__n, __hf, __eql, __a) { }
900 template<typename _InputIterator>
901 unordered_multiset(_InputIterator __first, _InputIterator __last,
903 const hasher& __hf = hasher(),
904 const key_equal& __eql = key_equal(),
905 const allocator_type& __a = allocator_type())
906 : _Base(__gnu_debug::__base(
907 __glibcxx_check_valid_constructor_range(__first, __last)),
908 __gnu_debug::__base(__last), __n,
909 __hf, __eql, __a) { }
911 unordered_multiset(const unordered_multiset&) = default;
913 unordered_multiset(_Base_ref __x)
914 : _Base(__x._M_ref) { }
916 unordered_multiset(unordered_multiset&&) = default;
919 unordered_multiset(const allocator_type& __a)
922 unordered_multiset(const unordered_multiset& __uset,
923 const allocator_type& __a)
924 : _Base(__uset, __a) { }
926 unordered_multiset(unordered_multiset&& __uset,
927 const allocator_type& __a)
928 noexcept( noexcept(_Base(std::move(__uset), __a)) )
929 : _Safe(std::move(__uset), __a),
930 _Base(std::move(__uset), __a) { }
932 unordered_multiset(initializer_list<value_type> __l,
934 const hasher& __hf = hasher(),
935 const key_equal& __eql = key_equal(),
936 const allocator_type& __a = allocator_type())
937 : _Base(__l, __n, __hf, __eql, __a) { }
939 unordered_multiset(size_type __n, const allocator_type& __a)
940 : unordered_multiset(__n, hasher(), key_equal(), __a)
943 unordered_multiset(size_type __n, const hasher& __hf,
944 const allocator_type& __a)
945 : unordered_multiset(__n, __hf, key_equal(), __a)
948 template<typename _InputIterator>
949 unordered_multiset(_InputIterator __first, _InputIterator __last,
950 const allocator_type& __a)
951 : unordered_multiset(__first, __last, 0, hasher(), key_equal(), __a)
954 template<typename _InputIterator>
955 unordered_multiset(_InputIterator __first, _InputIterator __last,
957 const allocator_type& __a)
958 : unordered_multiset(__first, __last, __n, hasher(), key_equal(), __a)
961 template<typename _InputIterator>
962 unordered_multiset(_InputIterator __first, _InputIterator __last,
963 size_type __n, const hasher& __hf,
964 const allocator_type& __a)
965 : unordered_multiset(__first, __last, __n, __hf, key_equal(), __a)
968 unordered_multiset(initializer_list<value_type> __l,
969 const allocator_type& __a)
970 : unordered_multiset(__l, 0, hasher(), key_equal(), __a)
973 unordered_multiset(initializer_list<value_type> __l,
975 const allocator_type& __a)
976 : unordered_multiset(__l, __n, hasher(), key_equal(), __a)
979 unordered_multiset(initializer_list<value_type> __l,
980 size_type __n, const hasher& __hf,
981 const allocator_type& __a)
982 : unordered_multiset(__l, __n, __hf, key_equal(), __a)
985 #if __glibcxx_containers_ranges // C++ >= 23
986 template<__detail::__container_compatible_range<value_type> _Rg>
987 unordered_multiset(from_range_t, _Rg&& __rg,
989 const hasher& __hf = hasher(),
990 const key_equal& __eql = key_equal(),
991 const allocator_type& __a = allocator_type())
992 : _Base(from_range, std::forward<_Rg>(__rg), __n, __hf, __eql, __a)
995 template<__detail::__container_compatible_range<value_type> _Rg>
996 unordered_multiset(from_range_t, _Rg&& __rg, const allocator_type& __a)
997 : _Base(from_range, std::forward<_Rg>(__rg), __a)
1000 template<__detail::__container_compatible_range<value_type> _Rg>
1001 unordered_multiset(from_range_t, _Rg&& __rg, size_type __n,
1002 const allocator_type& __a)
1003 : _Base(from_range, std::forward<_Rg>(__rg), __n, __a)
1006 template<__detail::__container_compatible_range<value_type> _Rg>
1007 unordered_multiset(from_range_t, _Rg&& __rg, size_type __n,
1008 const hasher& __hf, const allocator_type& __a)
1009 : _Base(from_range, std::forward<_Rg>(__rg), __n, __hf, __a)
1013 ~unordered_multiset() = default;
1016 operator=(const unordered_multiset&) = default;
1019 operator=(unordered_multiset&&) = default;
1022 operator=(initializer_list<value_type> __l)
1024 _Base::operator=(__l);
1025 this->_M_invalidate_all();
1029 using _Base::get_allocator;
1032 using _Base::max_size;
1035 swap(unordered_multiset& __x)
1036 noexcept( noexcept(declval<_Base&>().swap(__x)) )
1038 _Safe::_M_swap(__x);
1046 this->_M_invalidate_all();
1051 { return { _Base::begin(), this }; }
1054 begin() const noexcept
1055 { return { _Base::begin(), this }; }
1059 { return { _Base::end(), this }; }
1062 end() const noexcept
1063 { return { _Base::end(), this }; }
1066 cbegin() const noexcept
1067 { return { _Base::cbegin(), this }; }
1070 cend() const noexcept
1071 { return { _Base::cend(), this }; }
1075 begin(size_type __b)
1077 __glibcxx_check_bucket_index(__b);
1078 return { _Base::begin(__b), this };
1084 __glibcxx_check_bucket_index(__b);
1085 return { _Base::end(__b), this };
1088 const_local_iterator
1089 begin(size_type __b) const
1091 __glibcxx_check_bucket_index(__b);
1092 return { _Base::begin(__b), this };
1095 const_local_iterator
1096 end(size_type __b) const
1098 __glibcxx_check_bucket_index(__b);
1099 return { _Base::end(__b), this };
1102 const_local_iterator
1103 cbegin(size_type __b) const
1105 __glibcxx_check_bucket_index(__b);
1106 return { _Base::cbegin(__b), this };
1109 const_local_iterator
1110 cend(size_type __b) const
1112 __glibcxx_check_bucket_index(__b);
1113 return { _Base::cend(__b), this };
1116 using _Base::bucket_count;
1117 using _Base::max_bucket_count;
1120 bucket_size(size_type __b) const
1122 __glibcxx_check_bucket_index(__b);
1123 return _Base::bucket_size(__b);
1126 using _Base::bucket;
1127 using _Base::load_factor;
1130 max_load_factor() const noexcept
1131 { return _Base::max_load_factor(); }
1134 max_load_factor(float __f)
1136 __glibcxx_check_max_load_factor(__f);
1137 _Base::max_load_factor(__f);
1140 using _Base::rehash;
1141 using _Base::reserve;
1143 template<typename... _Args>
1145 emplace(_Args&&... __args)
1147 size_type __bucket_count = this->bucket_count();
1148 auto __it = _Base::emplace(std::forward<_Args>(__args)...);
1149 _M_check_rehashed(__bucket_count);
1150 return { __it, this };
1153 template<typename... _Args>
1155 emplace_hint(const_iterator __hint, _Args&&... __args)
1157 __glibcxx_check_insert(__hint);
1158 size_type __bucket_count = this->bucket_count();
1159 auto __it = _Base::emplace_hint(__hint.base(),
1160 std::forward<_Args>(__args)...);
1161 _M_check_rehashed(__bucket_count);
1162 return { __it, this };
1166 insert(const value_type& __obj)
1168 size_type __bucket_count = this->bucket_count();
1169 auto __it = _Base::insert(__obj);
1170 _M_check_rehashed(__bucket_count);
1171 return { __it, this };
1175 insert(const_iterator __hint, const value_type& __obj)
1177 __glibcxx_check_insert(__hint);
1178 size_type __bucket_count = this->bucket_count();
1179 auto __it = _Base::insert(__hint.base(), __obj);
1180 _M_check_rehashed(__bucket_count);
1181 return { __it, this };
1185 insert(value_type&& __obj)
1187 size_type __bucket_count = this->bucket_count();
1188 auto __it = _Base::insert(std::move(__obj));
1189 _M_check_rehashed(__bucket_count);
1190 return { __it, this };
1194 insert(const_iterator __hint, value_type&& __obj)
1196 __glibcxx_check_insert(__hint);
1197 size_type __bucket_count = this->bucket_count();
1198 auto __it = _Base::insert(__hint.base(), std::move(__obj));
1199 _M_check_rehashed(__bucket_count);
1200 return { __it, this };
1204 insert(std::initializer_list<value_type> __l)
1206 size_type __bucket_count = this->bucket_count();
1208 _M_check_rehashed(__bucket_count);
1211 template<typename _InputIterator>
1213 insert(_InputIterator __first, _InputIterator __last)
1215 typename __gnu_debug::_Distance_traits<_InputIterator>::__type __dist;
1216 __glibcxx_check_valid_range2(__first, __last, __dist);
1217 size_type __bucket_count = this->bucket_count();
1219 if (__dist.second >= __gnu_debug::__dp_sign)
1220 _Base::insert(__gnu_debug::__unsafe(__first),
1221 __gnu_debug::__unsafe(__last));
1223 _Base::insert(__first, __last);
1225 _M_check_rehashed(__bucket_count);
1228 #ifdef __glibcxx_node_extract // >= C++17 && HOSTED
1229 using node_type = typename _Base::node_type;
1232 extract(const_iterator __position)
1234 __glibcxx_check_erase(__position);
1235 return _M_extract(__position.base());
1239 extract(const key_type& __key)
1241 const auto __position = _Base::find(__key);
1242 if (__position != _Base::end())
1243 return _M_extract(__position);
1247 # ifdef __glibcxx_associative_heterogeneous_erasure
1248 template <__heterogeneous_hash_key<unordered_multiset> _Kt>
1250 extract(const _Kt& __key)
1252 const auto __position = _Base::find(__key);
1253 return __position != _Base::end() ?
1254 _M_extract(__position) : node_type{};
1259 insert(node_type&& __nh)
1260 { return { _Base::insert(std::move(__nh)), this }; }
1263 insert(const_iterator __hint, node_type&& __nh)
1265 __glibcxx_check_insert(__hint);
1266 return { _Base::insert(__hint.base(), std::move(__nh)), this };
1269 template<typename _H2, typename _P2>
1271 merge(unordered_multiset<_Value, _H2, _P2, _Alloc>& __source)
1274 = _Safe::_S_umc_guard(std::__detail::_Identity{}, __source);
1275 _Base::merge(__source);
1278 template<typename _H2, typename _P2>
1280 merge(unordered_multiset<_Value, _H2, _P2, _Alloc>&& __source)
1281 { merge(__source); }
1283 template<typename _H2, typename _P2>
1285 merge(unordered_set<_Value, _H2, _P2, _Alloc>& __source)
1288 = _Safe::_S_uc_guard(std::__detail::_Identity{}, __source);
1289 _Base::merge(__source);
1292 template<typename _H2, typename _P2>
1294 merge(unordered_set<_Value, _H2, _P2, _Alloc>&& __source)
1295 { merge(__source); }
1298 using _Base::hash_function;
1299 using _Base::key_eq;
1302 find(const key_type& __key)
1303 { return { _Base::find(__key), this }; }
1305 #ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
1306 template<typename _Kt,
1307 typename = std::__has_is_transparent_t<_Hash, _Kt>,
1308 typename = std::__has_is_transparent_t<_Pred, _Kt>>
1310 find(const _Kt& __k)
1311 { return { _Base::find(__k), this }; }
1315 find(const key_type& __key) const
1316 { return { _Base::find(__key), this }; }
1318 #ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
1319 template<typename _Kt,
1320 typename = std::__has_is_transparent_t<_Hash, _Kt>,
1321 typename = std::__has_is_transparent_t<_Pred, _Kt>>
1323 find(const _Kt& __k) const
1324 { return { _Base::find(__k), this }; }
1329 #if __cplusplus > 201703L
1330 using _Base::contains;
1333 std::pair<iterator, iterator>
1334 equal_range(const key_type& __key)
1336 auto __res = _Base::equal_range(__key);
1337 return { { __res.first, this }, { __res.second, this } };
1340 #ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
1341 template<typename _Kt,
1342 typename = std::__has_is_transparent_t<_Hash, _Kt>,
1343 typename = std::__has_is_transparent_t<_Pred, _Kt>>
1344 std::pair<iterator, iterator>
1345 equal_range(const _Kt& __k)
1347 auto __res = _Base::equal_range(__k);
1348 return { { __res.first, this }, { __res.second, this } };
1352 std::pair<const_iterator, const_iterator>
1353 equal_range(const key_type& __key) const
1355 auto __res = _Base::equal_range(__key);
1356 return { { __res.first, this }, { __res.second, this } };
1359 #ifdef __glibcxx_generic_unordered_lookup // C++ >= 20 && HOSTED
1360 template<typename _Kt,
1361 typename = std::__has_is_transparent_t<_Hash, _Kt>,
1362 typename = std::__has_is_transparent_t<_Pred, _Kt>>
1363 std::pair<const_iterator, const_iterator>
1364 equal_range(const _Kt& __k) const
1366 auto __res = _Base::equal_range(__k);
1367 return { { __res.first, this }, { __res.second, this } };
1372 erase(const key_type& __key)
1374 auto __victims = _Base::equal_range(__key);
1375 return _M_erase(__victims.first, __victims.second);
1378 # ifdef __glibcxx_associative_heterogeneous_erasure
1379 template <__heterogeneous_hash_key<unordered_multiset> _Kt>
1383 auto __victims = _Base::equal_range(__key);
1384 return _M_erase(__victims.first, __victims.second);
1389 erase(const_iterator __it)
1391 __glibcxx_check_erase(__it);
1392 return { _M_erase(__it.base()), this };
1396 erase(_Base_const_iterator __it)
1398 __glibcxx_check_erase2(__it);
1399 return _M_erase(__it);
1403 erase(iterator __it)
1405 __glibcxx_check_erase(__it);
1406 return { _M_erase(__it.base()), this };
1410 erase(const_iterator __first, const_iterator __last)
1412 __glibcxx_check_erase_range(__first, __last);
1414 __gnu_cxx::__scoped_lock sentry(_M_self()->_M_get_mutex());
1415 for (auto __tmp = __first.base(); __tmp != __last.base(); ++__tmp)
1417 _GLIBCXX_DEBUG_VERIFY(__tmp != _Base::cend(),
1418 _M_message(__gnu_debug::__msg_valid_range)
1419 ._M_iterator(__first, "first")
1420 ._M_iterator(__last, "last"));
1421 this->_M_invalidate(__tmp, sentry);
1425 return { _Base::erase(__first.base(), __last.base()), this };
1429 _M_base() noexcept { return *this; }
1432 _M_base() const noexcept { return *this; }
1435 const unordered_multiset*
1436 _M_self() const noexcept
1440 _M_check_rehashed(size_type __prev_count)
1442 if (__prev_count != this->bucket_count())
1443 this->_M_invalidate_all();
1447 _M_erase(_Base_const_iterator __victim)
1449 this->_M_invalidate(__victim);
1450 return _Base::erase(__victim);
1454 _M_erase(_Base_iterator __first, _Base_iterator __last)
1456 size_type __count(0);
1458 __gnu_cxx::__scoped_lock sentry(_M_self()->_M_get_mutex());
1459 for (auto __victim = __first; __victim != __last; ++__victim)
1461 this->_M_invalidate(__victim, sentry);
1466 _Base::erase(__first, __last);
1470 #ifdef __glibcxx_node_extract // >= C++17 && HOSTED
1472 _M_extract(_Base_const_iterator __victim)
1474 this->_M_invalidate(__victim);
1475 return _Base::extract(__victim);
1480 #if __cpp_deduction_guides >= 201606
1482 template<typename _InputIterator,
1484 hash<typename iterator_traits<_InputIterator>::value_type>,
1486 equal_to<typename iterator_traits<_InputIterator>::value_type>,
1487 typename _Allocator =
1488 allocator<typename iterator_traits<_InputIterator>::value_type>,
1489 typename = _RequireInputIter<_InputIterator>,
1490 typename = _RequireNotAllocatorOrIntegral<_Hash>,
1491 typename = _RequireNotAllocator<_Pred>,
1492 typename = _RequireAllocator<_Allocator>>
1493 unordered_multiset(_InputIterator, _InputIterator,
1494 unordered_multiset<int>::size_type = {},
1495 _Hash = _Hash(), _Pred = _Pred(),
1496 _Allocator = _Allocator())
1497 -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type,
1498 _Hash, _Pred, _Allocator>;
1500 template<typename _Tp, typename _Hash = hash<_Tp>,
1501 typename _Pred = equal_to<_Tp>,
1502 typename _Allocator = allocator<_Tp>,
1503 typename = _RequireNotAllocatorOrIntegral<_Hash>,
1504 typename = _RequireNotAllocator<_Pred>,
1505 typename = _RequireAllocator<_Allocator>>
1506 unordered_multiset(initializer_list<_Tp>,
1507 unordered_multiset<int>::size_type = {},
1508 _Hash = _Hash(), _Pred = _Pred(),
1509 _Allocator = _Allocator())
1510 -> unordered_multiset<_Tp, _Hash, _Pred, _Allocator>;
1512 template<typename _InputIterator, typename _Allocator,
1513 typename = _RequireInputIter<_InputIterator>,
1514 typename = _RequireAllocator<_Allocator>>
1515 unordered_multiset(_InputIterator, _InputIterator,
1516 unordered_multiset<int>::size_type, _Allocator)
1517 -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type,
1519 iterator_traits<_InputIterator>::value_type>,
1521 iterator_traits<_InputIterator>::value_type>,
1524 template<typename _InputIterator, typename _Allocator,
1525 typename = _RequireInputIter<_InputIterator>,
1526 typename = _RequireAllocator<_Allocator>>
1527 unordered_multiset(_InputIterator, _InputIterator, _Allocator)
1528 -> unordered_multiset<typename iterator_traits<_InputIterator>::value_type,
1530 iterator_traits<_InputIterator>::value_type>,
1532 iterator_traits<_InputIterator>::value_type>,
1535 template<typename _InputIterator, typename _Hash, typename _Allocator,
1536 typename = _RequireInputIter<_InputIterator>,
1537 typename = _RequireNotAllocatorOrIntegral<_Hash>,
1538 typename = _RequireAllocator<_Allocator>>
1539 unordered_multiset(_InputIterator, _InputIterator,
1540 unordered_multiset<int>::size_type,
1542 -> unordered_multiset<typename
1543 iterator_traits<_InputIterator>::value_type,
1547 iterator_traits<_InputIterator>::value_type>,
1550 template<typename _Tp, typename _Allocator,
1551 typename = _RequireAllocator<_Allocator>>
1552 unordered_multiset(initializer_list<_Tp>,
1553 unordered_multiset<int>::size_type, _Allocator)
1554 -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
1556 template<typename _Tp, typename _Allocator,
1557 typename = _RequireAllocator<_Allocator>>
1558 unordered_multiset(initializer_list<_Tp>, _Allocator)
1559 -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>;
1561 template<typename _Tp, typename _Hash, typename _Allocator,
1562 typename = _RequireNotAllocatorOrIntegral<_Hash>,
1563 typename = _RequireAllocator<_Allocator>>
1564 unordered_multiset(initializer_list<_Tp>,
1565 unordered_multiset<int>::size_type, _Hash, _Allocator)
1566 -> unordered_multiset<_Tp, _Hash, equal_to<_Tp>, _Allocator>;
1568 #if __glibcxx_containers_ranges // C++ >= 23
1569 template<ranges::input_range _Rg,
1570 __not_allocator_like _Hash = hash<ranges::range_value_t<_Rg>>,
1571 __not_allocator_like _Pred = equal_to<ranges::range_value_t<_Rg>>,
1572 __allocator_like _Allocator = allocator<ranges::range_value_t<_Rg>>>
1573 unordered_set(from_range_t, _Rg&&, unordered_set<int>::size_type = {},
1574 _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator())
1575 -> unordered_set<ranges::range_value_t<_Rg>, _Hash, _Pred, _Allocator>;
1577 template<ranges::input_range _Rg,
1578 __allocator_like _Allocator>
1579 unordered_set(from_range_t, _Rg&&, unordered_set<int>::size_type,
1581 -> unordered_set<ranges::range_value_t<_Rg>,
1582 hash<ranges::range_value_t<_Rg>>,
1583 equal_to<ranges::range_value_t<_Rg>>,
1586 template<ranges::input_range _Rg,
1587 __allocator_like _Allocator>
1588 unordered_set(from_range_t, _Rg&&, _Allocator)
1589 -> unordered_set<ranges::range_value_t<_Rg>,
1590 hash<ranges::range_value_t<_Rg>>,
1591 equal_to<ranges::range_value_t<_Rg>>,
1594 template<ranges::input_range _Rg,
1595 __not_allocator_like _Hash,
1596 __allocator_like _Allocator>
1597 unordered_set(from_range_t, _Rg&&, unordered_set<int>::size_type,
1599 -> unordered_set<ranges::range_value_t<_Rg>, _Hash,
1600 equal_to<ranges::range_value_t<_Rg>>,
1603 #if __glibcxx_containers_ranges // C++ >= 23
1604 template<ranges::input_range _Rg,
1605 __not_allocator_like _Hash = hash<ranges::range_value_t<_Rg>>,
1606 __not_allocator_like _Pred = equal_to<ranges::range_value_t<_Rg>>,
1607 __allocator_like _Allocator = allocator<ranges::range_value_t<_Rg>>>
1608 unordered_multiset(from_range_t, _Rg&&,
1609 unordered_multiset<int>::size_type = {},
1610 _Hash = _Hash(), _Pred = _Pred(),
1611 _Allocator = _Allocator())
1612 -> unordered_multiset<ranges::range_value_t<_Rg>, _Hash, _Pred, _Allocator>;
1614 template<ranges::input_range _Rg,
1615 __allocator_like _Allocator>
1616 unordered_multiset(from_range_t, _Rg&&, _Allocator)
1617 -> unordered_multiset<ranges::range_value_t<_Rg>,
1618 hash<ranges::range_value_t<_Rg>>,
1619 equal_to<ranges::range_value_t<_Rg>>,
1622 template<ranges::input_range _Rg,
1623 __allocator_like _Allocator>
1624 unordered_multiset(from_range_t, _Rg&&, unordered_multiset<int>::size_type,
1626 -> unordered_multiset<ranges::range_value_t<_Rg>,
1627 hash<ranges::range_value_t<_Rg>>,
1628 equal_to<ranges::range_value_t<_Rg>>,
1631 template<ranges::input_range _Rg,
1632 __not_allocator_like _Hash,
1633 __allocator_like _Allocator>
1634 unordered_multiset(from_range_t, _Rg&&,
1635 unordered_multiset<int>::size_type,
1637 -> unordered_multiset<ranges::range_value_t<_Rg>, _Hash,
1638 equal_to<ranges::range_value_t<_Rg>>,
1645 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
1647 swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
1648 unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
1649 noexcept(noexcept(__x.swap(__y)))
1652 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
1654 operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
1655 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
1656 { return __x._M_base() == __y._M_base(); }
1658 #if __cpp_impl_three_way_comparison < 201907L
1659 template<typename _Value, typename _Hash, typename _Pred, typename _Alloc>
1661 operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x,
1662 const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y)
1663 { return !(__x == __y); }
1666 } // namespace __debug
1668 #ifdef __glibcxx_erase_if // C++ >= 20 && HOSTED
1669 _GLIBCXX_BEGIN_NAMESPACE_VERSION
1670 template<typename _Key, typename _Hash, typename _CPred, typename _Alloc,
1671 typename _Predicate>
1672 inline typename __debug::unordered_set<_Key, _Hash,
1673 _CPred, _Alloc>::size_type
1674 erase_if(__debug::unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont,
1676 { return __detail::__erase_nodes_if(__cont, __cont._M_base(), __pred); }
1678 template<typename _Key, typename _Hash, typename _CPred, typename _Alloc,
1679 typename _Predicate>
1680 inline typename __debug::unordered_multiset<_Key, _Hash,
1681 _CPred, _Alloc>::size_type
1682 erase_if(__debug::unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont,
1684 { return __detail::__erase_nodes_if(__cont, __cont._M_base(), __pred); }
1685 _GLIBCXX_END_NAMESPACE_VERSION
1686 #endif // __glibcxx_erase_if