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