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