xref: /freebsd/contrib/llvm-project/libcxx/include/__flat_set/flat_multiset.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric // -*- C++ -*-
2*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
3*700637cbSDimitry Andric //
4*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
6*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*700637cbSDimitry Andric //
8*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
9*700637cbSDimitry Andric 
10*700637cbSDimitry Andric #ifndef _LIBCPP___FLAT_MAP_FLAT_MULTISET_H
11*700637cbSDimitry Andric #define _LIBCPP___FLAT_MAP_FLAT_MULTISET_H
12*700637cbSDimitry Andric 
13*700637cbSDimitry Andric #include <__algorithm/equal_range.h>
14*700637cbSDimitry Andric #include <__algorithm/lexicographical_compare_three_way.h>
15*700637cbSDimitry Andric #include <__algorithm/lower_bound.h>
16*700637cbSDimitry Andric #include <__algorithm/min.h>
17*700637cbSDimitry Andric #include <__algorithm/ranges_equal.h>
18*700637cbSDimitry Andric #include <__algorithm/ranges_inplace_merge.h>
19*700637cbSDimitry Andric #include <__algorithm/ranges_is_sorted.h>
20*700637cbSDimitry Andric #include <__algorithm/ranges_sort.h>
21*700637cbSDimitry Andric #include <__algorithm/ranges_unique.h>
22*700637cbSDimitry Andric #include <__algorithm/remove_if.h>
23*700637cbSDimitry Andric #include <__algorithm/upper_bound.h>
24*700637cbSDimitry Andric #include <__assert>
25*700637cbSDimitry Andric #include <__compare/synth_three_way.h>
26*700637cbSDimitry Andric #include <__concepts/convertible_to.h>
27*700637cbSDimitry Andric #include <__concepts/swappable.h>
28*700637cbSDimitry Andric #include <__config>
29*700637cbSDimitry Andric #include <__cstddef/byte.h>
30*700637cbSDimitry Andric #include <__cstddef/ptrdiff_t.h>
31*700637cbSDimitry Andric #include <__flat_map/key_value_iterator.h>
32*700637cbSDimitry Andric #include <__flat_map/sorted_equivalent.h>
33*700637cbSDimitry Andric #include <__flat_set/ra_iterator.h>
34*700637cbSDimitry Andric #include <__flat_set/utils.h>
35*700637cbSDimitry Andric #include <__functional/invoke.h>
36*700637cbSDimitry Andric #include <__functional/is_transparent.h>
37*700637cbSDimitry Andric #include <__functional/operations.h>
38*700637cbSDimitry Andric #include <__fwd/vector.h>
39*700637cbSDimitry Andric #include <__iterator/concepts.h>
40*700637cbSDimitry Andric #include <__iterator/distance.h>
41*700637cbSDimitry Andric #include <__iterator/iterator_traits.h>
42*700637cbSDimitry Andric #include <__iterator/prev.h>
43*700637cbSDimitry Andric #include <__iterator/ranges_iterator_traits.h>
44*700637cbSDimitry Andric #include <__iterator/reverse_iterator.h>
45*700637cbSDimitry Andric #include <__memory/allocator_traits.h>
46*700637cbSDimitry Andric #include <__memory/uses_allocator.h>
47*700637cbSDimitry Andric #include <__memory/uses_allocator_construction.h>
48*700637cbSDimitry Andric #include <__ranges/access.h>
49*700637cbSDimitry Andric #include <__ranges/concepts.h>
50*700637cbSDimitry Andric #include <__ranges/container_compatible_range.h>
51*700637cbSDimitry Andric #include <__ranges/drop_view.h>
52*700637cbSDimitry Andric #include <__ranges/from_range.h>
53*700637cbSDimitry Andric #include <__ranges/ref_view.h>
54*700637cbSDimitry Andric #include <__ranges/size.h>
55*700637cbSDimitry Andric #include <__ranges/subrange.h>
56*700637cbSDimitry Andric #include <__ranges/zip_view.h>
57*700637cbSDimitry Andric #include <__type_traits/conjunction.h>
58*700637cbSDimitry Andric #include <__type_traits/container_traits.h>
59*700637cbSDimitry Andric #include <__type_traits/invoke.h>
60*700637cbSDimitry Andric #include <__type_traits/is_allocator.h>
61*700637cbSDimitry Andric #include <__type_traits/is_nothrow_constructible.h>
62*700637cbSDimitry Andric #include <__type_traits/is_same.h>
63*700637cbSDimitry Andric #include <__type_traits/maybe_const.h>
64*700637cbSDimitry Andric #include <__utility/as_const.h>
65*700637cbSDimitry Andric #include <__utility/exception_guard.h>
66*700637cbSDimitry Andric #include <__utility/move.h>
67*700637cbSDimitry Andric #include <__utility/pair.h>
68*700637cbSDimitry Andric #include <__utility/scope_guard.h>
69*700637cbSDimitry Andric #include <__vector/vector.h>
70*700637cbSDimitry Andric #include <initializer_list>
71*700637cbSDimitry Andric 
72*700637cbSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
73*700637cbSDimitry Andric #  pragma GCC system_header
74*700637cbSDimitry Andric #endif
75*700637cbSDimitry Andric 
76*700637cbSDimitry Andric _LIBCPP_PUSH_MACROS
77*700637cbSDimitry Andric #include <__undef_macros>
78*700637cbSDimitry Andric 
79*700637cbSDimitry Andric #if _LIBCPP_STD_VER >= 23
80*700637cbSDimitry Andric 
81*700637cbSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
82*700637cbSDimitry Andric 
83*700637cbSDimitry Andric template <class _Key, class _Compare = less<_Key>, class _KeyContainer = vector<_Key>>
84*700637cbSDimitry Andric class flat_multiset {
85*700637cbSDimitry Andric   template <class, class, class>
86*700637cbSDimitry Andric   friend class flat_multiset;
87*700637cbSDimitry Andric 
88*700637cbSDimitry Andric   friend __flat_set_utils;
89*700637cbSDimitry Andric 
90*700637cbSDimitry Andric   static_assert(is_same_v<_Key, typename _KeyContainer::value_type>);
91*700637cbSDimitry Andric   static_assert(!is_same_v<_KeyContainer, std::vector<bool>>, "vector<bool> is not a sequence container");
92*700637cbSDimitry Andric 
93*700637cbSDimitry Andric public:
94*700637cbSDimitry Andric   // types
95*700637cbSDimitry Andric   using key_type               = _Key;
96*700637cbSDimitry Andric   using value_type             = _Key;
97*700637cbSDimitry Andric   using key_compare            = __type_identity_t<_Compare>;
98*700637cbSDimitry Andric   using value_compare          = _Compare;
99*700637cbSDimitry Andric   using reference              = value_type&;
100*700637cbSDimitry Andric   using const_reference        = const value_type&;
101*700637cbSDimitry Andric   using size_type              = typename _KeyContainer::size_type;
102*700637cbSDimitry Andric   using difference_type        = typename _KeyContainer::difference_type;
103*700637cbSDimitry Andric   using iterator               = __ra_iterator<flat_multiset, typename _KeyContainer::const_iterator>;
104*700637cbSDimitry Andric   using const_iterator         = iterator;
105*700637cbSDimitry Andric   using reverse_iterator       = std::reverse_iterator<iterator>;
106*700637cbSDimitry Andric   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
107*700637cbSDimitry Andric   using container_type         = _KeyContainer;
108*700637cbSDimitry Andric 
109*700637cbSDimitry Andric public:
110*700637cbSDimitry Andric   // [flat.multiset.cons], constructors
flat_multiset()111*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset() noexcept(is_nothrow_default_constructible_v<_KeyContainer> &&
112*700637cbSDimitry Andric                                                  is_nothrow_default_constructible_v<_Compare>)
113*700637cbSDimitry Andric       : __keys_(), __compare_() {}
114*700637cbSDimitry Andric 
115*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(const flat_multiset&) = default;
116*700637cbSDimitry Andric 
117*700637cbSDimitry Andric   // The copy/move constructors are not specified in the spec, which means they should be defaulted.
118*700637cbSDimitry Andric   // However, the move constructor can potentially leave a moved-from object in an inconsistent
119*700637cbSDimitry Andric   // state if an exception is thrown.
flat_multiset(flat_multiset && __other)120*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(flat_multiset&& __other) noexcept(
121*700637cbSDimitry Andric       is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_Compare>)
122*700637cbSDimitry Andric #  if _LIBCPP_HAS_EXCEPTIONS
123*700637cbSDimitry Andric       try
124*700637cbSDimitry Andric #  endif // _LIBCPP_HAS_EXCEPTIONS
125*700637cbSDimitry Andric       : __keys_(std::move(__other.__keys_)), __compare_(std::move(__other.__compare_)) {
126*700637cbSDimitry Andric     __other.clear();
127*700637cbSDimitry Andric #  if _LIBCPP_HAS_EXCEPTIONS
128*700637cbSDimitry Andric   } catch (...) {
129*700637cbSDimitry Andric     __other.clear();
130*700637cbSDimitry Andric     // gcc does not like the `throw` keyword in a conditionally noexcept function
131*700637cbSDimitry Andric     if constexpr (!(is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_Compare>)) {
132*700637cbSDimitry Andric       throw;
133*700637cbSDimitry Andric     }
134*700637cbSDimitry Andric #  endif // _LIBCPP_HAS_EXCEPTIONS
135*700637cbSDimitry Andric   }
136*700637cbSDimitry Andric 
flat_multiset(const key_compare & __comp)137*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI explicit flat_multiset(const key_compare& __comp) : __keys_(), __compare_(__comp) {}
138*700637cbSDimitry Andric 
139*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI explicit flat_multiset(container_type __keys, const key_compare& __comp = key_compare())
__keys_(std::move (__keys))140*700637cbSDimitry Andric       : __keys_(std::move(__keys)), __compare_(__comp) {
141*700637cbSDimitry Andric     ranges::sort(__keys_, __compare_);
142*700637cbSDimitry Andric   }
143*700637cbSDimitry Andric 
144*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
145*700637cbSDimitry Andric   flat_multiset(sorted_equivalent_t, container_type __keys, const key_compare& __comp = key_compare())
__keys_(std::move (__keys))146*700637cbSDimitry Andric       : __keys_(std::move(__keys)), __compare_(__comp) {
147*700637cbSDimitry Andric     _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");
148*700637cbSDimitry Andric   }
149*700637cbSDimitry Andric 
150*700637cbSDimitry Andric   template <class _InputIterator>
151*700637cbSDimitry Andric     requires __has_input_iterator_category<_InputIterator>::value
152*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
153*700637cbSDimitry Andric   flat_multiset(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare())
__keys_()154*700637cbSDimitry Andric       : __keys_(), __compare_(__comp) {
155*700637cbSDimitry Andric     insert(__first, __last);
156*700637cbSDimitry Andric   }
157*700637cbSDimitry Andric 
158*700637cbSDimitry Andric   template <class _InputIterator>
159*700637cbSDimitry Andric     requires __has_input_iterator_category<_InputIterator>::value
160*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(
161*700637cbSDimitry Andric       sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare())
__keys_(__first,__last)162*700637cbSDimitry Andric       : __keys_(__first, __last), __compare_(__comp) {
163*700637cbSDimitry Andric     _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");
164*700637cbSDimitry Andric   }
165*700637cbSDimitry Andric 
166*700637cbSDimitry Andric   template <_ContainerCompatibleRange<value_type> _Range>
flat_multiset(from_range_t __fr,_Range && __rg)167*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t __fr, _Range&& __rg)
168*700637cbSDimitry Andric       : flat_multiset(__fr, std::forward<_Range>(__rg), key_compare()) {}
169*700637cbSDimitry Andric 
170*700637cbSDimitry Andric   template <_ContainerCompatibleRange<value_type> _Range>
flat_multiset(from_range_t,_Range && __rg,const key_compare & __comp)171*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const key_compare& __comp) : flat_multiset(__comp) {
172*700637cbSDimitry Andric     insert_range(std::forward<_Range>(__rg));
173*700637cbSDimitry Andric   }
174*700637cbSDimitry Andric 
175*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(initializer_list<value_type> __il, const key_compare& __comp = key_compare())
176*700637cbSDimitry Andric       : flat_multiset(__il.begin(), __il.end(), __comp) {}
177*700637cbSDimitry Andric 
178*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
179*700637cbSDimitry Andric   flat_multiset(sorted_equivalent_t, initializer_list<value_type> __il, const key_compare& __comp = key_compare())
180*700637cbSDimitry Andric       : flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __comp) {}
181*700637cbSDimitry Andric 
182*700637cbSDimitry Andric   template <class _Allocator>
183*700637cbSDimitry Andric     requires uses_allocator<container_type, _Allocator>::value
flat_multiset(const _Allocator & __alloc)184*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI explicit flat_multiset(const _Allocator& __alloc)
185*700637cbSDimitry Andric       : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() {}
186*700637cbSDimitry Andric 
187*700637cbSDimitry Andric   template <class _Allocator>
188*700637cbSDimitry Andric     requires uses_allocator<container_type, _Allocator>::value
flat_multiset(const key_compare & __comp,const _Allocator & __alloc)189*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(const key_compare& __comp, const _Allocator& __alloc)
190*700637cbSDimitry Andric       : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) {}
191*700637cbSDimitry Andric 
192*700637cbSDimitry Andric   template <class _Allocator>
193*700637cbSDimitry Andric     requires uses_allocator<container_type, _Allocator>::value
flat_multiset(const container_type & __keys,const _Allocator & __alloc)194*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(const container_type& __keys, const _Allocator& __alloc)
195*700637cbSDimitry Andric       : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_() {
196*700637cbSDimitry Andric     ranges::sort(__keys_, __compare_);
197*700637cbSDimitry Andric   }
198*700637cbSDimitry Andric 
199*700637cbSDimitry Andric   template <class _Allocator>
200*700637cbSDimitry Andric     requires uses_allocator<container_type, _Allocator>::value
201*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
flat_multiset(const container_type & __keys,const key_compare & __comp,const _Allocator & __alloc)202*700637cbSDimitry Andric   flat_multiset(const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc)
203*700637cbSDimitry Andric       : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_(__comp) {
204*700637cbSDimitry Andric     ranges::sort(__keys_, __compare_);
205*700637cbSDimitry Andric   }
206*700637cbSDimitry Andric 
207*700637cbSDimitry Andric   template <class _Allocator>
208*700637cbSDimitry Andric     requires uses_allocator<container_type, _Allocator>::value
flat_multiset(sorted_equivalent_t,const container_type & __keys,const _Allocator & __alloc)209*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(sorted_equivalent_t, const container_type& __keys, const _Allocator& __alloc)
210*700637cbSDimitry Andric       : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_() {
211*700637cbSDimitry Andric     _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");
212*700637cbSDimitry Andric   }
213*700637cbSDimitry Andric 
214*700637cbSDimitry Andric   template <class _Allocator>
215*700637cbSDimitry Andric     requires uses_allocator<container_type, _Allocator>::value
216*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
flat_multiset(sorted_equivalent_t,const container_type & __keys,const key_compare & __comp,const _Allocator & __alloc)217*700637cbSDimitry Andric   flat_multiset(sorted_equivalent_t, const container_type& __keys, const key_compare& __comp, const _Allocator& __alloc)
218*700637cbSDimitry Andric       : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __keys)), __compare_(__comp) {
219*700637cbSDimitry Andric     _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");
220*700637cbSDimitry Andric   }
221*700637cbSDimitry Andric 
222*700637cbSDimitry Andric   template <class _Allocator>
223*700637cbSDimitry Andric     requires uses_allocator<container_type, _Allocator>::value
flat_multiset(const flat_multiset & __other,const _Allocator & __alloc)224*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(const flat_multiset& __other, const _Allocator& __alloc)
225*700637cbSDimitry Andric       : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __other.__keys_)),
226*700637cbSDimitry Andric         __compare_(__other.__compare_) {}
227*700637cbSDimitry Andric 
228*700637cbSDimitry Andric   template <class _Allocator>
229*700637cbSDimitry Andric     requires uses_allocator<container_type, _Allocator>::value
flat_multiset(flat_multiset && __other,const _Allocator & __alloc)230*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(flat_multiset&& __other, const _Allocator& __alloc)
231*700637cbSDimitry Andric #  if _LIBCPP_HAS_EXCEPTIONS
232*700637cbSDimitry Andric       try
233*700637cbSDimitry Andric #  endif // _LIBCPP_HAS_EXCEPTIONS
234*700637cbSDimitry Andric       : __keys_(std::make_obj_using_allocator<container_type>(__alloc, std::move(__other.__keys_))),
235*700637cbSDimitry Andric         __compare_(std::move(__other.__compare_)) {
236*700637cbSDimitry Andric     __other.clear();
237*700637cbSDimitry Andric #  if _LIBCPP_HAS_EXCEPTIONS
238*700637cbSDimitry Andric   } catch (...) {
239*700637cbSDimitry Andric     __other.clear();
240*700637cbSDimitry Andric     throw;
241*700637cbSDimitry Andric #  endif // _LIBCPP_HAS_EXCEPTIONS
242*700637cbSDimitry Andric   }
243*700637cbSDimitry Andric 
244*700637cbSDimitry Andric   template <class _InputIterator, class _Allocator>
requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type,_Allocator>::value)245*700637cbSDimitry Andric     requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value)
246*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc)
247*700637cbSDimitry Andric       : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() {
248*700637cbSDimitry Andric     insert(__first, __last);
249*700637cbSDimitry Andric   }
250*700637cbSDimitry Andric 
251*700637cbSDimitry Andric   template <class _InputIterator, class _Allocator>
requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type,_Allocator>::value)252*700637cbSDimitry Andric     requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value)
253*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
254*700637cbSDimitry Andric   flat_multiset(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc)
255*700637cbSDimitry Andric       : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) {
256*700637cbSDimitry Andric     insert(__first, __last);
257*700637cbSDimitry Andric   }
258*700637cbSDimitry Andric 
259*700637cbSDimitry Andric   template <class _InputIterator, class _Allocator>
requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type,_Allocator>::value)260*700637cbSDimitry Andric     requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value)
261*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
262*700637cbSDimitry Andric   flat_multiset(sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const _Allocator& __alloc)
263*700637cbSDimitry Andric       : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __first, __last)), __compare_() {
264*700637cbSDimitry Andric     _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");
265*700637cbSDimitry Andric   }
266*700637cbSDimitry Andric 
267*700637cbSDimitry Andric   template <class _InputIterator, class _Allocator>
requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type,_Allocator>::value)268*700637cbSDimitry Andric     requires(__has_input_iterator_category<_InputIterator>::value && uses_allocator<container_type, _Allocator>::value)
269*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
270*700637cbSDimitry Andric   flat_multiset(sorted_equivalent_t,
271*700637cbSDimitry Andric                 _InputIterator __first,
272*700637cbSDimitry Andric                 _InputIterator __last,
273*700637cbSDimitry Andric                 const key_compare& __comp,
274*700637cbSDimitry Andric                 const _Allocator& __alloc)
275*700637cbSDimitry Andric       : __keys_(std::make_obj_using_allocator<container_type>(__alloc, __first, __last)), __compare_(__comp) {
276*700637cbSDimitry Andric     _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys_, __compare_), "Key container is not sorted");
277*700637cbSDimitry Andric   }
278*700637cbSDimitry Andric 
279*700637cbSDimitry Andric   template <_ContainerCompatibleRange<value_type> _Range, class _Allocator>
280*700637cbSDimitry Andric     requires uses_allocator<container_type, _Allocator>::value
flat_multiset(from_range_t,_Range && __rg,const _Allocator & __alloc)281*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const _Allocator& __alloc)
282*700637cbSDimitry Andric       : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_() {
283*700637cbSDimitry Andric     insert_range(std::forward<_Range>(__rg));
284*700637cbSDimitry Andric   }
285*700637cbSDimitry Andric 
286*700637cbSDimitry Andric   template <_ContainerCompatibleRange<value_type> _Range, class _Allocator>
287*700637cbSDimitry Andric     requires uses_allocator<container_type, _Allocator>::value
flat_multiset(from_range_t,_Range && __rg,const key_compare & __comp,const _Allocator & __alloc)288*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc)
289*700637cbSDimitry Andric       : __keys_(std::make_obj_using_allocator<container_type>(__alloc)), __compare_(__comp) {
290*700637cbSDimitry Andric     insert_range(std::forward<_Range>(__rg));
291*700637cbSDimitry Andric   }
292*700637cbSDimitry Andric 
293*700637cbSDimitry Andric   template <class _Allocator>
294*700637cbSDimitry Andric     requires uses_allocator<container_type, _Allocator>::value
flat_multiset(initializer_list<value_type> __il,const _Allocator & __alloc)295*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(initializer_list<value_type> __il, const _Allocator& __alloc)
296*700637cbSDimitry Andric       : flat_multiset(__il.begin(), __il.end(), __alloc) {}
297*700637cbSDimitry Andric 
298*700637cbSDimitry Andric   template <class _Allocator>
299*700637cbSDimitry Andric     requires uses_allocator<container_type, _Allocator>::value
300*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
flat_multiset(initializer_list<value_type> __il,const key_compare & __comp,const _Allocator & __alloc)301*700637cbSDimitry Andric   flat_multiset(initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc)
302*700637cbSDimitry Andric       : flat_multiset(__il.begin(), __il.end(), __comp, __alloc) {}
303*700637cbSDimitry Andric 
304*700637cbSDimitry Andric   template <class _Allocator>
305*700637cbSDimitry Andric     requires uses_allocator<container_type, _Allocator>::value
flat_multiset(sorted_equivalent_t,initializer_list<value_type> __il,const _Allocator & __alloc)306*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(sorted_equivalent_t, initializer_list<value_type> __il, const _Allocator& __alloc)
307*700637cbSDimitry Andric       : flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __alloc) {}
308*700637cbSDimitry Andric 
309*700637cbSDimitry Andric   template <class _Allocator>
310*700637cbSDimitry Andric     requires uses_allocator<container_type, _Allocator>::value
flat_multiset(sorted_equivalent_t,initializer_list<value_type> __il,const key_compare & __comp,const _Allocator & __alloc)311*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset(
312*700637cbSDimitry Andric       sorted_equivalent_t, initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc)
313*700637cbSDimitry Andric       : flat_multiset(sorted_equivalent, __il.begin(), __il.end(), __comp, __alloc) {}
314*700637cbSDimitry Andric 
315*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(initializer_list<value_type> __il) {
316*700637cbSDimitry Andric     clear();
317*700637cbSDimitry Andric     insert(__il);
318*700637cbSDimitry Andric     return *this;
319*700637cbSDimitry Andric   }
320*700637cbSDimitry Andric 
321*700637cbSDimitry Andric   // copy/move assignment are not specified in the spec (defaulted)
322*700637cbSDimitry Andric   // but move assignment can potentially leave moved from object in an inconsistent
323*700637cbSDimitry Andric   // state if an exception is thrown
324*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(const flat_multiset&) = default;
325*700637cbSDimitry Andric 
noexcept(is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_Compare>)326*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multiset& operator=(flat_multiset&& __other) noexcept(
327*700637cbSDimitry Andric       is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_Compare>) {
328*700637cbSDimitry Andric     auto __clear_other_guard = std::__make_scope_guard([&]() noexcept { __other.clear() /* noexcept */; });
329*700637cbSDimitry Andric     auto __clear_self_guard  = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
330*700637cbSDimitry Andric     __keys_                  = std::move(__other.__keys_);
331*700637cbSDimitry Andric     __compare_               = std::move(__other.__compare_);
332*700637cbSDimitry Andric     __clear_self_guard.__complete();
333*700637cbSDimitry Andric     return *this;
334*700637cbSDimitry Andric   }
335*700637cbSDimitry Andric 
336*700637cbSDimitry Andric   // iterators
begin()337*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator begin() noexcept { return iterator(std::as_const(__keys_).begin()); }
begin()338*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept { return const_iterator(__keys_.begin()); }
end()339*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator end() noexcept { return iterator(std::as_const(__keys_).end()); }
end()340*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept { return const_iterator(__keys_.end()); }
341*700637cbSDimitry Andric 
rbegin()342*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
rbegin()343*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
rend()344*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
rend()345*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
346*700637cbSDimitry Andric 
cbegin()347*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return begin(); }
cend()348*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return end(); }
crbegin()349*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
crend()350*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
351*700637cbSDimitry Andric 
352*700637cbSDimitry Andric   // capacity
empty()353*700637cbSDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __keys_.empty(); }
size()354*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI size_type size() const noexcept { return __keys_.size(); }
max_size()355*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI size_type max_size() const noexcept { return __keys_.max_size(); }
356*700637cbSDimitry Andric 
357*700637cbSDimitry Andric   // [flat.multiset.modifiers], modifiers
358*700637cbSDimitry Andric   template <class... _Args>
359*700637cbSDimitry Andric     requires is_constructible_v<value_type, _Args...>
emplace(_Args &&...__args)360*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator emplace(_Args&&... __args) {
361*700637cbSDimitry Andric     if constexpr (sizeof...(__args) == 1 && (is_same_v<remove_cvref_t<_Args>, _Key> && ...)) {
362*700637cbSDimitry Andric       return __emplace(std::forward<_Args>(__args)...);
363*700637cbSDimitry Andric     } else {
364*700637cbSDimitry Andric       return __emplace(_Key(std::forward<_Args>(__args)...));
365*700637cbSDimitry Andric     }
366*700637cbSDimitry Andric   }
367*700637cbSDimitry Andric 
368*700637cbSDimitry Andric   template <class... _Args>
369*700637cbSDimitry Andric     requires is_constructible_v<value_type, _Args...>
emplace_hint(const_iterator __hint,_Args &&...__args)370*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __hint, _Args&&... __args) {
371*700637cbSDimitry Andric     if constexpr (sizeof...(__args) == 1 && (is_same_v<remove_cvref_t<_Args>, _Key> && ...)) {
372*700637cbSDimitry Andric       return __emplace_hint(std::move(__hint), std::forward<_Args>(__args)...);
373*700637cbSDimitry Andric     } else {
374*700637cbSDimitry Andric       return __emplace_hint(std::move(__hint), _Key(std::forward<_Args>(__args)...));
375*700637cbSDimitry Andric     }
376*700637cbSDimitry Andric   }
377*700637cbSDimitry Andric 
insert(const value_type & __x)378*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return emplace(__x); }
379*700637cbSDimitry Andric 
insert(value_type && __x)380*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator insert(value_type&& __x) { return emplace(std::move(__x)); }
381*700637cbSDimitry Andric 
insert(const_iterator __hint,const value_type & __x)382*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, const value_type& __x) {
383*700637cbSDimitry Andric     return emplace_hint(__hint, __x);
384*700637cbSDimitry Andric   }
385*700637cbSDimitry Andric 
insert(const_iterator __hint,value_type && __x)386*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, value_type&& __x) {
387*700637cbSDimitry Andric     return emplace_hint(__hint, std::move(__x));
388*700637cbSDimitry Andric   }
389*700637cbSDimitry Andric 
390*700637cbSDimitry Andric   template <class _InputIterator>
391*700637cbSDimitry Andric     requires __has_input_iterator_category<_InputIterator>::value
insert(_InputIterator __first,_InputIterator __last)392*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) {
393*700637cbSDimitry Andric     if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) {
394*700637cbSDimitry Andric       __reserve(__last - __first);
395*700637cbSDimitry Andric     }
396*700637cbSDimitry Andric     __append_sort_merge</*WasSorted = */ false>(std::move(__first), std::move(__last));
397*700637cbSDimitry Andric   }
398*700637cbSDimitry Andric 
399*700637cbSDimitry Andric   template <class _InputIterator>
400*700637cbSDimitry Andric     requires __has_input_iterator_category<_InputIterator>::value
insert(sorted_equivalent_t,_InputIterator __first,_InputIterator __last)401*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, _InputIterator __first, _InputIterator __last) {
402*700637cbSDimitry Andric     if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) {
403*700637cbSDimitry Andric       __reserve(__last - __first);
404*700637cbSDimitry Andric     }
405*700637cbSDimitry Andric 
406*700637cbSDimitry Andric     __append_sort_merge</*WasSorted = */ true>(std::move(__first), std::move(__last));
407*700637cbSDimitry Andric   }
408*700637cbSDimitry Andric 
409*700637cbSDimitry Andric   template <_ContainerCompatibleRange<value_type> _Range>
insert_range(_Range && __range)410*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) {
411*700637cbSDimitry Andric     if constexpr (ranges::sized_range<_Range>) {
412*700637cbSDimitry Andric       __reserve(ranges::size(__range));
413*700637cbSDimitry Andric     }
414*700637cbSDimitry Andric 
415*700637cbSDimitry Andric     __append_sort_merge</*WasSorted = */ false>(std::forward<_Range>(__range));
416*700637cbSDimitry Andric   }
417*700637cbSDimitry Andric 
insert(initializer_list<value_type> __il)418*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void insert(initializer_list<value_type> __il) { insert(__il.begin(), __il.end()); }
419*700637cbSDimitry Andric 
insert(sorted_equivalent_t,initializer_list<value_type> __il)420*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, initializer_list<value_type> __il) {
421*700637cbSDimitry Andric     insert(sorted_equivalent, __il.begin(), __il.end());
422*700637cbSDimitry Andric   }
423*700637cbSDimitry Andric 
extract()424*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI container_type extract() && {
425*700637cbSDimitry Andric     auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; });
426*700637cbSDimitry Andric     auto __ret   = std::move(__keys_);
427*700637cbSDimitry Andric     return __ret;
428*700637cbSDimitry Andric   }
429*700637cbSDimitry Andric 
replace(container_type && __keys)430*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void replace(container_type&& __keys) {
431*700637cbSDimitry Andric     _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(ranges::is_sorted(__keys, __compare_), "Key container is not sorted");
432*700637cbSDimitry Andric     auto __guard = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
433*700637cbSDimitry Andric     __keys_      = std::move(__keys);
434*700637cbSDimitry Andric     __guard.__complete();
435*700637cbSDimitry Andric   }
436*700637cbSDimitry Andric 
erase(iterator __position)437*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator erase(iterator __position) {
438*700637cbSDimitry Andric     auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
439*700637cbSDimitry Andric     auto __key_iter   = __keys_.erase(__position.__base());
440*700637cbSDimitry Andric     __on_failure.__complete();
441*700637cbSDimitry Andric     return iterator(__key_iter);
442*700637cbSDimitry Andric   }
443*700637cbSDimitry Andric 
444*700637cbSDimitry Andric   // The following overload is the same as the iterator overload
445*700637cbSDimitry Andric   // iterator erase(const_iterator __position);
446*700637cbSDimitry Andric 
erase(const key_type & __x)447*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __x) {
448*700637cbSDimitry Andric     auto [__first, __last] = equal_range(__x);
449*700637cbSDimitry Andric     auto __res             = __last - __first;
450*700637cbSDimitry Andric     erase(__first, __last);
451*700637cbSDimitry Andric     return __res;
452*700637cbSDimitry Andric   }
453*700637cbSDimitry Andric 
454*700637cbSDimitry Andric   template <class _Kp>
455*700637cbSDimitry Andric     requires(__is_transparent_v<_Compare> && !is_convertible_v<_Kp &&, iterator> &&
456*700637cbSDimitry Andric              !is_convertible_v<_Kp &&, const_iterator>)
erase(_Kp && __x)457*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI size_type erase(_Kp&& __x) {
458*700637cbSDimitry Andric     auto [__first, __last] = equal_range(__x);
459*700637cbSDimitry Andric     auto __res             = __last - __first;
460*700637cbSDimitry Andric     erase(__first, __last);
461*700637cbSDimitry Andric     return __res;
462*700637cbSDimitry Andric   }
463*700637cbSDimitry Andric 
erase(const_iterator __first,const_iterator __last)464*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) {
465*700637cbSDimitry Andric     auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
466*700637cbSDimitry Andric     auto __key_it     = __keys_.erase(__first.__base(), __last.__base());
467*700637cbSDimitry Andric     __on_failure.__complete();
468*700637cbSDimitry Andric     return iterator(std::move(__key_it));
469*700637cbSDimitry Andric   }
470*700637cbSDimitry Andric 
swap(flat_multiset & __y)471*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void swap(flat_multiset& __y) noexcept {
472*700637cbSDimitry Andric     // warning: The spec has unconditional noexcept, which means that
473*700637cbSDimitry Andric     // if any of the following functions throw an exception,
474*700637cbSDimitry Andric     // std::terminate will be called
475*700637cbSDimitry Andric     // This is discussed in P3567, which hasn't been voted on yet.
476*700637cbSDimitry Andric     ranges::swap(__compare_, __y.__compare_);
477*700637cbSDimitry Andric     ranges::swap(__keys_, __y.__keys_);
478*700637cbSDimitry Andric   }
479*700637cbSDimitry Andric 
clear()480*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void clear() noexcept { __keys_.clear(); }
481*700637cbSDimitry Andric 
482*700637cbSDimitry Andric   // observers
key_comp()483*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __compare_; }
value_comp()484*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return __compare_; }
485*700637cbSDimitry Andric 
486*700637cbSDimitry Andric   // map operations
find(const key_type & __x)487*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __x) { return __find_impl(*this, __x); }
488*700637cbSDimitry Andric 
find(const key_type & __x)489*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); }
490*700637cbSDimitry Andric 
491*700637cbSDimitry Andric   template <class _Kp>
492*700637cbSDimitry Andric     requires __is_transparent_v<_Compare>
find(const _Kp & __x)493*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator find(const _Kp& __x) {
494*700637cbSDimitry Andric     return __find_impl(*this, __x);
495*700637cbSDimitry Andric   }
496*700637cbSDimitry Andric 
497*700637cbSDimitry Andric   template <class _Kp>
498*700637cbSDimitry Andric     requires __is_transparent_v<_Compare>
find(const _Kp & __x)499*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Kp& __x) const {
500*700637cbSDimitry Andric     return __find_impl(*this, __x);
501*700637cbSDimitry Andric   }
502*700637cbSDimitry Andric 
count(const key_type & __x)503*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __x) const {
504*700637cbSDimitry Andric     auto [__first, __last] = equal_range(__x);
505*700637cbSDimitry Andric     return __last - __first;
506*700637cbSDimitry Andric   }
507*700637cbSDimitry Andric 
508*700637cbSDimitry Andric   template <class _Kp>
509*700637cbSDimitry Andric     requires __is_transparent_v<_Compare>
count(const _Kp & __x)510*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI size_type count(const _Kp& __x) const {
511*700637cbSDimitry Andric     auto [__first, __last] = equal_range(__x);
512*700637cbSDimitry Andric     return __last - __first;
513*700637cbSDimitry Andric   }
514*700637cbSDimitry Andric 
contains(const key_type & __x)515*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __x) const { return find(__x) != end(); }
516*700637cbSDimitry Andric 
517*700637cbSDimitry Andric   template <class _Kp>
518*700637cbSDimitry Andric     requires __is_transparent_v<_Compare>
contains(const _Kp & __x)519*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool contains(const _Kp& __x) const {
520*700637cbSDimitry Andric     return find(__x) != end();
521*700637cbSDimitry Andric   }
522*700637cbSDimitry Andric 
lower_bound(const key_type & __x)523*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __x) {
524*700637cbSDimitry Andric     const auto& __keys = __keys_;
525*700637cbSDimitry Andric     return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_));
526*700637cbSDimitry Andric   }
527*700637cbSDimitry Andric 
lower_bound(const key_type & __x)528*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __x) const {
529*700637cbSDimitry Andric     return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_));
530*700637cbSDimitry Andric   }
531*700637cbSDimitry Andric 
532*700637cbSDimitry Andric   template <class _Kp>
533*700637cbSDimitry Andric     requires __is_transparent_v<_Compare>
lower_bound(const _Kp & __x)534*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Kp& __x) {
535*700637cbSDimitry Andric     const auto& __keys = __keys_;
536*700637cbSDimitry Andric     return iterator(std::lower_bound(__keys.begin(), __keys.end(), __x, __compare_));
537*700637cbSDimitry Andric   }
538*700637cbSDimitry Andric 
539*700637cbSDimitry Andric   template <class _Kp>
540*700637cbSDimitry Andric     requires __is_transparent_v<_Compare>
lower_bound(const _Kp & __x)541*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Kp& __x) const {
542*700637cbSDimitry Andric     return const_iterator(std::lower_bound(__keys_.begin(), __keys_.end(), __x, __compare_));
543*700637cbSDimitry Andric   }
544*700637cbSDimitry Andric 
upper_bound(const key_type & __x)545*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __x) {
546*700637cbSDimitry Andric     const auto& __keys = __keys_;
547*700637cbSDimitry Andric     return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_));
548*700637cbSDimitry Andric   }
549*700637cbSDimitry Andric 
upper_bound(const key_type & __x)550*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __x) const {
551*700637cbSDimitry Andric     return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_));
552*700637cbSDimitry Andric   }
553*700637cbSDimitry Andric 
554*700637cbSDimitry Andric   template <class _Kp>
555*700637cbSDimitry Andric     requires __is_transparent_v<_Compare>
upper_bound(const _Kp & __x)556*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _Kp& __x) {
557*700637cbSDimitry Andric     const auto& __keys = __keys_;
558*700637cbSDimitry Andric     return iterator(std::upper_bound(__keys.begin(), __keys.end(), __x, __compare_));
559*700637cbSDimitry Andric   }
560*700637cbSDimitry Andric 
561*700637cbSDimitry Andric   template <class _Kp>
562*700637cbSDimitry Andric     requires __is_transparent_v<_Compare>
upper_bound(const _Kp & __x)563*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Kp& __x) const {
564*700637cbSDimitry Andric     return const_iterator(std::upper_bound(__keys_.begin(), __keys_.end(), __x, __compare_));
565*700637cbSDimitry Andric   }
566*700637cbSDimitry Andric 
equal_range(const key_type & __x)567*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __x) {
568*700637cbSDimitry Andric     return __equal_range_impl(*this, __x);
569*700637cbSDimitry Andric   }
570*700637cbSDimitry Andric 
equal_range(const key_type & __x)571*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __x) const {
572*700637cbSDimitry Andric     return __equal_range_impl(*this, __x);
573*700637cbSDimitry Andric   }
574*700637cbSDimitry Andric 
575*700637cbSDimitry Andric   template <class _Kp>
576*700637cbSDimitry Andric     requires __is_transparent_v<_Compare>
equal_range(const _Kp & __x)577*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _Kp& __x) {
578*700637cbSDimitry Andric     return __equal_range_impl(*this, __x);
579*700637cbSDimitry Andric   }
580*700637cbSDimitry Andric   template <class _Kp>
581*700637cbSDimitry Andric     requires __is_transparent_v<_Compare>
equal_range(const _Kp & __x)582*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _Kp& __x) const {
583*700637cbSDimitry Andric     return __equal_range_impl(*this, __x);
584*700637cbSDimitry Andric   }
585*700637cbSDimitry Andric 
586*700637cbSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool operator==(const flat_multiset& __x, const flat_multiset& __y) {
587*700637cbSDimitry Andric     return ranges::equal(__x, __y);
588*700637cbSDimitry Andric   }
589*700637cbSDimitry Andric 
590*700637cbSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI auto operator<=>(const flat_multiset& __x, const flat_multiset& __y) {
591*700637cbSDimitry Andric     return std::lexicographical_compare_three_way(
592*700637cbSDimitry Andric         __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
593*700637cbSDimitry Andric   }
594*700637cbSDimitry Andric 
swap(flat_multiset & __x,flat_multiset & __y)595*700637cbSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI void swap(flat_multiset& __x, flat_multiset& __y) noexcept { __x.swap(__y); }
596*700637cbSDimitry Andric 
597*700637cbSDimitry Andric private:
598*700637cbSDimitry Andric   template <bool _WasSorted, class... _Args>
__append_sort_merge(_Args &&...__args)599*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void __append_sort_merge(_Args&&... __args) {
600*700637cbSDimitry Andric     auto __on_failure    = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
601*700637cbSDimitry Andric     size_type __old_size = size();
602*700637cbSDimitry Andric     __flat_set_utils::__append(*this, std::forward<_Args>(__args)...);
603*700637cbSDimitry Andric     if constexpr (!_WasSorted) {
604*700637cbSDimitry Andric       ranges::sort(__keys_.begin() + __old_size, __keys_.end(), __compare_);
605*700637cbSDimitry Andric     } else {
606*700637cbSDimitry Andric       _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
607*700637cbSDimitry Andric           ranges::is_sorted(__keys_ | ranges::views::drop(__old_size)), "Key container is not sorted");
608*700637cbSDimitry Andric     }
609*700637cbSDimitry Andric     ranges::inplace_merge(__keys_.begin(), __keys_.begin() + __old_size, __keys_.end(), __compare_);
610*700637cbSDimitry Andric     __on_failure.__complete();
611*700637cbSDimitry Andric   }
612*700637cbSDimitry Andric 
613*700637cbSDimitry Andric   template <class _Kp>
__emplace(_Kp && __key)614*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator __emplace(_Kp&& __key) {
615*700637cbSDimitry Andric     auto __it = upper_bound(__key);
616*700637cbSDimitry Andric     return __flat_set_utils::__emplace_exact_pos(*this, __it, std::forward<_Kp>(__key));
617*700637cbSDimitry Andric   }
618*700637cbSDimitry Andric 
619*700637cbSDimitry Andric   template <class _Kp>
__emplace_hint(const_iterator __hint,_Kp && __key)620*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator __emplace_hint(const_iterator __hint, _Kp&& __key) {
621*700637cbSDimitry Andric     auto __prev_larger  = __hint != cbegin() && __compare_(__key, *std::prev(__hint));
622*700637cbSDimitry Andric     auto __next_smaller = __hint != cend() && __compare_(*__hint, __key);
623*700637cbSDimitry Andric 
624*700637cbSDimitry Andric     if (!__prev_larger && !__next_smaller) [[likely]] {
625*700637cbSDimitry Andric       // hint correct, just use exact hint iterator
626*700637cbSDimitry Andric     } else if (__prev_larger && !__next_smaller) {
627*700637cbSDimitry Andric       // the hint position is more to the right than the key should have been.
628*700637cbSDimitry Andric       // we want to emplace the element to a position as right as possible
629*700637cbSDimitry Andric       // e.g. Insert new element "2" in the following range
630*700637cbSDimitry Andric       // 1, 1, 2, 2, 2, 3, 4, 6
631*700637cbSDimitry Andric       //                   ^
632*700637cbSDimitry Andric       //                   |
633*700637cbSDimitry Andric       //                  hint
634*700637cbSDimitry Andric       // We want to insert "2" after the last existing "2"
635*700637cbSDimitry Andric       __hint = std::upper_bound(begin(), __hint, __key, __compare_);
636*700637cbSDimitry Andric     } else {
637*700637cbSDimitry Andric       _LIBCPP_ASSERT_INTERNAL(!__prev_larger && __next_smaller, "this means that the multiset is not sorted");
638*700637cbSDimitry Andric 
639*700637cbSDimitry Andric       // the hint position is more to the left than the key should have been.
640*700637cbSDimitry Andric       // we want to emplace the element to a position as left as possible
641*700637cbSDimitry Andric       //  1, 1, 2, 2, 2, 3, 4, 6
642*700637cbSDimitry Andric       //  ^
643*700637cbSDimitry Andric       //  |
644*700637cbSDimitry Andric       // hint
645*700637cbSDimitry Andric       // We want to insert "2" before the first existing "2"
646*700637cbSDimitry Andric       __hint = std::lower_bound(__hint, end(), __key, __compare_);
647*700637cbSDimitry Andric     }
648*700637cbSDimitry Andric     return __flat_set_utils::__emplace_exact_pos(*this, __hint, std::forward<_Kp>(__key));
649*700637cbSDimitry Andric   }
650*700637cbSDimitry Andric 
651*700637cbSDimitry Andric   template <class _Self, class _Kp>
__find_impl(_Self && __self,const _Kp & __key)652*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static auto __find_impl(_Self&& __self, const _Kp& __key) {
653*700637cbSDimitry Andric     auto __it   = __self.lower_bound(__key);
654*700637cbSDimitry Andric     auto __last = __self.end();
655*700637cbSDimitry Andric     if (__it == __last || __self.__compare_(__key, *__it)) {
656*700637cbSDimitry Andric       return __last;
657*700637cbSDimitry Andric     }
658*700637cbSDimitry Andric     return __it;
659*700637cbSDimitry Andric   }
660*700637cbSDimitry Andric 
661*700637cbSDimitry Andric   template <class _Self, class _Kp>
__equal_range_impl(_Self && __self,const _Kp & __key)662*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static auto __equal_range_impl(_Self&& __self, const _Kp& __key) {
663*700637cbSDimitry Andric     using __iter = _If<is_const_v<__libcpp_remove_reference_t<_Self>>, const_iterator, iterator>;
664*700637cbSDimitry Andric     auto [__key_first, __key_last] =
665*700637cbSDimitry Andric         std::equal_range(__self.__keys_.begin(), __self.__keys_.end(), __key, __self.__compare_);
666*700637cbSDimitry Andric     return std::make_pair(__iter(__key_first), __iter(__key_last));
667*700637cbSDimitry Andric   }
668*700637cbSDimitry Andric 
__reserve(size_t __size)669*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) {
670*700637cbSDimitry Andric     if constexpr (__container_traits<_KeyContainer>::__reservable) {
671*700637cbSDimitry Andric       __keys_.reserve(__size);
672*700637cbSDimitry Andric     }
673*700637cbSDimitry Andric   }
674*700637cbSDimitry Andric 
675*700637cbSDimitry Andric   template <class _Key2, class _Compare2, class _KeyContainer2, class _Predicate>
676*700637cbSDimitry Andric   friend typename flat_multiset<_Key2, _Compare2, _KeyContainer2>::size_type
677*700637cbSDimitry Andric   erase_if(flat_multiset<_Key2, _Compare2, _KeyContainer2>&, _Predicate);
678*700637cbSDimitry Andric 
679*700637cbSDimitry Andric   _KeyContainer __keys_;
680*700637cbSDimitry Andric   _LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_;
681*700637cbSDimitry Andric 
682*700637cbSDimitry Andric   struct __key_equiv {
__key_equiv__key_equiv683*700637cbSDimitry Andric     _LIBCPP_HIDE_FROM_ABI __key_equiv(key_compare __c) : __comp_(__c) {}
operator__key_equiv684*700637cbSDimitry Andric     _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const {
685*700637cbSDimitry Andric       return !__comp_(std::get<0>(__x), std::get<0>(__y)) && !__comp_(std::get<0>(__y), std::get<0>(__x));
686*700637cbSDimitry Andric     }
687*700637cbSDimitry Andric     key_compare __comp_;
688*700637cbSDimitry Andric   };
689*700637cbSDimitry Andric };
690*700637cbSDimitry Andric 
691*700637cbSDimitry Andric template <class _KeyContainer, class _Compare = less<typename _KeyContainer::value_type>>
692*700637cbSDimitry Andric   requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
693*700637cbSDimitry Andric            is_invocable_v<const _Compare&,
694*700637cbSDimitry Andric                           const typename _KeyContainer::value_type&,
695*700637cbSDimitry Andric                           const typename _KeyContainer::value_type&>)
696*700637cbSDimitry Andric flat_multiset(_KeyContainer, _Compare = _Compare())
697*700637cbSDimitry Andric     -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
698*700637cbSDimitry Andric 
699*700637cbSDimitry Andric template <class _KeyContainer, class _Allocator>
700*700637cbSDimitry Andric   requires(uses_allocator_v<_KeyContainer, _Allocator> && !__is_allocator<_KeyContainer>::value)
701*700637cbSDimitry Andric flat_multiset(_KeyContainer, _Allocator)
702*700637cbSDimitry Andric     -> flat_multiset<typename _KeyContainer::value_type, less<typename _KeyContainer::value_type>, _KeyContainer>;
703*700637cbSDimitry Andric 
704*700637cbSDimitry Andric template <class _KeyContainer, class _Compare, class _Allocator>
705*700637cbSDimitry Andric   requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
706*700637cbSDimitry Andric            uses_allocator_v<_KeyContainer, _Allocator> &&
707*700637cbSDimitry Andric            is_invocable_v<const _Compare&,
708*700637cbSDimitry Andric                           const typename _KeyContainer::value_type&,
709*700637cbSDimitry Andric                           const typename _KeyContainer::value_type&>)
710*700637cbSDimitry Andric flat_multiset(_KeyContainer, _Compare, _Allocator)
711*700637cbSDimitry Andric     -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
712*700637cbSDimitry Andric 
713*700637cbSDimitry Andric template <class _KeyContainer, class _Compare = less<typename _KeyContainer::value_type>>
714*700637cbSDimitry Andric   requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
715*700637cbSDimitry Andric            is_invocable_v<const _Compare&,
716*700637cbSDimitry Andric                           const typename _KeyContainer::value_type&,
717*700637cbSDimitry Andric                           const typename _KeyContainer::value_type&>)
718*700637cbSDimitry Andric flat_multiset(sorted_equivalent_t, _KeyContainer, _Compare = _Compare())
719*700637cbSDimitry Andric     -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
720*700637cbSDimitry Andric 
721*700637cbSDimitry Andric template <class _KeyContainer, class _Allocator>
722*700637cbSDimitry Andric   requires(uses_allocator_v<_KeyContainer, _Allocator> && !__is_allocator<_KeyContainer>::value)
723*700637cbSDimitry Andric flat_multiset(sorted_equivalent_t, _KeyContainer, _Allocator)
724*700637cbSDimitry Andric     -> flat_multiset<typename _KeyContainer::value_type, less<typename _KeyContainer::value_type>, _KeyContainer>;
725*700637cbSDimitry Andric 
726*700637cbSDimitry Andric template <class _KeyContainer, class _Compare, class _Allocator>
727*700637cbSDimitry Andric   requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
728*700637cbSDimitry Andric            uses_allocator_v<_KeyContainer, _Allocator> &&
729*700637cbSDimitry Andric            is_invocable_v<const _Compare&,
730*700637cbSDimitry Andric                           const typename _KeyContainer::value_type&,
731*700637cbSDimitry Andric                           const typename _KeyContainer::value_type&>)
732*700637cbSDimitry Andric flat_multiset(sorted_equivalent_t, _KeyContainer, _Compare, _Allocator)
733*700637cbSDimitry Andric     -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;
734*700637cbSDimitry Andric 
735*700637cbSDimitry Andric template <class _InputIterator, class _Compare = less<__iter_value_type<_InputIterator>>>
736*700637cbSDimitry Andric   requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value)
737*700637cbSDimitry Andric flat_multiset(_InputIterator, _InputIterator, _Compare = _Compare())
738*700637cbSDimitry Andric     -> flat_multiset<__iter_value_type<_InputIterator>, _Compare>;
739*700637cbSDimitry Andric 
740*700637cbSDimitry Andric template <class _InputIterator, class _Compare = less<__iter_value_type<_InputIterator>>>
741*700637cbSDimitry Andric   requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value)
742*700637cbSDimitry Andric flat_multiset(sorted_equivalent_t, _InputIterator, _InputIterator, _Compare = _Compare())
743*700637cbSDimitry Andric     -> flat_multiset<__iter_value_type<_InputIterator>, _Compare>;
744*700637cbSDimitry Andric 
745*700637cbSDimitry Andric template <ranges::input_range _Range,
746*700637cbSDimitry Andric           class _Compare   = less<ranges::range_value_t<_Range>>,
747*700637cbSDimitry Andric           class _Allocator = allocator<ranges::range_value_t<_Range>>,
748*700637cbSDimitry Andric           class            = __enable_if_t<!__is_allocator<_Compare>::value && __is_allocator<_Allocator>::value>>
749*700637cbSDimitry Andric flat_multiset(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) -> flat_multiset<
750*700637cbSDimitry Andric     ranges::range_value_t<_Range>,
751*700637cbSDimitry Andric     _Compare,
752*700637cbSDimitry Andric     vector<ranges::range_value_t<_Range>, __allocator_traits_rebind_t<_Allocator, ranges::range_value_t<_Range>>>>;
753*700637cbSDimitry Andric 
754*700637cbSDimitry Andric template <ranges::input_range _Range, class _Allocator, class = __enable_if_t<__is_allocator<_Allocator>::value>>
755*700637cbSDimitry Andric flat_multiset(from_range_t, _Range&&, _Allocator) -> flat_multiset<
756*700637cbSDimitry Andric     ranges::range_value_t<_Range>,
757*700637cbSDimitry Andric     less<ranges::range_value_t<_Range>>,
758*700637cbSDimitry Andric     vector<ranges::range_value_t<_Range>, __allocator_traits_rebind_t<_Allocator, ranges::range_value_t<_Range>>>>;
759*700637cbSDimitry Andric 
760*700637cbSDimitry Andric template <class _Key, class _Compare = less<_Key>>
761*700637cbSDimitry Andric   requires(!__is_allocator<_Compare>::value)
762*700637cbSDimitry Andric flat_multiset(initializer_list<_Key>, _Compare = _Compare()) -> flat_multiset<_Key, _Compare>;
763*700637cbSDimitry Andric 
764*700637cbSDimitry Andric template <class _Key, class _Compare = less<_Key>>
765*700637cbSDimitry Andric   requires(!__is_allocator<_Compare>::value)
766*700637cbSDimitry Andric flat_multiset(sorted_equivalent_t, initializer_list<_Key>, _Compare = _Compare()) -> flat_multiset<_Key, _Compare>;
767*700637cbSDimitry Andric 
768*700637cbSDimitry Andric template <class _Key, class _Compare, class _KeyContainer, class _Allocator>
769*700637cbSDimitry Andric struct uses_allocator<flat_multiset<_Key, _Compare, _KeyContainer>, _Allocator>
770*700637cbSDimitry Andric     : bool_constant<uses_allocator_v<_KeyContainer, _Allocator> > {};
771*700637cbSDimitry Andric 
772*700637cbSDimitry Andric template <class _Key, class _Compare, class _KeyContainer, class _Predicate>
773*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI typename flat_multiset<_Key, _Compare, _KeyContainer>::size_type
774*700637cbSDimitry Andric erase_if(flat_multiset<_Key, _Compare, _KeyContainer>& __flat_multiset, _Predicate __pred) {
775*700637cbSDimitry Andric   auto __guard = std::__make_exception_guard([&] { __flat_multiset.clear(); });
776*700637cbSDimitry Andric   auto __it =
777*700637cbSDimitry Andric       std::remove_if(__flat_multiset.__keys_.begin(), __flat_multiset.__keys_.end(), [&](const auto& __e) -> bool {
778*700637cbSDimitry Andric         return static_cast<bool>(__pred(__e));
779*700637cbSDimitry Andric       });
780*700637cbSDimitry Andric   auto __res = __flat_multiset.__keys_.end() - __it;
781*700637cbSDimitry Andric   __flat_multiset.__keys_.erase(__it, __flat_multiset.__keys_.end());
782*700637cbSDimitry Andric   __guard.__complete();
783*700637cbSDimitry Andric   return __res;
784*700637cbSDimitry Andric }
785*700637cbSDimitry Andric 
786*700637cbSDimitry Andric _LIBCPP_END_NAMESPACE_STD
787*700637cbSDimitry Andric 
788*700637cbSDimitry Andric #endif // _LIBCPP_STD_VER >= 23
789*700637cbSDimitry Andric 
790*700637cbSDimitry Andric _LIBCPP_POP_MACROS
791*700637cbSDimitry Andric 
792*700637cbSDimitry Andric #endif // _LIBCPP___FLAT_MAP_FLAT_MULTISET_H
793