xref: /freebsd/contrib/llvm-project/libcxx/include/__flat_map/flat_multimap.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_MULTIMAP_H
11*700637cbSDimitry Andric #define _LIBCPP___FLAT_MAP_FLAT_MULTIMAP_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/remove_if.h>
22*700637cbSDimitry Andric #include <__algorithm/upper_bound.h>
23*700637cbSDimitry Andric #include <__assert>
24*700637cbSDimitry Andric #include <__compare/synth_three_way.h>
25*700637cbSDimitry Andric #include <__concepts/convertible_to.h>
26*700637cbSDimitry Andric #include <__concepts/swappable.h>
27*700637cbSDimitry Andric #include <__config>
28*700637cbSDimitry Andric #include <__cstddef/byte.h>
29*700637cbSDimitry Andric #include <__cstddef/ptrdiff_t.h>
30*700637cbSDimitry Andric #include <__flat_map/key_value_iterator.h>
31*700637cbSDimitry Andric #include <__flat_map/sorted_equivalent.h>
32*700637cbSDimitry Andric #include <__flat_map/utils.h>
33*700637cbSDimitry Andric #include <__functional/invoke.h>
34*700637cbSDimitry Andric #include <__functional/is_transparent.h>
35*700637cbSDimitry Andric #include <__functional/operations.h>
36*700637cbSDimitry Andric #include <__fwd/vector.h>
37*700637cbSDimitry Andric #include <__iterator/concepts.h>
38*700637cbSDimitry Andric #include <__iterator/distance.h>
39*700637cbSDimitry Andric #include <__iterator/iterator_traits.h>
40*700637cbSDimitry Andric #include <__iterator/ranges_iterator_traits.h>
41*700637cbSDimitry Andric #include <__iterator/reverse_iterator.h>
42*700637cbSDimitry Andric #include <__memory/allocator_traits.h>
43*700637cbSDimitry Andric #include <__memory/uses_allocator.h>
44*700637cbSDimitry Andric #include <__memory/uses_allocator_construction.h>
45*700637cbSDimitry Andric #include <__ranges/access.h>
46*700637cbSDimitry Andric #include <__ranges/concepts.h>
47*700637cbSDimitry Andric #include <__ranges/container_compatible_range.h>
48*700637cbSDimitry Andric #include <__ranges/drop_view.h>
49*700637cbSDimitry Andric #include <__ranges/from_range.h>
50*700637cbSDimitry Andric #include <__ranges/ref_view.h>
51*700637cbSDimitry Andric #include <__ranges/size.h>
52*700637cbSDimitry Andric #include <__ranges/subrange.h>
53*700637cbSDimitry Andric #include <__ranges/zip_view.h>
54*700637cbSDimitry Andric #include <__type_traits/conjunction.h>
55*700637cbSDimitry Andric #include <__type_traits/container_traits.h>
56*700637cbSDimitry Andric #include <__type_traits/invoke.h>
57*700637cbSDimitry Andric #include <__type_traits/is_allocator.h>
58*700637cbSDimitry Andric #include <__type_traits/is_nothrow_constructible.h>
59*700637cbSDimitry Andric #include <__type_traits/is_same.h>
60*700637cbSDimitry Andric #include <__type_traits/maybe_const.h>
61*700637cbSDimitry Andric #include <__utility/exception_guard.h>
62*700637cbSDimitry Andric #include <__utility/move.h>
63*700637cbSDimitry Andric #include <__utility/pair.h>
64*700637cbSDimitry Andric #include <__utility/scope_guard.h>
65*700637cbSDimitry Andric #include <__vector/vector.h>
66*700637cbSDimitry Andric #include <initializer_list>
67*700637cbSDimitry Andric #include <stdexcept>
68*700637cbSDimitry Andric 
69*700637cbSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
70*700637cbSDimitry Andric #  pragma GCC system_header
71*700637cbSDimitry Andric #endif
72*700637cbSDimitry Andric 
73*700637cbSDimitry Andric _LIBCPP_PUSH_MACROS
74*700637cbSDimitry Andric #include <__undef_macros>
75*700637cbSDimitry Andric 
76*700637cbSDimitry Andric #if _LIBCPP_STD_VER >= 23
77*700637cbSDimitry Andric 
78*700637cbSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
79*700637cbSDimitry Andric 
80*700637cbSDimitry Andric template <class _Key,
81*700637cbSDimitry Andric           class _Tp,
82*700637cbSDimitry Andric           class _Compare         = less<_Key>,
83*700637cbSDimitry Andric           class _KeyContainer    = vector<_Key>,
84*700637cbSDimitry Andric           class _MappedContainer = vector<_Tp>>
85*700637cbSDimitry Andric class flat_multimap {
86*700637cbSDimitry Andric   template <class, class, class, class, class>
87*700637cbSDimitry Andric   friend class flat_multimap;
88*700637cbSDimitry Andric 
89*700637cbSDimitry Andric   static_assert(is_same_v<_Key, typename _KeyContainer::value_type>);
90*700637cbSDimitry Andric   static_assert(is_same_v<_Tp, typename _MappedContainer::value_type>);
91*700637cbSDimitry Andric   static_assert(!is_same_v<_KeyContainer, std::vector<bool>>, "vector<bool> is not a sequence container");
92*700637cbSDimitry Andric   static_assert(!is_same_v<_MappedContainer, std::vector<bool>>, "vector<bool> is not a sequence container");
93*700637cbSDimitry Andric 
94*700637cbSDimitry Andric   template <bool _Const>
95*700637cbSDimitry Andric   using __iterator _LIBCPP_NODEBUG = __key_value_iterator<flat_multimap, _KeyContainer, _MappedContainer, _Const>;
96*700637cbSDimitry Andric 
97*700637cbSDimitry Andric public:
98*700637cbSDimitry Andric   // types
99*700637cbSDimitry Andric   using key_type               = _Key;
100*700637cbSDimitry Andric   using mapped_type            = _Tp;
101*700637cbSDimitry Andric   using value_type             = pair<key_type, mapped_type>;
102*700637cbSDimitry Andric   using key_compare            = __type_identity_t<_Compare>;
103*700637cbSDimitry Andric   using reference              = pair<const key_type&, mapped_type&>;
104*700637cbSDimitry Andric   using const_reference        = pair<const key_type&, const mapped_type&>;
105*700637cbSDimitry Andric   using size_type              = size_t;
106*700637cbSDimitry Andric   using difference_type        = ptrdiff_t;
107*700637cbSDimitry Andric   using iterator               = __iterator<false>; // see [container.requirements]
108*700637cbSDimitry Andric   using const_iterator         = __iterator<true>;  // see [container.requirements]
109*700637cbSDimitry Andric   using reverse_iterator       = std::reverse_iterator<iterator>;
110*700637cbSDimitry Andric   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
111*700637cbSDimitry Andric   using key_container_type     = _KeyContainer;
112*700637cbSDimitry Andric   using mapped_container_type  = _MappedContainer;
113*700637cbSDimitry Andric 
114*700637cbSDimitry Andric   class value_compare {
115*700637cbSDimitry Andric   private:
116*700637cbSDimitry Andric     _LIBCPP_NO_UNIQUE_ADDRESS key_compare __comp_;
value_compare(key_compare __c)117*700637cbSDimitry Andric     _LIBCPP_HIDE_FROM_ABI value_compare(key_compare __c) : __comp_(__c) {}
118*700637cbSDimitry Andric     friend flat_multimap;
119*700637cbSDimitry Andric 
120*700637cbSDimitry Andric   public:
operator()121*700637cbSDimitry Andric     _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const {
122*700637cbSDimitry Andric       return __comp_(__x.first, __y.first);
123*700637cbSDimitry Andric     }
124*700637cbSDimitry Andric   };
125*700637cbSDimitry Andric 
126*700637cbSDimitry Andric   struct containers {
127*700637cbSDimitry Andric     key_container_type keys;
128*700637cbSDimitry Andric     mapped_container_type values;
129*700637cbSDimitry Andric   };
130*700637cbSDimitry Andric 
131*700637cbSDimitry Andric private:
132*700637cbSDimitry Andric   template <class _Allocator>
133*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static constexpr bool __allocator_ctor_constraint =
134*700637cbSDimitry Andric       _And<uses_allocator<key_container_type, _Allocator>, uses_allocator<mapped_container_type, _Allocator>>::value;
135*700637cbSDimitry Andric 
136*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static constexpr bool __is_compare_transparent = __is_transparent_v<_Compare>;
137*700637cbSDimitry Andric 
138*700637cbSDimitry Andric public:
139*700637cbSDimitry Andric   // [flat.map.cons], construct/copy/destroy
flat_multimap()140*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap() noexcept(
141*700637cbSDimitry Andric       is_nothrow_default_constructible_v<_KeyContainer> && is_nothrow_default_constructible_v<_MappedContainer> &&
142*700637cbSDimitry Andric       is_nothrow_default_constructible_v<_Compare>)
143*700637cbSDimitry Andric       : __containers_(), __compare_() {}
144*700637cbSDimitry Andric 
145*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(const flat_multimap&) = default;
146*700637cbSDimitry Andric 
147*700637cbSDimitry Andric   // The copy/move constructors are not specified in the spec, which means they should be defaulted.
148*700637cbSDimitry Andric   // However, the move constructor can potentially leave a moved-from object in an inconsistent
149*700637cbSDimitry Andric   // state if an exception is thrown.
flat_multimap(flat_multimap && __other)150*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(flat_multimap&& __other) noexcept(
151*700637cbSDimitry Andric       is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_MappedContainer> &&
152*700637cbSDimitry Andric       is_nothrow_move_constructible_v<_Compare>)
153*700637cbSDimitry Andric #  if _LIBCPP_HAS_EXCEPTIONS
154*700637cbSDimitry Andric       try
155*700637cbSDimitry Andric #  endif // _LIBCPP_HAS_EXCEPTIONS
156*700637cbSDimitry Andric       : __containers_(std::move(__other.__containers_)), __compare_(std::move(__other.__compare_)) {
157*700637cbSDimitry Andric     __other.clear();
158*700637cbSDimitry Andric #  if _LIBCPP_HAS_EXCEPTIONS
159*700637cbSDimitry Andric   } catch (...) {
160*700637cbSDimitry Andric     __other.clear();
161*700637cbSDimitry Andric     // gcc does not like the `throw` keyword in a conditionally noexcept function
162*700637cbSDimitry Andric     if constexpr (!(is_nothrow_move_constructible_v<_KeyContainer> &&
163*700637cbSDimitry Andric                     is_nothrow_move_constructible_v<_MappedContainer> && is_nothrow_move_constructible_v<_Compare>)) {
164*700637cbSDimitry Andric       throw;
165*700637cbSDimitry Andric     }
166*700637cbSDimitry Andric #  endif // _LIBCPP_HAS_EXCEPTIONS
167*700637cbSDimitry Andric   }
168*700637cbSDimitry Andric 
169*700637cbSDimitry Andric   template <class _Allocator>
170*700637cbSDimitry Andric     requires __allocator_ctor_constraint<_Allocator>
flat_multimap(const flat_multimap & __other,const _Allocator & __alloc)171*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(const flat_multimap& __other, const _Allocator& __alloc)
172*700637cbSDimitry Andric       : flat_multimap(__ctor_uses_allocator_tag{},
173*700637cbSDimitry Andric                       __alloc,
174*700637cbSDimitry Andric                       __other.__containers_.keys,
175*700637cbSDimitry Andric                       __other.__containers_.values,
176*700637cbSDimitry Andric                       __other.__compare_) {}
177*700637cbSDimitry Andric 
178*700637cbSDimitry Andric   template <class _Allocator>
179*700637cbSDimitry Andric     requires __allocator_ctor_constraint<_Allocator>
flat_multimap(flat_multimap && __other,const _Allocator & __alloc)180*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(flat_multimap&& __other, const _Allocator& __alloc)
181*700637cbSDimitry Andric #  if _LIBCPP_HAS_EXCEPTIONS
182*700637cbSDimitry Andric       try
183*700637cbSDimitry Andric #  endif // _LIBCPP_HAS_EXCEPTIONS
184*700637cbSDimitry Andric       : flat_multimap(__ctor_uses_allocator_tag{},
185*700637cbSDimitry Andric                       __alloc,
186*700637cbSDimitry Andric                       std::move(__other.__containers_.keys),
187*700637cbSDimitry Andric                       std::move(__other.__containers_.values),
188*700637cbSDimitry Andric                       std::move(__other.__compare_)) {
189*700637cbSDimitry Andric     __other.clear();
190*700637cbSDimitry Andric #  if _LIBCPP_HAS_EXCEPTIONS
catch(...)191*700637cbSDimitry Andric   } catch (...) {
192*700637cbSDimitry Andric     __other.clear();
193*700637cbSDimitry Andric     throw;
194*700637cbSDimitry Andric #  endif // _LIBCPP_HAS_EXCEPTIONS
195*700637cbSDimitry Andric   }
196*700637cbSDimitry Andric 
197*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(
198*700637cbSDimitry Andric       key_container_type __key_cont, mapped_container_type __mapped_cont, const key_compare& __comp = key_compare())
199*700637cbSDimitry Andric       : __containers_{.keys = std::move(__key_cont), .values = std::move(__mapped_cont)}, __compare_(__comp) {
200*700637cbSDimitry Andric     _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
201*700637cbSDimitry Andric                                      "flat_multimap keys and mapped containers have different size");
202*700637cbSDimitry Andric     __sort();
203*700637cbSDimitry Andric   }
204*700637cbSDimitry Andric 
205*700637cbSDimitry Andric   template <class _Allocator>
206*700637cbSDimitry Andric     requires __allocator_ctor_constraint<_Allocator>
flat_multimap(const key_container_type & __key_cont,const mapped_container_type & __mapped_cont,const _Allocator & __alloc)207*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(
208*700637cbSDimitry Andric       const key_container_type& __key_cont, const mapped_container_type& __mapped_cont, const _Allocator& __alloc)
209*700637cbSDimitry Andric       : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont) {
210*700637cbSDimitry Andric     _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
211*700637cbSDimitry Andric                                      "flat_multimap keys and mapped containers have different size");
212*700637cbSDimitry Andric     __sort();
213*700637cbSDimitry Andric   }
214*700637cbSDimitry Andric 
215*700637cbSDimitry Andric   template <class _Allocator>
216*700637cbSDimitry Andric     requires __allocator_ctor_constraint<_Allocator>
217*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
flat_multimap(const key_container_type & __key_cont,const mapped_container_type & __mapped_cont,const key_compare & __comp,const _Allocator & __alloc)218*700637cbSDimitry Andric   flat_multimap(const key_container_type& __key_cont,
219*700637cbSDimitry Andric                 const mapped_container_type& __mapped_cont,
220*700637cbSDimitry Andric                 const key_compare& __comp,
221*700637cbSDimitry Andric                 const _Allocator& __alloc)
222*700637cbSDimitry Andric       : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont, __comp) {
223*700637cbSDimitry Andric     _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
224*700637cbSDimitry Andric                                      "flat_multimap keys and mapped containers have different size");
225*700637cbSDimitry Andric     __sort();
226*700637cbSDimitry Andric   }
227*700637cbSDimitry Andric 
228*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
229*700637cbSDimitry Andric   flat_multimap(sorted_equivalent_t,
230*700637cbSDimitry Andric                 key_container_type __key_cont,
231*700637cbSDimitry Andric                 mapped_container_type __mapped_cont,
232*700637cbSDimitry Andric                 const key_compare& __comp = key_compare())
233*700637cbSDimitry Andric       : __containers_{.keys = std::move(__key_cont), .values = std::move(__mapped_cont)}, __compare_(__comp) {
234*700637cbSDimitry Andric     _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
235*700637cbSDimitry Andric                                      "flat_multimap keys and mapped containers have different size");
236*700637cbSDimitry Andric     _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__is_sorted(__containers_.keys), "Key container is not sorted");
237*700637cbSDimitry Andric   }
238*700637cbSDimitry Andric 
239*700637cbSDimitry Andric   template <class _Allocator>
240*700637cbSDimitry Andric     requires __allocator_ctor_constraint<_Allocator>
241*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
flat_multimap(sorted_equivalent_t,const key_container_type & __key_cont,const mapped_container_type & __mapped_cont,const _Allocator & __alloc)242*700637cbSDimitry Andric   flat_multimap(sorted_equivalent_t,
243*700637cbSDimitry Andric                 const key_container_type& __key_cont,
244*700637cbSDimitry Andric                 const mapped_container_type& __mapped_cont,
245*700637cbSDimitry Andric                 const _Allocator& __alloc)
246*700637cbSDimitry Andric       : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont) {
247*700637cbSDimitry Andric     _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
248*700637cbSDimitry Andric                                      "flat_multimap keys and mapped containers have different size");
249*700637cbSDimitry Andric     _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__is_sorted(__containers_.keys), "Key container is not sorted");
250*700637cbSDimitry Andric   }
251*700637cbSDimitry Andric 
252*700637cbSDimitry Andric   template <class _Allocator>
253*700637cbSDimitry Andric     requires __allocator_ctor_constraint<_Allocator>
254*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
flat_multimap(sorted_equivalent_t,const key_container_type & __key_cont,const mapped_container_type & __mapped_cont,const key_compare & __comp,const _Allocator & __alloc)255*700637cbSDimitry Andric   flat_multimap(sorted_equivalent_t,
256*700637cbSDimitry Andric                 const key_container_type& __key_cont,
257*700637cbSDimitry Andric                 const mapped_container_type& __mapped_cont,
258*700637cbSDimitry Andric                 const key_compare& __comp,
259*700637cbSDimitry Andric                 const _Allocator& __alloc)
260*700637cbSDimitry Andric       : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont, __comp) {
261*700637cbSDimitry Andric     _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
262*700637cbSDimitry Andric                                      "flat_multimap keys and mapped containers have different size");
263*700637cbSDimitry Andric     _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__is_sorted(__containers_.keys), "Key container is not sorted");
264*700637cbSDimitry Andric   }
265*700637cbSDimitry Andric 
flat_multimap(const key_compare & __comp)266*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI explicit flat_multimap(const key_compare& __comp) : __containers_(), __compare_(__comp) {}
267*700637cbSDimitry Andric 
268*700637cbSDimitry Andric   template <class _Allocator>
269*700637cbSDimitry Andric     requires __allocator_ctor_constraint<_Allocator>
flat_multimap(const key_compare & __comp,const _Allocator & __alloc)270*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(const key_compare& __comp, const _Allocator& __alloc)
271*700637cbSDimitry Andric       : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {}
272*700637cbSDimitry Andric 
273*700637cbSDimitry Andric   template <class _Allocator>
274*700637cbSDimitry Andric     requires __allocator_ctor_constraint<_Allocator>
flat_multimap(const _Allocator & __alloc)275*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI explicit flat_multimap(const _Allocator& __alloc)
276*700637cbSDimitry Andric       : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) {}
277*700637cbSDimitry Andric 
278*700637cbSDimitry Andric   template <class _InputIterator>
279*700637cbSDimitry Andric     requires __has_input_iterator_category<_InputIterator>::value
280*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
281*700637cbSDimitry Andric   flat_multimap(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare())
__containers_()282*700637cbSDimitry Andric       : __containers_(), __compare_(__comp) {
283*700637cbSDimitry Andric     insert(__first, __last);
284*700637cbSDimitry Andric   }
285*700637cbSDimitry Andric 
286*700637cbSDimitry Andric   template <class _InputIterator, class _Allocator>
requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)287*700637cbSDimitry Andric     requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)
288*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
289*700637cbSDimitry Andric   flat_multimap(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc)
290*700637cbSDimitry Andric       : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {
291*700637cbSDimitry Andric     insert(__first, __last);
292*700637cbSDimitry Andric   }
293*700637cbSDimitry Andric 
294*700637cbSDimitry Andric   template <class _InputIterator, class _Allocator>
requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)295*700637cbSDimitry Andric     requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)
296*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc)
297*700637cbSDimitry Andric       : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) {
298*700637cbSDimitry Andric     insert(__first, __last);
299*700637cbSDimitry Andric   }
300*700637cbSDimitry Andric 
301*700637cbSDimitry Andric   template <_ContainerCompatibleRange<value_type> _Range>
flat_multimap(from_range_t __fr,_Range && __rg)302*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t __fr, _Range&& __rg)
303*700637cbSDimitry Andric       : flat_multimap(__fr, std::forward<_Range>(__rg), key_compare()) {}
304*700637cbSDimitry Andric 
305*700637cbSDimitry Andric   template <_ContainerCompatibleRange<value_type> _Range, class _Allocator>
306*700637cbSDimitry Andric     requires __allocator_ctor_constraint<_Allocator>
flat_multimap(from_range_t,_Range && __rg,const _Allocator & __alloc)307*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t, _Range&& __rg, const _Allocator& __alloc)
308*700637cbSDimitry Andric       : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) {
309*700637cbSDimitry Andric     insert_range(std::forward<_Range>(__rg));
310*700637cbSDimitry Andric   }
311*700637cbSDimitry Andric 
312*700637cbSDimitry Andric   template <_ContainerCompatibleRange<value_type> _Range>
flat_multimap(from_range_t,_Range && __rg,const key_compare & __comp)313*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t, _Range&& __rg, const key_compare& __comp) : flat_multimap(__comp) {
314*700637cbSDimitry Andric     insert_range(std::forward<_Range>(__rg));
315*700637cbSDimitry Andric   }
316*700637cbSDimitry Andric 
317*700637cbSDimitry Andric   template <_ContainerCompatibleRange<value_type> _Range, class _Allocator>
318*700637cbSDimitry Andric     requires __allocator_ctor_constraint<_Allocator>
flat_multimap(from_range_t,_Range && __rg,const key_compare & __comp,const _Allocator & __alloc)319*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc)
320*700637cbSDimitry Andric       : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {
321*700637cbSDimitry Andric     insert_range(std::forward<_Range>(__rg));
322*700637cbSDimitry Andric   }
323*700637cbSDimitry Andric 
324*700637cbSDimitry Andric   template <class _InputIterator>
325*700637cbSDimitry Andric     requires __has_input_iterator_category<_InputIterator>::value
326*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(
327*700637cbSDimitry Andric       sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare())
__containers_()328*700637cbSDimitry Andric       : __containers_(), __compare_(__comp) {
329*700637cbSDimitry Andric     insert(sorted_equivalent, __first, __last);
330*700637cbSDimitry Andric   }
331*700637cbSDimitry Andric   template <class _InputIterator, class _Allocator>
requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)332*700637cbSDimitry Andric     requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)
333*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
334*700637cbSDimitry Andric   flat_multimap(sorted_equivalent_t,
335*700637cbSDimitry Andric                 _InputIterator __first,
336*700637cbSDimitry Andric                 _InputIterator __last,
337*700637cbSDimitry Andric                 const key_compare& __comp,
338*700637cbSDimitry Andric                 const _Allocator& __alloc)
339*700637cbSDimitry Andric       : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {
340*700637cbSDimitry Andric     insert(sorted_equivalent, __first, __last);
341*700637cbSDimitry Andric   }
342*700637cbSDimitry Andric 
343*700637cbSDimitry Andric   template <class _InputIterator, class _Allocator>
requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)344*700637cbSDimitry Andric     requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)
345*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
346*700637cbSDimitry Andric   flat_multimap(sorted_equivalent_t, _InputIterator __first, _InputIterator __last, const _Allocator& __alloc)
347*700637cbSDimitry Andric       : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) {
348*700637cbSDimitry Andric     insert(sorted_equivalent, __first, __last);
349*700637cbSDimitry Andric   }
350*700637cbSDimitry Andric 
351*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(initializer_list<value_type> __il, const key_compare& __comp = key_compare())
352*700637cbSDimitry Andric       : flat_multimap(__il.begin(), __il.end(), __comp) {}
353*700637cbSDimitry Andric 
354*700637cbSDimitry Andric   template <class _Allocator>
355*700637cbSDimitry Andric     requires __allocator_ctor_constraint<_Allocator>
356*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
flat_multimap(initializer_list<value_type> __il,const key_compare & __comp,const _Allocator & __alloc)357*700637cbSDimitry Andric   flat_multimap(initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc)
358*700637cbSDimitry Andric       : flat_multimap(__il.begin(), __il.end(), __comp, __alloc) {}
359*700637cbSDimitry Andric 
360*700637cbSDimitry Andric   template <class _Allocator>
361*700637cbSDimitry Andric     requires __allocator_ctor_constraint<_Allocator>
flat_multimap(initializer_list<value_type> __il,const _Allocator & __alloc)362*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(initializer_list<value_type> __il, const _Allocator& __alloc)
363*700637cbSDimitry Andric       : flat_multimap(__il.begin(), __il.end(), __alloc) {}
364*700637cbSDimitry Andric 
365*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
366*700637cbSDimitry Andric   flat_multimap(sorted_equivalent_t, initializer_list<value_type> __il, const key_compare& __comp = key_compare())
367*700637cbSDimitry Andric       : flat_multimap(sorted_equivalent, __il.begin(), __il.end(), __comp) {}
368*700637cbSDimitry Andric 
369*700637cbSDimitry Andric   template <class _Allocator>
370*700637cbSDimitry Andric     requires __allocator_ctor_constraint<_Allocator>
flat_multimap(sorted_equivalent_t,initializer_list<value_type> __il,const key_compare & __comp,const _Allocator & __alloc)371*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(
372*700637cbSDimitry Andric       sorted_equivalent_t, initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc)
373*700637cbSDimitry Andric       : flat_multimap(sorted_equivalent, __il.begin(), __il.end(), __comp, __alloc) {}
374*700637cbSDimitry Andric 
375*700637cbSDimitry Andric   template <class _Allocator>
376*700637cbSDimitry Andric     requires __allocator_ctor_constraint<_Allocator>
flat_multimap(sorted_equivalent_t,initializer_list<value_type> __il,const _Allocator & __alloc)377*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(sorted_equivalent_t, initializer_list<value_type> __il, const _Allocator& __alloc)
378*700637cbSDimitry Andric       : flat_multimap(sorted_equivalent, __il.begin(), __il.end(), __alloc) {}
379*700637cbSDimitry Andric 
380*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap& operator=(initializer_list<value_type> __il) {
381*700637cbSDimitry Andric     clear();
382*700637cbSDimitry Andric     insert(__il);
383*700637cbSDimitry Andric     return *this;
384*700637cbSDimitry Andric   }
385*700637cbSDimitry Andric 
386*700637cbSDimitry Andric   // copy/move assignment are not specified in the spec (defaulted)
387*700637cbSDimitry Andric   // but move assignment can potentially leave moved from object in an inconsistent
388*700637cbSDimitry Andric   // state if an exception is thrown
389*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap& operator=(const flat_multimap&) = default;
390*700637cbSDimitry Andric 
noexcept(is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_MappedContainer> && is_nothrow_move_assignable_v<_Compare>)391*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap& operator=(flat_multimap&& __other) noexcept(
392*700637cbSDimitry Andric       is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_MappedContainer> &&
393*700637cbSDimitry Andric       is_nothrow_move_assignable_v<_Compare>) {
394*700637cbSDimitry Andric     auto __clear_other_guard = std::__make_scope_guard([&]() noexcept { __other.clear() /* noexcept */; });
395*700637cbSDimitry Andric     auto __clear_self_guard  = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
396*700637cbSDimitry Andric     __containers_            = std::move(__other.__containers_);
397*700637cbSDimitry Andric     __compare_               = std::move(__other.__compare_);
398*700637cbSDimitry Andric     __clear_self_guard.__complete();
399*700637cbSDimitry Andric     return *this;
400*700637cbSDimitry Andric   }
401*700637cbSDimitry Andric 
402*700637cbSDimitry Andric   // iterators
begin()403*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator begin() noexcept {
404*700637cbSDimitry Andric     return iterator(__containers_.keys.begin(), __containers_.values.begin());
405*700637cbSDimitry Andric   }
406*700637cbSDimitry Andric 
begin()407*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept {
408*700637cbSDimitry Andric     return const_iterator(__containers_.keys.begin(), __containers_.values.begin());
409*700637cbSDimitry Andric   }
410*700637cbSDimitry Andric 
end()411*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator end() noexcept {
412*700637cbSDimitry Andric     return iterator(__containers_.keys.end(), __containers_.values.end());
413*700637cbSDimitry Andric   }
414*700637cbSDimitry Andric 
end()415*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept {
416*700637cbSDimitry Andric     return const_iterator(__containers_.keys.end(), __containers_.values.end());
417*700637cbSDimitry Andric   }
418*700637cbSDimitry Andric 
rbegin()419*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
rbegin()420*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
rend()421*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
rend()422*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
423*700637cbSDimitry Andric 
cbegin()424*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return begin(); }
cend()425*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return end(); }
crbegin()426*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
crend()427*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
428*700637cbSDimitry Andric 
429*700637cbSDimitry Andric   // [flat.map.capacity], capacity
empty()430*700637cbSDimitry Andric   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __containers_.keys.empty(); }
431*700637cbSDimitry Andric 
size()432*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI size_type size() const noexcept { return __containers_.keys.size(); }
433*700637cbSDimitry Andric 
max_size()434*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI size_type max_size() const noexcept {
435*700637cbSDimitry Andric     return std::min<size_type>(__containers_.keys.max_size(), __containers_.values.max_size());
436*700637cbSDimitry Andric   }
437*700637cbSDimitry Andric 
438*700637cbSDimitry Andric   // [flat.map.modifiers], modifiers
439*700637cbSDimitry Andric   template <class... _Args>
440*700637cbSDimitry Andric     requires is_constructible_v<pair<key_type, mapped_type>, _Args...> && is_move_constructible_v<key_type> &&
441*700637cbSDimitry Andric              is_move_constructible_v<mapped_type>
emplace(_Args &&...__args)442*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator emplace(_Args&&... __args) {
443*700637cbSDimitry Andric     std::pair<key_type, mapped_type> __pair(std::forward<_Args>(__args)...);
444*700637cbSDimitry Andric     auto __key_it    = std::upper_bound(__containers_.keys.begin(), __containers_.keys.end(), __pair.first, __compare_);
445*700637cbSDimitry Andric     auto __mapped_it = __corresponding_mapped_it(*this, __key_it);
446*700637cbSDimitry Andric 
447*700637cbSDimitry Andric     return __flat_map_utils::__emplace_exact_pos(
448*700637cbSDimitry Andric         *this, std::move(__key_it), std::move(__mapped_it), std::move(__pair.first), std::move(__pair.second));
449*700637cbSDimitry Andric   }
450*700637cbSDimitry Andric 
451*700637cbSDimitry Andric   template <class... _Args>
452*700637cbSDimitry Andric     requires is_constructible_v<pair<key_type, mapped_type>, _Args...>
emplace_hint(const_iterator __hint,_Args &&...__args)453*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __hint, _Args&&... __args) {
454*700637cbSDimitry Andric     std::pair<key_type, mapped_type> __pair(std::forward<_Args>(__args)...);
455*700637cbSDimitry Andric 
456*700637cbSDimitry Andric     auto __prev_larger  = __hint != cbegin() && __compare_(__pair.first, (__hint - 1)->first);
457*700637cbSDimitry Andric     auto __next_smaller = __hint != cend() && __compare_(__hint->first, __pair.first);
458*700637cbSDimitry Andric 
459*700637cbSDimitry Andric     auto __hint_distance = __hint.__key_iter_ - __containers_.keys.cbegin();
460*700637cbSDimitry Andric     auto __key_iter      = __containers_.keys.begin() + __hint_distance;
461*700637cbSDimitry Andric     auto __mapped_iter   = __containers_.values.begin() + __hint_distance;
462*700637cbSDimitry Andric 
463*700637cbSDimitry Andric     if (!__prev_larger && !__next_smaller) [[likely]] {
464*700637cbSDimitry Andric       // hint correct, just use exact hint iterators
465*700637cbSDimitry Andric     } else if (__prev_larger && !__next_smaller) {
466*700637cbSDimitry Andric       // the hint position is more to the right than the key should have been.
467*700637cbSDimitry Andric       // we want to emplace the element to a position as right as possible
468*700637cbSDimitry Andric       // e.g. Insert new element "2" in the following range
469*700637cbSDimitry Andric       // 1, 1, 2, 2, 2, 3, 4, 6
470*700637cbSDimitry Andric       //                   ^
471*700637cbSDimitry Andric       //                   |
472*700637cbSDimitry Andric       //                  hint
473*700637cbSDimitry Andric       // We want to insert "2" after the last existing "2"
474*700637cbSDimitry Andric       __key_iter    = std::upper_bound(__containers_.keys.begin(), __key_iter, __pair.first, __compare_);
475*700637cbSDimitry Andric       __mapped_iter = __corresponding_mapped_it(*this, __key_iter);
476*700637cbSDimitry Andric     } else {
477*700637cbSDimitry Andric       _LIBCPP_ASSERT_INTERNAL(!__prev_larger && __next_smaller, "this means that the multimap is not sorted");
478*700637cbSDimitry Andric 
479*700637cbSDimitry Andric       // the hint position is more to the left than the key should have been.
480*700637cbSDimitry Andric       // we want to emplace the element to a position as left as possible
481*700637cbSDimitry Andric       //  1, 1, 2, 2, 2, 3, 4, 6
482*700637cbSDimitry Andric       //  ^
483*700637cbSDimitry Andric       //  |
484*700637cbSDimitry Andric       // hint
485*700637cbSDimitry Andric       // We want to insert "2" before the first existing "2"
486*700637cbSDimitry Andric       __key_iter    = std::lower_bound(__key_iter, __containers_.keys.end(), __pair.first, __compare_);
487*700637cbSDimitry Andric       __mapped_iter = __corresponding_mapped_it(*this, __key_iter);
488*700637cbSDimitry Andric     }
489*700637cbSDimitry Andric     return __flat_map_utils::__emplace_exact_pos(
490*700637cbSDimitry Andric         *this, __key_iter, __mapped_iter, std::move(__pair.first), std::move(__pair.second));
491*700637cbSDimitry Andric   }
492*700637cbSDimitry Andric 
insert(const value_type & __x)493*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return emplace(__x); }
494*700637cbSDimitry Andric 
insert(value_type && __x)495*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator insert(value_type&& __x) { return emplace(std::move(__x)); }
496*700637cbSDimitry Andric 
insert(const_iterator __hint,const value_type & __x)497*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, const value_type& __x) {
498*700637cbSDimitry Andric     return emplace_hint(__hint, __x);
499*700637cbSDimitry Andric   }
500*700637cbSDimitry Andric 
insert(const_iterator __hint,value_type && __x)501*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, value_type&& __x) {
502*700637cbSDimitry Andric     return emplace_hint(__hint, std::move(__x));
503*700637cbSDimitry Andric   }
504*700637cbSDimitry Andric 
505*700637cbSDimitry Andric   template <class _PairLike>
506*700637cbSDimitry Andric     requires is_constructible_v<pair<key_type, mapped_type>, _PairLike>
insert(_PairLike && __x)507*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator insert(_PairLike&& __x) {
508*700637cbSDimitry Andric     return emplace(std::forward<_PairLike>(__x));
509*700637cbSDimitry Andric   }
510*700637cbSDimitry Andric 
511*700637cbSDimitry Andric   template <class _PairLike>
512*700637cbSDimitry Andric     requires is_constructible_v<pair<key_type, mapped_type>, _PairLike>
insert(const_iterator __hint,_PairLike && __x)513*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, _PairLike&& __x) {
514*700637cbSDimitry Andric     return emplace_hint(__hint, std::forward<_PairLike>(__x));
515*700637cbSDimitry Andric   }
516*700637cbSDimitry Andric 
517*700637cbSDimitry Andric   template <class _InputIterator>
518*700637cbSDimitry Andric     requires __has_input_iterator_category<_InputIterator>::value
insert(_InputIterator __first,_InputIterator __last)519*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) {
520*700637cbSDimitry Andric     if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) {
521*700637cbSDimitry Andric       __reserve(__last - __first);
522*700637cbSDimitry Andric     }
523*700637cbSDimitry Andric     __append_sort_merge</*WasSorted = */ false>(std::move(__first), std::move(__last));
524*700637cbSDimitry Andric   }
525*700637cbSDimitry Andric 
526*700637cbSDimitry Andric   template <class _InputIterator>
527*700637cbSDimitry Andric     requires __has_input_iterator_category<_InputIterator>::value
insert(sorted_equivalent_t,_InputIterator __first,_InputIterator __last)528*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, _InputIterator __first, _InputIterator __last) {
529*700637cbSDimitry Andric     if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) {
530*700637cbSDimitry Andric       __reserve(__last - __first);
531*700637cbSDimitry Andric     }
532*700637cbSDimitry Andric 
533*700637cbSDimitry Andric     __append_sort_merge</*WasSorted = */ true>(std::move(__first), std::move(__last));
534*700637cbSDimitry Andric   }
535*700637cbSDimitry Andric 
536*700637cbSDimitry Andric   template <_ContainerCompatibleRange<value_type> _Range>
insert_range(_Range && __range)537*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) {
538*700637cbSDimitry Andric     if constexpr (ranges::sized_range<_Range>) {
539*700637cbSDimitry Andric       __reserve(ranges::size(__range));
540*700637cbSDimitry Andric     }
541*700637cbSDimitry Andric 
542*700637cbSDimitry Andric     __append_sort_merge</*WasSorted = */ false>(ranges::begin(__range), ranges::end(__range));
543*700637cbSDimitry Andric   }
544*700637cbSDimitry Andric 
insert(initializer_list<value_type> __il)545*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void insert(initializer_list<value_type> __il) { insert(__il.begin(), __il.end()); }
546*700637cbSDimitry Andric 
insert(sorted_equivalent_t,initializer_list<value_type> __il)547*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void insert(sorted_equivalent_t, initializer_list<value_type> __il) {
548*700637cbSDimitry Andric     insert(sorted_equivalent, __il.begin(), __il.end());
549*700637cbSDimitry Andric   }
550*700637cbSDimitry Andric 
extract()551*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI containers extract() && {
552*700637cbSDimitry Andric     auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; });
553*700637cbSDimitry Andric     auto __ret   = std::move(__containers_);
554*700637cbSDimitry Andric     return __ret;
555*700637cbSDimitry Andric   }
556*700637cbSDimitry Andric 
replace(key_container_type && __key_cont,mapped_container_type && __mapped_cont)557*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void replace(key_container_type&& __key_cont, mapped_container_type&& __mapped_cont) {
558*700637cbSDimitry Andric     _LIBCPP_ASSERT_VALID_INPUT_RANGE(
559*700637cbSDimitry Andric         __key_cont.size() == __mapped_cont.size(), "flat_multimap keys and mapped containers have different size");
560*700637cbSDimitry Andric 
561*700637cbSDimitry Andric     _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__is_sorted(__key_cont), "Key container is not sorted");
562*700637cbSDimitry Andric     auto __guard         = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
563*700637cbSDimitry Andric     __containers_.keys   = std::move(__key_cont);
564*700637cbSDimitry Andric     __containers_.values = std::move(__mapped_cont);
565*700637cbSDimitry Andric     __guard.__complete();
566*700637cbSDimitry Andric   }
567*700637cbSDimitry Andric 
erase(iterator __position)568*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator erase(iterator __position) {
569*700637cbSDimitry Andric     return __erase(__position.__key_iter_, __position.__mapped_iter_);
570*700637cbSDimitry Andric   }
571*700637cbSDimitry Andric 
erase(const_iterator __position)572*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __position) {
573*700637cbSDimitry Andric     return __erase(__position.__key_iter_, __position.__mapped_iter_);
574*700637cbSDimitry Andric   }
575*700637cbSDimitry Andric 
erase(const key_type & __x)576*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __x) {
577*700637cbSDimitry Andric     auto [__first, __last] = equal_range(__x);
578*700637cbSDimitry Andric     auto __res             = __last - __first;
579*700637cbSDimitry Andric     erase(__first, __last);
580*700637cbSDimitry Andric     return __res;
581*700637cbSDimitry Andric   }
582*700637cbSDimitry Andric 
583*700637cbSDimitry Andric   template <class _Kp>
584*700637cbSDimitry Andric     requires(__is_compare_transparent && !is_convertible_v<_Kp &&, iterator> &&
585*700637cbSDimitry Andric              !is_convertible_v<_Kp &&, const_iterator>)
erase(_Kp && __x)586*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI size_type erase(_Kp&& __x) {
587*700637cbSDimitry Andric     auto [__first, __last] = equal_range(__x);
588*700637cbSDimitry Andric     auto __res             = __last - __first;
589*700637cbSDimitry Andric     erase(__first, __last);
590*700637cbSDimitry Andric     return __res;
591*700637cbSDimitry Andric   }
592*700637cbSDimitry Andric 
erase(const_iterator __first,const_iterator __last)593*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) {
594*700637cbSDimitry Andric     auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
595*700637cbSDimitry Andric     auto __key_it     = __containers_.keys.erase(__first.__key_iter_, __last.__key_iter_);
596*700637cbSDimitry Andric     auto __mapped_it  = __containers_.values.erase(__first.__mapped_iter_, __last.__mapped_iter_);
597*700637cbSDimitry Andric     __on_failure.__complete();
598*700637cbSDimitry Andric     return iterator(std::move(__key_it), std::move(__mapped_it));
599*700637cbSDimitry Andric   }
600*700637cbSDimitry Andric 
swap(flat_multimap & __y)601*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void swap(flat_multimap& __y) noexcept {
602*700637cbSDimitry Andric     // warning: The spec has unconditional noexcept, which means that
603*700637cbSDimitry Andric     // if any of the following functions throw an exception,
604*700637cbSDimitry Andric     // std::terminate will be called
605*700637cbSDimitry Andric     ranges::swap(__compare_, __y.__compare_);
606*700637cbSDimitry Andric     ranges::swap(__containers_.keys, __y.__containers_.keys);
607*700637cbSDimitry Andric     ranges::swap(__containers_.values, __y.__containers_.values);
608*700637cbSDimitry Andric   }
609*700637cbSDimitry Andric 
clear()610*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void clear() noexcept {
611*700637cbSDimitry Andric     __containers_.keys.clear();
612*700637cbSDimitry Andric     __containers_.values.clear();
613*700637cbSDimitry Andric   }
614*700637cbSDimitry Andric 
615*700637cbSDimitry Andric   // observers
key_comp()616*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __compare_; }
value_comp()617*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return value_compare(__compare_); }
618*700637cbSDimitry Andric 
keys()619*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const key_container_type& keys() const noexcept { return __containers_.keys; }
values()620*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const mapped_container_type& values() const noexcept { return __containers_.values; }
621*700637cbSDimitry Andric 
622*700637cbSDimitry Andric   // map operations
find(const key_type & __x)623*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __x) { return __find_impl(*this, __x); }
624*700637cbSDimitry Andric 
find(const key_type & __x)625*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); }
626*700637cbSDimitry Andric 
627*700637cbSDimitry Andric   template <class _Kp>
628*700637cbSDimitry Andric     requires __is_compare_transparent
find(const _Kp & __x)629*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator find(const _Kp& __x) {
630*700637cbSDimitry Andric     return __find_impl(*this, __x);
631*700637cbSDimitry Andric   }
632*700637cbSDimitry Andric 
633*700637cbSDimitry Andric   template <class _Kp>
634*700637cbSDimitry Andric     requires __is_compare_transparent
find(const _Kp & __x)635*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Kp& __x) const {
636*700637cbSDimitry Andric     return __find_impl(*this, __x);
637*700637cbSDimitry Andric   }
638*700637cbSDimitry Andric 
count(const key_type & __x)639*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __x) const {
640*700637cbSDimitry Andric     auto [__first, __last] = equal_range(__x);
641*700637cbSDimitry Andric     return __last - __first;
642*700637cbSDimitry Andric   }
643*700637cbSDimitry Andric 
644*700637cbSDimitry Andric   template <class _Kp>
645*700637cbSDimitry Andric     requires __is_compare_transparent
count(const _Kp & __x)646*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI size_type count(const _Kp& __x) const {
647*700637cbSDimitry Andric     auto [__first, __last] = equal_range(__x);
648*700637cbSDimitry Andric     return __last - __first;
649*700637cbSDimitry Andric   }
650*700637cbSDimitry Andric 
contains(const key_type & __x)651*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __x) const { return find(__x) != end(); }
652*700637cbSDimitry Andric 
653*700637cbSDimitry Andric   template <class _Kp>
654*700637cbSDimitry Andric     requires __is_compare_transparent
contains(const _Kp & __x)655*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool contains(const _Kp& __x) const {
656*700637cbSDimitry Andric     return find(__x) != end();
657*700637cbSDimitry Andric   }
658*700637cbSDimitry Andric 
lower_bound(const key_type & __x)659*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __x) { return __lower_bound<iterator>(*this, __x); }
660*700637cbSDimitry Andric 
lower_bound(const key_type & __x)661*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __x) const {
662*700637cbSDimitry Andric     return __lower_bound<const_iterator>(*this, __x);
663*700637cbSDimitry Andric   }
664*700637cbSDimitry Andric 
665*700637cbSDimitry Andric   template <class _Kp>
666*700637cbSDimitry Andric     requires __is_compare_transparent
lower_bound(const _Kp & __x)667*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Kp& __x) {
668*700637cbSDimitry Andric     return __lower_bound<iterator>(*this, __x);
669*700637cbSDimitry Andric   }
670*700637cbSDimitry Andric 
671*700637cbSDimitry Andric   template <class _Kp>
672*700637cbSDimitry Andric     requires __is_compare_transparent
lower_bound(const _Kp & __x)673*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Kp& __x) const {
674*700637cbSDimitry Andric     return __lower_bound<const_iterator>(*this, __x);
675*700637cbSDimitry Andric   }
676*700637cbSDimitry Andric 
upper_bound(const key_type & __x)677*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __x) { return __upper_bound<iterator>(*this, __x); }
678*700637cbSDimitry Andric 
upper_bound(const key_type & __x)679*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __x) const {
680*700637cbSDimitry Andric     return __upper_bound<const_iterator>(*this, __x);
681*700637cbSDimitry Andric   }
682*700637cbSDimitry Andric 
683*700637cbSDimitry Andric   template <class _Kp>
684*700637cbSDimitry Andric     requires __is_compare_transparent
upper_bound(const _Kp & __x)685*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _Kp& __x) {
686*700637cbSDimitry Andric     return __upper_bound<iterator>(*this, __x);
687*700637cbSDimitry Andric   }
688*700637cbSDimitry Andric 
689*700637cbSDimitry Andric   template <class _Kp>
690*700637cbSDimitry Andric     requires __is_compare_transparent
upper_bound(const _Kp & __x)691*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Kp& __x) const {
692*700637cbSDimitry Andric     return __upper_bound<const_iterator>(*this, __x);
693*700637cbSDimitry Andric   }
694*700637cbSDimitry Andric 
equal_range(const key_type & __x)695*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __x) {
696*700637cbSDimitry Andric     return __equal_range_impl(*this, __x);
697*700637cbSDimitry Andric   }
698*700637cbSDimitry Andric 
equal_range(const key_type & __x)699*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __x) const {
700*700637cbSDimitry Andric     return __equal_range_impl(*this, __x);
701*700637cbSDimitry Andric   }
702*700637cbSDimitry Andric 
703*700637cbSDimitry Andric   template <class _Kp>
704*700637cbSDimitry Andric     requires __is_compare_transparent
equal_range(const _Kp & __x)705*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _Kp& __x) {
706*700637cbSDimitry Andric     return __equal_range_impl(*this, __x);
707*700637cbSDimitry Andric   }
708*700637cbSDimitry Andric   template <class _Kp>
709*700637cbSDimitry Andric     requires __is_compare_transparent
equal_range(const _Kp & __x)710*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _Kp& __x) const {
711*700637cbSDimitry Andric     return __equal_range_impl(*this, __x);
712*700637cbSDimitry Andric   }
713*700637cbSDimitry Andric 
714*700637cbSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI bool operator==(const flat_multimap& __x, const flat_multimap& __y) {
715*700637cbSDimitry Andric     return ranges::equal(__x, __y);
716*700637cbSDimitry Andric   }
717*700637cbSDimitry Andric 
718*700637cbSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI auto operator<=>(const flat_multimap& __x, const flat_multimap& __y) {
719*700637cbSDimitry Andric     return std::lexicographical_compare_three_way(
720*700637cbSDimitry Andric         __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
721*700637cbSDimitry Andric   }
722*700637cbSDimitry Andric 
swap(flat_multimap & __x,flat_multimap & __y)723*700637cbSDimitry Andric   friend _LIBCPP_HIDE_FROM_ABI void swap(flat_multimap& __x, flat_multimap& __y) noexcept { __x.swap(__y); }
724*700637cbSDimitry Andric 
725*700637cbSDimitry Andric private:
726*700637cbSDimitry Andric   struct __ctor_uses_allocator_tag {
727*700637cbSDimitry Andric     explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_tag() = default;
728*700637cbSDimitry Andric   };
729*700637cbSDimitry Andric   struct __ctor_uses_allocator_empty_tag {
730*700637cbSDimitry Andric     explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_empty_tag() = default;
731*700637cbSDimitry Andric   };
732*700637cbSDimitry Andric 
733*700637cbSDimitry Andric   template <class _Allocator, class _KeyCont, class _MappedCont, class... _CompArg>
734*700637cbSDimitry Andric     requires __allocator_ctor_constraint<_Allocator>
735*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI
flat_multimap(__ctor_uses_allocator_tag,const _Allocator & __alloc,_KeyCont && __key_cont,_MappedCont && __mapped_cont,_CompArg &&...__comp)736*700637cbSDimitry Andric   flat_multimap(__ctor_uses_allocator_tag,
737*700637cbSDimitry Andric                 const _Allocator& __alloc,
738*700637cbSDimitry Andric                 _KeyCont&& __key_cont,
739*700637cbSDimitry Andric                 _MappedCont&& __mapped_cont,
740*700637cbSDimitry Andric                 _CompArg&&... __comp)
741*700637cbSDimitry Andric       : __containers_{.keys = std::make_obj_using_allocator<key_container_type>(
742*700637cbSDimitry Andric                           __alloc, std::forward<_KeyCont>(__key_cont)),
743*700637cbSDimitry Andric                       .values = std::make_obj_using_allocator<mapped_container_type>(
744*700637cbSDimitry Andric                           __alloc, std::forward<_MappedCont>(__mapped_cont))},
745*700637cbSDimitry Andric         __compare_(std::forward<_CompArg>(__comp)...) {}
746*700637cbSDimitry Andric 
747*700637cbSDimitry Andric   template <class _Allocator, class... _CompArg>
748*700637cbSDimitry Andric     requires __allocator_ctor_constraint<_Allocator>
flat_multimap(__ctor_uses_allocator_empty_tag,const _Allocator & __alloc,_CompArg &&...__comp)749*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI flat_multimap(__ctor_uses_allocator_empty_tag, const _Allocator& __alloc, _CompArg&&... __comp)
750*700637cbSDimitry Andric       : __containers_{.keys   = std::make_obj_using_allocator<key_container_type>(__alloc),
751*700637cbSDimitry Andric                       .values = std::make_obj_using_allocator<mapped_container_type>(__alloc)},
752*700637cbSDimitry Andric         __compare_(std::forward<_CompArg>(__comp)...) {}
753*700637cbSDimitry Andric 
__is_sorted(auto && __key_container)754*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI bool __is_sorted(auto&& __key_container) const {
755*700637cbSDimitry Andric     return ranges::is_sorted(__key_container, __compare_);
756*700637cbSDimitry Andric   }
757*700637cbSDimitry Andric 
__sort()758*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void __sort() {
759*700637cbSDimitry Andric     auto __zv = ranges::views::zip(__containers_.keys, __containers_.values);
760*700637cbSDimitry Andric     ranges::sort(__zv, __compare_, [](const auto& __p) -> decltype(auto) { return std::get<0>(__p); });
761*700637cbSDimitry Andric   }
762*700637cbSDimitry Andric 
763*700637cbSDimitry Andric   template <class _Self, class _KeyIter>
__corresponding_mapped_it(_Self && __self,_KeyIter && __key_iter)764*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static auto __corresponding_mapped_it(_Self&& __self, _KeyIter&& __key_iter) {
765*700637cbSDimitry Andric     return __self.__containers_.values.begin() +
766*700637cbSDimitry Andric            static_cast<ranges::range_difference_t<mapped_container_type>>(
767*700637cbSDimitry Andric                ranges::distance(__self.__containers_.keys.begin(), __key_iter));
768*700637cbSDimitry Andric   }
769*700637cbSDimitry Andric 
770*700637cbSDimitry Andric   template <bool _WasSorted, class _InputIterator, class _Sentinel>
__append_sort_merge(_InputIterator __first,_Sentinel __last)771*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void __append_sort_merge(_InputIterator __first, _Sentinel __last) {
772*700637cbSDimitry Andric     auto __on_failure     = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
773*700637cbSDimitry Andric     size_t __num_appended = __flat_map_utils::__append(*this, std::move(__first), std::move(__last));
774*700637cbSDimitry Andric     if (__num_appended != 0) {
775*700637cbSDimitry Andric       auto __zv                  = ranges::views::zip(__containers_.keys, __containers_.values);
776*700637cbSDimitry Andric       auto __append_start_offset = __containers_.keys.size() - __num_appended;
777*700637cbSDimitry Andric       auto __end                 = __zv.end();
778*700637cbSDimitry Andric       auto __compare_key         = [this](const auto& __p1, const auto& __p2) {
779*700637cbSDimitry Andric         return __compare_(std::get<0>(__p1), std::get<0>(__p2));
780*700637cbSDimitry Andric       };
781*700637cbSDimitry Andric       if constexpr (!_WasSorted) {
782*700637cbSDimitry Andric         ranges::sort(__zv.begin() + __append_start_offset, __end, __compare_key);
783*700637cbSDimitry Andric       } else {
784*700637cbSDimitry Andric         _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
785*700637cbSDimitry Andric             __is_sorted(__containers_.keys | ranges::views::drop(__append_start_offset)),
786*700637cbSDimitry Andric             "Key container is not sorted");
787*700637cbSDimitry Andric       }
788*700637cbSDimitry Andric       ranges::inplace_merge(__zv.begin(), __zv.begin() + __append_start_offset, __end, __compare_key);
789*700637cbSDimitry Andric     }
790*700637cbSDimitry Andric     __on_failure.__complete();
791*700637cbSDimitry Andric   }
792*700637cbSDimitry Andric 
793*700637cbSDimitry Andric   template <class _Self, class _Kp>
__find_impl(_Self && __self,const _Kp & __key)794*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static auto __find_impl(_Self&& __self, const _Kp& __key) {
795*700637cbSDimitry Andric     auto __it   = __self.lower_bound(__key);
796*700637cbSDimitry Andric     auto __last = __self.end();
797*700637cbSDimitry Andric     if (__it == __last || __self.__compare_(__key, __it->first)) {
798*700637cbSDimitry Andric       return __last;
799*700637cbSDimitry Andric     }
800*700637cbSDimitry Andric     return __it;
801*700637cbSDimitry Andric   }
802*700637cbSDimitry Andric 
803*700637cbSDimitry Andric   template <class _Self, class _Kp>
__equal_range_impl(_Self && __self,const _Kp & __key)804*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static auto __equal_range_impl(_Self&& __self, const _Kp& __key) {
805*700637cbSDimitry Andric     auto [__key_first, __key_last] =
806*700637cbSDimitry Andric         std::equal_range(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __key, __self.__compare_);
807*700637cbSDimitry Andric 
808*700637cbSDimitry Andric     using __iterator_type = ranges::iterator_t<decltype(__self)>;
809*700637cbSDimitry Andric     return std::make_pair(__iterator_type(__key_first, __corresponding_mapped_it(__self, __key_first)),
810*700637cbSDimitry Andric                           __iterator_type(__key_last, __corresponding_mapped_it(__self, __key_last)));
811*700637cbSDimitry Andric   }
812*700637cbSDimitry Andric 
813*700637cbSDimitry Andric   template <class _Res, class _Self, class _Kp>
__lower_bound(_Self && __self,_Kp & __x)814*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _Res __lower_bound(_Self&& __self, _Kp& __x) {
815*700637cbSDimitry Andric     auto __key_iter =
816*700637cbSDimitry Andric         std::lower_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __x, __self.__compare_);
817*700637cbSDimitry Andric     auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter);
818*700637cbSDimitry Andric     return _Res(std::move(__key_iter), std::move(__mapped_iter));
819*700637cbSDimitry Andric   }
820*700637cbSDimitry Andric 
821*700637cbSDimitry Andric   template <class _Res, class _Self, class _Kp>
__upper_bound(_Self && __self,_Kp & __x)822*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI static _Res __upper_bound(_Self&& __self, _Kp& __x) {
823*700637cbSDimitry Andric     auto __key_iter =
824*700637cbSDimitry Andric         std::upper_bound(__self.__containers_.keys.begin(), __self.__containers_.keys.end(), __x, __self.__compare_);
825*700637cbSDimitry Andric     auto __mapped_iter = __corresponding_mapped_it(__self, __key_iter);
826*700637cbSDimitry Andric     return _Res(std::move(__key_iter), std::move(__mapped_iter));
827*700637cbSDimitry Andric   }
828*700637cbSDimitry Andric 
__reserve(size_t __size)829*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) {
830*700637cbSDimitry Andric     if constexpr (__container_traits<_KeyContainer>::__reservable) {
831*700637cbSDimitry Andric       __containers_.keys.reserve(__size);
832*700637cbSDimitry Andric     }
833*700637cbSDimitry Andric 
834*700637cbSDimitry Andric     if constexpr (__container_traits<_MappedContainer>::__reservable) {
835*700637cbSDimitry Andric       __containers_.values.reserve(__size);
836*700637cbSDimitry Andric     }
837*700637cbSDimitry Andric   }
838*700637cbSDimitry Andric 
839*700637cbSDimitry Andric   template <class _KIter, class _MIter>
__erase(_KIter __key_iter_to_remove,_MIter __mapped_iter_to_remove)840*700637cbSDimitry Andric   _LIBCPP_HIDE_FROM_ABI iterator __erase(_KIter __key_iter_to_remove, _MIter __mapped_iter_to_remove) {
841*700637cbSDimitry Andric     auto __on_failure  = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
842*700637cbSDimitry Andric     auto __key_iter    = __containers_.keys.erase(__key_iter_to_remove);
843*700637cbSDimitry Andric     auto __mapped_iter = __containers_.values.erase(__mapped_iter_to_remove);
844*700637cbSDimitry Andric     __on_failure.__complete();
845*700637cbSDimitry Andric     return iterator(std::move(__key_iter), std::move(__mapped_iter));
846*700637cbSDimitry Andric   }
847*700637cbSDimitry Andric 
848*700637cbSDimitry Andric   template <class _Key2, class _Tp2, class _Compare2, class _KeyContainer2, class _MappedContainer2, class _Predicate>
849*700637cbSDimitry Andric   friend typename flat_multimap<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>::size_type
850*700637cbSDimitry Andric   erase_if(flat_multimap<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>&, _Predicate);
851*700637cbSDimitry Andric 
852*700637cbSDimitry Andric   friend __flat_map_utils;
853*700637cbSDimitry Andric 
854*700637cbSDimitry Andric   containers __containers_;
855*700637cbSDimitry Andric   _LIBCPP_NO_UNIQUE_ADDRESS key_compare __compare_;
856*700637cbSDimitry Andric 
857*700637cbSDimitry Andric   struct __key_equiv {
__key_equiv__key_equiv858*700637cbSDimitry Andric     _LIBCPP_HIDE_FROM_ABI __key_equiv(key_compare __c) : __comp_(__c) {}
operator__key_equiv859*700637cbSDimitry Andric     _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const {
860*700637cbSDimitry Andric       return !__comp_(std::get<0>(__x), std::get<0>(__y)) && !__comp_(std::get<0>(__y), std::get<0>(__x));
861*700637cbSDimitry Andric     }
862*700637cbSDimitry Andric     key_compare __comp_;
863*700637cbSDimitry Andric   };
864*700637cbSDimitry Andric };
865*700637cbSDimitry Andric 
866*700637cbSDimitry Andric template <class _KeyContainer, class _MappedContainer, class _Compare = less<typename _KeyContainer::value_type>>
867*700637cbSDimitry Andric   requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
868*700637cbSDimitry Andric            !__is_allocator<_MappedContainer>::value &&
869*700637cbSDimitry Andric            is_invocable_v<const _Compare&,
870*700637cbSDimitry Andric                           const typename _KeyContainer::value_type&,
871*700637cbSDimitry Andric                           const typename _KeyContainer::value_type&>)
872*700637cbSDimitry Andric flat_multimap(_KeyContainer, _MappedContainer, _Compare = _Compare())
873*700637cbSDimitry Andric     -> flat_multimap<typename _KeyContainer::value_type,
874*700637cbSDimitry Andric                      typename _MappedContainer::value_type,
875*700637cbSDimitry Andric                      _Compare,
876*700637cbSDimitry Andric                      _KeyContainer,
877*700637cbSDimitry Andric                      _MappedContainer>;
878*700637cbSDimitry Andric 
879*700637cbSDimitry Andric template <class _KeyContainer, class _MappedContainer, class _Allocator>
880*700637cbSDimitry Andric   requires(uses_allocator_v<_KeyContainer, _Allocator> && uses_allocator_v<_MappedContainer, _Allocator> &&
881*700637cbSDimitry Andric            !__is_allocator<_KeyContainer>::value && !__is_allocator<_MappedContainer>::value)
882*700637cbSDimitry Andric flat_multimap(_KeyContainer, _MappedContainer, _Allocator)
883*700637cbSDimitry Andric     -> flat_multimap<typename _KeyContainer::value_type,
884*700637cbSDimitry Andric                      typename _MappedContainer::value_type,
885*700637cbSDimitry Andric                      less<typename _KeyContainer::value_type>,
886*700637cbSDimitry Andric                      _KeyContainer,
887*700637cbSDimitry Andric                      _MappedContainer>;
888*700637cbSDimitry Andric 
889*700637cbSDimitry Andric template <class _KeyContainer, class _MappedContainer, class _Compare, class _Allocator>
890*700637cbSDimitry Andric   requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
891*700637cbSDimitry Andric            !__is_allocator<_MappedContainer>::value && uses_allocator_v<_KeyContainer, _Allocator> &&
892*700637cbSDimitry Andric            uses_allocator_v<_MappedContainer, _Allocator> &&
893*700637cbSDimitry Andric            is_invocable_v<const _Compare&,
894*700637cbSDimitry Andric                           const typename _KeyContainer::value_type&,
895*700637cbSDimitry Andric                           const typename _KeyContainer::value_type&>)
896*700637cbSDimitry Andric flat_multimap(_KeyContainer, _MappedContainer, _Compare, _Allocator)
897*700637cbSDimitry Andric     -> flat_multimap<typename _KeyContainer::value_type,
898*700637cbSDimitry Andric                      typename _MappedContainer::value_type,
899*700637cbSDimitry Andric                      _Compare,
900*700637cbSDimitry Andric                      _KeyContainer,
901*700637cbSDimitry Andric                      _MappedContainer>;
902*700637cbSDimitry Andric 
903*700637cbSDimitry Andric template <class _KeyContainer, class _MappedContainer, class _Compare = less<typename _KeyContainer::value_type>>
904*700637cbSDimitry Andric   requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
905*700637cbSDimitry Andric            !__is_allocator<_MappedContainer>::value &&
906*700637cbSDimitry Andric            is_invocable_v<const _Compare&,
907*700637cbSDimitry Andric                           const typename _KeyContainer::value_type&,
908*700637cbSDimitry Andric                           const typename _KeyContainer::value_type&>)
909*700637cbSDimitry Andric flat_multimap(sorted_equivalent_t, _KeyContainer, _MappedContainer, _Compare = _Compare())
910*700637cbSDimitry Andric     -> flat_multimap<typename _KeyContainer::value_type,
911*700637cbSDimitry Andric                      typename _MappedContainer::value_type,
912*700637cbSDimitry Andric                      _Compare,
913*700637cbSDimitry Andric                      _KeyContainer,
914*700637cbSDimitry Andric                      _MappedContainer>;
915*700637cbSDimitry Andric 
916*700637cbSDimitry Andric template <class _KeyContainer, class _MappedContainer, class _Allocator>
917*700637cbSDimitry Andric   requires(uses_allocator_v<_KeyContainer, _Allocator> && uses_allocator_v<_MappedContainer, _Allocator> &&
918*700637cbSDimitry Andric            !__is_allocator<_KeyContainer>::value && !__is_allocator<_MappedContainer>::value)
919*700637cbSDimitry Andric flat_multimap(sorted_equivalent_t, _KeyContainer, _MappedContainer, _Allocator)
920*700637cbSDimitry Andric     -> flat_multimap<typename _KeyContainer::value_type,
921*700637cbSDimitry Andric                      typename _MappedContainer::value_type,
922*700637cbSDimitry Andric                      less<typename _KeyContainer::value_type>,
923*700637cbSDimitry Andric                      _KeyContainer,
924*700637cbSDimitry Andric                      _MappedContainer>;
925*700637cbSDimitry Andric 
926*700637cbSDimitry Andric template <class _KeyContainer, class _MappedContainer, class _Compare, class _Allocator>
927*700637cbSDimitry Andric   requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
928*700637cbSDimitry Andric            !__is_allocator<_MappedContainer>::value && uses_allocator_v<_KeyContainer, _Allocator> &&
929*700637cbSDimitry Andric            uses_allocator_v<_MappedContainer, _Allocator> &&
930*700637cbSDimitry Andric            is_invocable_v<const _Compare&,
931*700637cbSDimitry Andric                           const typename _KeyContainer::value_type&,
932*700637cbSDimitry Andric                           const typename _KeyContainer::value_type&>)
933*700637cbSDimitry Andric flat_multimap(sorted_equivalent_t, _KeyContainer, _MappedContainer, _Compare, _Allocator)
934*700637cbSDimitry Andric     -> flat_multimap<typename _KeyContainer::value_type,
935*700637cbSDimitry Andric                      typename _MappedContainer::value_type,
936*700637cbSDimitry Andric                      _Compare,
937*700637cbSDimitry Andric                      _KeyContainer,
938*700637cbSDimitry Andric                      _MappedContainer>;
939*700637cbSDimitry Andric 
940*700637cbSDimitry Andric template <class _InputIterator, class _Compare = less<__iter_key_type<_InputIterator>>>
941*700637cbSDimitry Andric   requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value)
942*700637cbSDimitry Andric flat_multimap(_InputIterator, _InputIterator, _Compare = _Compare())
943*700637cbSDimitry Andric     -> flat_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Compare>;
944*700637cbSDimitry Andric 
945*700637cbSDimitry Andric template <class _InputIterator, class _Compare = less<__iter_key_type<_InputIterator>>>
946*700637cbSDimitry Andric   requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value)
947*700637cbSDimitry Andric flat_multimap(sorted_equivalent_t, _InputIterator, _InputIterator, _Compare = _Compare())
948*700637cbSDimitry Andric     -> flat_multimap<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Compare>;
949*700637cbSDimitry Andric 
950*700637cbSDimitry Andric template <ranges::input_range _Range,
951*700637cbSDimitry Andric           class _Compare   = less<__range_key_type<_Range>>,
952*700637cbSDimitry Andric           class _Allocator = allocator<byte>,
953*700637cbSDimitry Andric           class            = __enable_if_t<!__is_allocator<_Compare>::value && __is_allocator<_Allocator>::value>>
954*700637cbSDimitry Andric flat_multimap(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) -> flat_multimap<
955*700637cbSDimitry Andric     __range_key_type<_Range>,
956*700637cbSDimitry Andric     __range_mapped_type<_Range>,
957*700637cbSDimitry Andric     _Compare,
958*700637cbSDimitry Andric     vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
959*700637cbSDimitry Andric     vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
960*700637cbSDimitry Andric 
961*700637cbSDimitry Andric template <ranges::input_range _Range, class _Allocator, class = __enable_if_t<__is_allocator<_Allocator>::value>>
962*700637cbSDimitry Andric flat_multimap(from_range_t, _Range&&, _Allocator) -> flat_multimap<
963*700637cbSDimitry Andric     __range_key_type<_Range>,
964*700637cbSDimitry Andric     __range_mapped_type<_Range>,
965*700637cbSDimitry Andric     less<__range_key_type<_Range>>,
966*700637cbSDimitry Andric     vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
967*700637cbSDimitry Andric     vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
968*700637cbSDimitry Andric 
969*700637cbSDimitry Andric template <class _Key, class _Tp, class _Compare = less<_Key>>
970*700637cbSDimitry Andric   requires(!__is_allocator<_Compare>::value)
971*700637cbSDimitry Andric flat_multimap(initializer_list<pair<_Key, _Tp>>, _Compare = _Compare()) -> flat_multimap<_Key, _Tp, _Compare>;
972*700637cbSDimitry Andric 
973*700637cbSDimitry Andric template <class _Key, class _Tp, class _Compare = less<_Key>>
974*700637cbSDimitry Andric   requires(!__is_allocator<_Compare>::value)
975*700637cbSDimitry Andric flat_multimap(sorted_equivalent_t, initializer_list<pair<_Key, _Tp>>, _Compare = _Compare())
976*700637cbSDimitry Andric     -> flat_multimap<_Key, _Tp, _Compare>;
977*700637cbSDimitry Andric 
978*700637cbSDimitry Andric template <class _Key, class _Tp, class _Compare, class _KeyContainer, class _MappedContainer, class _Allocator>
979*700637cbSDimitry Andric struct uses_allocator<flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>, _Allocator>
980*700637cbSDimitry Andric     : bool_constant<uses_allocator_v<_KeyContainer, _Allocator> && uses_allocator_v<_MappedContainer, _Allocator>> {};
981*700637cbSDimitry Andric 
982*700637cbSDimitry Andric template <class _Key, class _Tp, class _Compare, class _KeyContainer, class _MappedContainer, class _Predicate>
983*700637cbSDimitry Andric _LIBCPP_HIDE_FROM_ABI typename flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::size_type
984*700637cbSDimitry Andric erase_if(flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>& __flat_multimap, _Predicate __pred) {
985*700637cbSDimitry Andric   auto __zv     = ranges::views::zip(__flat_multimap.__containers_.keys, __flat_multimap.__containers_.values);
986*700637cbSDimitry Andric   auto __first  = __zv.begin();
987*700637cbSDimitry Andric   auto __last   = __zv.end();
988*700637cbSDimitry Andric   auto __guard  = std::__make_exception_guard([&] { __flat_multimap.clear(); });
989*700637cbSDimitry Andric   auto __it     = std::remove_if(__first, __last, [&](auto&& __zipped) -> bool {
990*700637cbSDimitry Andric     using _Ref = typename flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::const_reference;
991*700637cbSDimitry Andric     return __pred(_Ref(std::get<0>(__zipped), std::get<1>(__zipped)));
992*700637cbSDimitry Andric   });
993*700637cbSDimitry Andric   auto __res    = __last - __it;
994*700637cbSDimitry Andric   auto __offset = __it - __first;
995*700637cbSDimitry Andric 
996*700637cbSDimitry Andric   const auto __erase_container = [&](auto& __cont) { __cont.erase(__cont.begin() + __offset, __cont.end()); };
997*700637cbSDimitry Andric 
998*700637cbSDimitry Andric   __erase_container(__flat_multimap.__containers_.keys);
999*700637cbSDimitry Andric   __erase_container(__flat_multimap.__containers_.values);
1000*700637cbSDimitry Andric 
1001*700637cbSDimitry Andric   __guard.__complete();
1002*700637cbSDimitry Andric   return __res;
1003*700637cbSDimitry Andric }
1004*700637cbSDimitry Andric 
1005*700637cbSDimitry Andric _LIBCPP_END_NAMESPACE_STD
1006*700637cbSDimitry Andric 
1007*700637cbSDimitry Andric #endif // _LIBCPP_STD_VER >= 23
1008*700637cbSDimitry Andric 
1009*700637cbSDimitry Andric _LIBCPP_POP_MACROS
1010*700637cbSDimitry Andric 
1011*700637cbSDimitry Andric #endif // _LIBCPP___FLAT_MAP_FLAT_MULTIMAP_H
1012