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_MAP_H
11 #define _LIBCPP___FLAT_MAP_FLAT_MAP_H
12 
13 #include <__algorithm/lexicographical_compare_three_way.h>
14 #include <__algorithm/min.h>
15 #include <__algorithm/ranges_adjacent_find.h>
16 #include <__algorithm/ranges_equal.h>
17 #include <__algorithm/ranges_inplace_merge.h>
18 #include <__algorithm/ranges_lower_bound.h>
19 #include <__algorithm/ranges_partition_point.h>
20 #include <__algorithm/ranges_stable_sort.h>
21 #include <__algorithm/ranges_unique.h>
22 #include <__algorithm/ranges_upper_bound.h>
23 #include <__algorithm/remove_if.h>
24 #include <__assert>
25 #include <__compare/synth_three_way.h>
26 #include <__concepts/convertible_to.h>
27 #include <__concepts/swappable.h>
28 #include <__config>
29 #include <__cstddef/byte.h>
30 #include <__cstddef/ptrdiff_t.h>
31 #include <__flat_map/sorted_unique.h>
32 #include <__functional/invoke.h>
33 #include <__functional/is_transparent.h>
34 #include <__functional/operations.h>
35 #include <__iterator/concepts.h>
36 #include <__iterator/distance.h>
37 #include <__iterator/iterator_traits.h>
38 #include <__iterator/next.h>
39 #include <__iterator/ranges_iterator_traits.h>
40 #include <__iterator/reverse_iterator.h>
41 #include <__memory/addressof.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/pair.h>
63 #include <__vector/vector.h>
64 #include <initializer_list>
65 #include <stdexcept>
66 
67 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
68 #  pragma GCC system_header
69 #endif
70 
71 _LIBCPP_PUSH_MACROS
72 #include <__undef_macros>
73 
74 #if _LIBCPP_STD_VER >= 23
75 
76 _LIBCPP_BEGIN_NAMESPACE_STD
77 
78 template <class _Key,
79           class _Tp,
80           class _Compare         = less<_Key>,
81           class _KeyContainer    = vector<_Key>,
82           class _MappedContainer = vector<_Tp>>
83 class flat_map {
84   template <bool _Const>
85   struct __iterator;
86 
87   template <class, class, class, class, class>
88   friend class flat_map;
89 
90   static_assert(is_same_v<_Key, typename _KeyContainer::value_type>);
91   static_assert(is_same_v<_Tp, typename _MappedContainer::value_type>);
92   static_assert(!is_same_v<_KeyContainer, std::vector<bool>>, "vector<bool> is not a sequence container");
93   static_assert(!is_same_v<_MappedContainer, std::vector<bool>>, "vector<bool> is not a sequence container");
94 
95 public:
96   // types
97   using key_type               = _Key;
98   using mapped_type            = _Tp;
99   using value_type             = pair<key_type, mapped_type>;
100   using key_compare            = __type_identity_t<_Compare>;
101   using reference              = pair<const key_type&, mapped_type&>;
102   using const_reference        = pair<const key_type&, const mapped_type&>;
103   using size_type              = size_t;
104   using difference_type        = ptrdiff_t;
105   using iterator               = __iterator<false>; // see [container.requirements]
106   using const_iterator         = __iterator<true>;  // see [container.requirements]
107   using reverse_iterator       = std::reverse_iterator<iterator>;
108   using const_reverse_iterator = std::reverse_iterator<const_iterator>;
109   using key_container_type     = _KeyContainer;
110   using mapped_container_type  = _MappedContainer;
111 
112   class value_compare {
113   private:
114     key_compare __comp_;
value_compare(key_compare __c)115     value_compare(key_compare __c) : __comp_(__c) {}
116     friend flat_map;
117 
118   public:
operator()119     _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const {
120       return __comp_(__x.first, __y.first);
121     }
122   };
123 
124   struct containers {
125     key_container_type keys;
126     mapped_container_type values;
127   };
128 
129 private:
130   template <class _Allocator>
131   _LIBCPP_HIDE_FROM_ABI static constexpr bool __allocator_ctor_constraint =
132       _And<uses_allocator<key_container_type, _Allocator>, uses_allocator<mapped_container_type, _Allocator>>::value;
133 
134   _LIBCPP_HIDE_FROM_ABI static constexpr bool __is_compare_transparent = __is_transparent_v<_Compare, _Compare>;
135 
136   template <bool _Const>
137   struct __iterator {
138   private:
139     using __key_iterator    = ranges::iterator_t<const key_container_type>;
140     using __mapped_iterator = ranges::iterator_t<__maybe_const<_Const, mapped_container_type>>;
141     using __reference       = pair<iter_reference_t<__key_iterator>, iter_reference_t<__mapped_iterator>>;
142 
143     struct __arrow_proxy {
144       __reference __ref_;
145       _LIBCPP_HIDE_FROM_ABI __reference* operator->() { return std::addressof(__ref_); }
146     };
147 
148     __key_iterator __key_iter_;
149     __mapped_iterator __mapped_iter_;
150 
151     friend flat_map;
152 
153   public:
154     using iterator_concept = random_access_iterator_tag;
155     // `flat_map::iterator` only satisfy "Cpp17InputIterator" named requirements, because
156     // its `reference` is not a reference type.
157     // However, to avoid surprising runtime behaviour when it is used with the
158     // Cpp17 algorithms or operations, iterator_category is set to random_access_iterator_tag.
159     using iterator_category = random_access_iterator_tag;
160     using value_type        = flat_map::value_type;
161     using difference_type   = flat_map::difference_type;
162 
163     _LIBCPP_HIDE_FROM_ABI __iterator() = default;
164 
__iterator__iterator165     _LIBCPP_HIDE_FROM_ABI __iterator(__iterator<!_Const> __i)
166       requires _Const && convertible_to<ranges::iterator_t<key_container_type>, __key_iterator> &&
167                    convertible_to<ranges::iterator_t<mapped_container_type>, __mapped_iterator>
168         : __key_iter_(std::move(__i.__key_iter_)), __mapped_iter_(std::move(__i.__mapped_iter_)) {}
169 
__iterator__iterator170     _LIBCPP_HIDE_FROM_ABI __iterator(__key_iterator __key_iter, __mapped_iterator __mapped_iter)
171         : __key_iter_(std::move(__key_iter)), __mapped_iter_(std::move(__mapped_iter)) {}
172 
173     _LIBCPP_HIDE_FROM_ABI __reference operator*() const { return __reference(*__key_iter_, *__mapped_iter_); }
174     _LIBCPP_HIDE_FROM_ABI __arrow_proxy operator->() const { return __arrow_proxy{**this}; }
175 
176     _LIBCPP_HIDE_FROM_ABI __iterator& operator++() {
177       ++__key_iter_;
178       ++__mapped_iter_;
179       return *this;
180     }
181 
182     _LIBCPP_HIDE_FROM_ABI __iterator operator++(int) {
183       __iterator __tmp(*this);
184       ++*this;
185       return __tmp;
186     }
187 
188     _LIBCPP_HIDE_FROM_ABI __iterator& operator--() {
189       --__key_iter_;
190       --__mapped_iter_;
191       return *this;
192     }
193 
194     _LIBCPP_HIDE_FROM_ABI __iterator operator--(int) {
195       __iterator __tmp(*this);
196       --*this;
197       return __tmp;
198     }
199 
200     _LIBCPP_HIDE_FROM_ABI __iterator& operator+=(difference_type __x) {
201       __key_iter_ += __x;
202       __mapped_iter_ += __x;
203       return *this;
204     }
205 
206     _LIBCPP_HIDE_FROM_ABI __iterator& operator-=(difference_type __x) {
207       __key_iter_ -= __x;
208       __mapped_iter_ -= __x;
209       return *this;
210     }
211 
212     _LIBCPP_HIDE_FROM_ABI __reference operator[](difference_type __n) const { return *(*this + __n); }
213 
214     _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) {
215       return __x.__key_iter_ == __y.__key_iter_;
216     }
217 
218     _LIBCPP_HIDE_FROM_ABI friend bool operator<(const __iterator& __x, const __iterator& __y) {
219       return __x.__key_iter_ < __y.__key_iter_;
220     }
221 
222     _LIBCPP_HIDE_FROM_ABI friend bool operator>(const __iterator& __x, const __iterator& __y) { return __y < __x; }
223 
224     _LIBCPP_HIDE_FROM_ABI friend bool operator<=(const __iterator& __x, const __iterator& __y) { return !(__y < __x); }
225 
226     _LIBCPP_HIDE_FROM_ABI friend bool operator>=(const __iterator& __x, const __iterator& __y) { return !(__x < __y); }
227 
228     _LIBCPP_HIDE_FROM_ABI friend auto operator<=>(const __iterator& __x, const __iterator& __y)
229       requires three_way_comparable<__key_iterator>
230     {
231       return __x.__key_iter_ <=> __y.__key_iter_;
232     }
233 
234     _LIBCPP_HIDE_FROM_ABI friend __iterator operator+(const __iterator& __i, difference_type __n) {
235       auto __tmp = __i;
236       __tmp += __n;
237       return __tmp;
238     }
239 
240     _LIBCPP_HIDE_FROM_ABI friend __iterator operator+(difference_type __n, const __iterator& __i) { return __i + __n; }
241 
242     _LIBCPP_HIDE_FROM_ABI friend __iterator operator-(const __iterator& __i, difference_type __n) {
243       auto __tmp = __i;
244       __tmp -= __n;
245       return __tmp;
246     }
247 
248     _LIBCPP_HIDE_FROM_ABI friend difference_type operator-(const __iterator& __x, const __iterator& __y) {
249       return difference_type(__x.__key_iter_ - __y.__key_iter_);
250     }
251   };
252 
253 public:
254   // [flat.map.cons], construct/copy/destroy
flat_map()255   _LIBCPP_HIDE_FROM_ABI flat_map() noexcept(
256       is_nothrow_default_constructible_v<_KeyContainer> && is_nothrow_default_constructible_v<_MappedContainer> &&
257       is_nothrow_default_constructible_v<_Compare>)
258       : __containers_(), __compare_() {}
259 
260   _LIBCPP_HIDE_FROM_ABI flat_map(const flat_map&) = default;
261 
flat_map(flat_map && __other)262   _LIBCPP_HIDE_FROM_ABI flat_map(flat_map&& __other) noexcept(
263       is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_MappedContainer> &&
264       is_nothrow_move_constructible_v<_Compare>)
265 #  if _LIBCPP_HAS_EXCEPTIONS
266       try
267 #  endif // _LIBCPP_HAS_EXCEPTIONS
268       : __containers_(std::move(__other.__containers_)), __compare_(std::move(__other.__compare_)) {
269     __other.clear();
270 #  if _LIBCPP_HAS_EXCEPTIONS
271   } catch (...) {
272     __other.clear();
273     // gcc does not like the `throw` keyword in a conditional noexcept function
274     if constexpr (!(is_nothrow_move_constructible_v<_KeyContainer> &&
275                     is_nothrow_move_constructible_v<_MappedContainer> && is_nothrow_move_constructible_v<_Compare>)) {
276       throw;
277     }
278 #  endif // _LIBCPP_HAS_EXCEPTIONS
279   }
280 
281   template <class _Allocator>
282     requires __allocator_ctor_constraint<_Allocator>
flat_map(const flat_map & __other,const _Allocator & __alloc)283   _LIBCPP_HIDE_FROM_ABI flat_map(const flat_map& __other, const _Allocator& __alloc)
284       : flat_map(__ctor_uses_allocator_tag{},
285                  __alloc,
286                  __other.__containers_.keys,
287                  __other.__containers_.values,
288                  __other.__compare_) {}
289 
290   template <class _Allocator>
291     requires __allocator_ctor_constraint<_Allocator>
flat_map(flat_map && __other,const _Allocator & __alloc)292   _LIBCPP_HIDE_FROM_ABI flat_map(flat_map&& __other, const _Allocator& __alloc)
293 #  if _LIBCPP_HAS_EXCEPTIONS
294       try
295 #  endif // _LIBCPP_HAS_EXCEPTIONS
296       : flat_map(__ctor_uses_allocator_tag{},
297                  __alloc,
298                  std::move(__other.__containers_.keys),
299                  std::move(__other.__containers_.values),
300                  std::move(__other.__compare_)) {
301     __other.clear();
302 #  if _LIBCPP_HAS_EXCEPTIONS
catch(...)303   } catch (...) {
304     __other.clear();
305     throw;
306 #  endif // _LIBCPP_HAS_EXCEPTIONS
307   }
308 
309   _LIBCPP_HIDE_FROM_ABI flat_map(
310       key_container_type __key_cont, mapped_container_type __mapped_cont, const key_compare& __comp = key_compare())
311       : __containers_{.keys = std::move(__key_cont), .values = std::move(__mapped_cont)}, __compare_(__comp) {
312     _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
313                                      "flat_map keys and mapped containers have different size");
314     __sort_and_unique();
315   }
316 
317   template <class _Allocator>
318     requires __allocator_ctor_constraint<_Allocator>
319   _LIBCPP_HIDE_FROM_ABI
flat_map(const key_container_type & __key_cont,const mapped_container_type & __mapped_cont,const _Allocator & __alloc)320   flat_map(const key_container_type& __key_cont, const mapped_container_type& __mapped_cont, const _Allocator& __alloc)
321       : flat_map(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont) {
322     _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
323                                      "flat_map keys and mapped containers have different size");
324     __sort_and_unique();
325   }
326 
327   template <class _Allocator>
328     requires __allocator_ctor_constraint<_Allocator>
329   _LIBCPP_HIDE_FROM_ABI
flat_map(const key_container_type & __key_cont,const mapped_container_type & __mapped_cont,const key_compare & __comp,const _Allocator & __alloc)330   flat_map(const key_container_type& __key_cont,
331            const mapped_container_type& __mapped_cont,
332            const key_compare& __comp,
333            const _Allocator& __alloc)
334       : flat_map(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont, __comp) {
335     _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
336                                      "flat_map keys and mapped containers have different size");
337     __sort_and_unique();
338   }
339 
340   _LIBCPP_HIDE_FROM_ABI
341   flat_map(sorted_unique_t,
342            key_container_type __key_cont,
343            mapped_container_type __mapped_cont,
344            const key_compare& __comp = key_compare())
345       : __containers_{.keys = std::move(__key_cont), .values = std::move(__mapped_cont)}, __compare_(__comp) {
346     _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
347                                      "flat_map keys and mapped containers have different size");
348     _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
349         __is_sorted_and_unique(__containers_.keys), "Either the key container is not sorted or it contains duplicates");
350   }
351 
352   template <class _Allocator>
353     requires __allocator_ctor_constraint<_Allocator>
354   _LIBCPP_HIDE_FROM_ABI
flat_map(sorted_unique_t,const key_container_type & __key_cont,const mapped_container_type & __mapped_cont,const _Allocator & __alloc)355   flat_map(sorted_unique_t,
356            const key_container_type& __key_cont,
357            const mapped_container_type& __mapped_cont,
358            const _Allocator& __alloc)
359       : flat_map(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont) {
360     _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
361                                      "flat_map keys and mapped containers have different size");
362     _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
363         __is_sorted_and_unique(__containers_.keys), "Either the key container is not sorted or it contains duplicates");
364   }
365 
366   template <class _Allocator>
367     requires __allocator_ctor_constraint<_Allocator>
368   _LIBCPP_HIDE_FROM_ABI
flat_map(sorted_unique_t,const key_container_type & __key_cont,const mapped_container_type & __mapped_cont,const key_compare & __comp,const _Allocator & __alloc)369   flat_map(sorted_unique_t,
370            const key_container_type& __key_cont,
371            const mapped_container_type& __mapped_cont,
372            const key_compare& __comp,
373            const _Allocator& __alloc)
374       : flat_map(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont, __comp) {
375     _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
376                                      "flat_map keys and mapped containers have different size");
377     _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
378         __is_sorted_and_unique(__containers_.keys), "Either the key container is not sorted or it contains duplicates");
379   }
380 
flat_map(const key_compare & __comp)381   _LIBCPP_HIDE_FROM_ABI explicit flat_map(const key_compare& __comp) : __containers_(), __compare_(__comp) {}
382 
383   template <class _Allocator>
384     requires __allocator_ctor_constraint<_Allocator>
flat_map(const key_compare & __comp,const _Allocator & __alloc)385   _LIBCPP_HIDE_FROM_ABI flat_map(const key_compare& __comp, const _Allocator& __alloc)
386       : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {}
387 
388   template <class _Allocator>
389     requires __allocator_ctor_constraint<_Allocator>
flat_map(const _Allocator & __alloc)390   _LIBCPP_HIDE_FROM_ABI explicit flat_map(const _Allocator& __alloc)
391       : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc) {}
392 
393   template <class _InputIterator>
394     requires __has_input_iterator_category<_InputIterator>::value
395   _LIBCPP_HIDE_FROM_ABI
396   flat_map(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare())
__containers_()397       : __containers_(), __compare_(__comp) {
398     insert(__first, __last);
399   }
400 
401   template <class _InputIterator, class _Allocator>
requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)402     requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)
403   _LIBCPP_HIDE_FROM_ABI
404   flat_map(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc)
405       : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {
406     insert(__first, __last);
407   }
408 
409   template <class _InputIterator, class _Allocator>
requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)410     requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)
411   _LIBCPP_HIDE_FROM_ABI flat_map(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc)
412       : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc) {
413     insert(__first, __last);
414   }
415 
416   template <_ContainerCompatibleRange<value_type> _Range>
flat_map(from_range_t __fr,_Range && __rg)417   _LIBCPP_HIDE_FROM_ABI flat_map(from_range_t __fr, _Range&& __rg)
418       : flat_map(__fr, std::forward<_Range>(__rg), key_compare()) {}
419 
420   template <_ContainerCompatibleRange<value_type> _Range, class _Allocator>
421     requires __allocator_ctor_constraint<_Allocator>
flat_map(from_range_t,_Range && __rg,const _Allocator & __alloc)422   _LIBCPP_HIDE_FROM_ABI flat_map(from_range_t, _Range&& __rg, const _Allocator& __alloc)
423       : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc) {
424     insert_range(std::forward<_Range>(__rg));
425   }
426 
427   template <_ContainerCompatibleRange<value_type> _Range>
flat_map(from_range_t,_Range && __rg,const key_compare & __comp)428   _LIBCPP_HIDE_FROM_ABI flat_map(from_range_t, _Range&& __rg, const key_compare& __comp) : flat_map(__comp) {
429     insert_range(std::forward<_Range>(__rg));
430   }
431 
432   template <_ContainerCompatibleRange<value_type> _Range, class _Allocator>
433     requires __allocator_ctor_constraint<_Allocator>
flat_map(from_range_t,_Range && __rg,const key_compare & __comp,const _Allocator & __alloc)434   _LIBCPP_HIDE_FROM_ABI flat_map(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc)
435       : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {
436     insert_range(std::forward<_Range>(__rg));
437   }
438 
439   template <class _InputIterator>
440     requires __has_input_iterator_category<_InputIterator>::value
441   _LIBCPP_HIDE_FROM_ABI
442   flat_map(sorted_unique_t, _InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare())
__containers_()443       : __containers_(), __compare_(__comp) {
444     insert(sorted_unique, __first, __last);
445   }
446   template <class _InputIterator, class _Allocator>
requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)447     requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)
448   _LIBCPP_HIDE_FROM_ABI
449   flat_map(sorted_unique_t,
450            _InputIterator __first,
451            _InputIterator __last,
452            const key_compare& __comp,
453            const _Allocator& __alloc)
454       : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {
455     insert(sorted_unique, __first, __last);
456   }
457 
458   template <class _InputIterator, class _Allocator>
requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)459     requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)
460   _LIBCPP_HIDE_FROM_ABI
461   flat_map(sorted_unique_t, _InputIterator __first, _InputIterator __last, const _Allocator& __alloc)
462       : flat_map(__ctor_uses_allocator_empty_tag{}, __alloc) {
463     insert(sorted_unique, __first, __last);
464   }
465 
466   _LIBCPP_HIDE_FROM_ABI flat_map(initializer_list<value_type> __il, const key_compare& __comp = key_compare())
467       : flat_map(__il.begin(), __il.end(), __comp) {}
468 
469   template <class _Allocator>
470     requires __allocator_ctor_constraint<_Allocator>
471   _LIBCPP_HIDE_FROM_ABI
flat_map(initializer_list<value_type> __il,const key_compare & __comp,const _Allocator & __alloc)472   flat_map(initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc)
473       : flat_map(__il.begin(), __il.end(), __comp, __alloc) {}
474 
475   template <class _Allocator>
476     requires __allocator_ctor_constraint<_Allocator>
flat_map(initializer_list<value_type> __il,const _Allocator & __alloc)477   _LIBCPP_HIDE_FROM_ABI flat_map(initializer_list<value_type> __il, const _Allocator& __alloc)
478       : flat_map(__il.begin(), __il.end(), __alloc) {}
479 
480   _LIBCPP_HIDE_FROM_ABI
481   flat_map(sorted_unique_t, initializer_list<value_type> __il, const key_compare& __comp = key_compare())
482       : flat_map(sorted_unique, __il.begin(), __il.end(), __comp) {}
483 
484   template <class _Allocator>
485     requires __allocator_ctor_constraint<_Allocator>
486   _LIBCPP_HIDE_FROM_ABI
flat_map(sorted_unique_t,initializer_list<value_type> __il,const key_compare & __comp,const _Allocator & __alloc)487   flat_map(sorted_unique_t, initializer_list<value_type> __il, const key_compare& __comp, const _Allocator& __alloc)
488       : flat_map(sorted_unique, __il.begin(), __il.end(), __comp, __alloc) {}
489 
490   template <class _Allocator>
491     requires __allocator_ctor_constraint<_Allocator>
flat_map(sorted_unique_t,initializer_list<value_type> __il,const _Allocator & __alloc)492   _LIBCPP_HIDE_FROM_ABI flat_map(sorted_unique_t, initializer_list<value_type> __il, const _Allocator& __alloc)
493       : flat_map(sorted_unique, __il.begin(), __il.end(), __alloc) {}
494 
495   _LIBCPP_HIDE_FROM_ABI flat_map& operator=(initializer_list<value_type> __il) {
496     clear();
497     insert(__il);
498     return *this;
499   }
500 
501   _LIBCPP_HIDE_FROM_ABI flat_map& operator=(const flat_map&) = default;
502 
noexcept(is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_MappedContainer> && is_nothrow_move_assignable_v<_Compare>)503   _LIBCPP_HIDE_FROM_ABI flat_map& operator=(flat_map&& __other) noexcept(
504       is_nothrow_move_assignable_v<_KeyContainer> && is_nothrow_move_assignable_v<_MappedContainer> &&
505       is_nothrow_move_assignable_v<_Compare>) {
506     // No matter what happens, we always want to clear the other container before returning
507     // since we moved from it
508     auto __clear_other_guard = std::__make_scope_guard([&]() noexcept { __other.clear() /* noexcept */; });
509     {
510       // If an exception is thrown, we have no choice but to clear *this to preserve invariants
511       auto __on_exception = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
512       __containers_       = std::move(__other.__containers_);
513       __compare_          = std::move(__other.__compare_);
514       __on_exception.__complete();
515     }
516     return *this;
517   }
518 
519   // iterators
begin()520   _LIBCPP_HIDE_FROM_ABI iterator begin() noexcept {
521     return iterator(__containers_.keys.begin(), __containers_.values.begin());
522   }
523 
begin()524   _LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept {
525     return const_iterator(__containers_.keys.begin(), __containers_.values.begin());
526   }
527 
end()528   _LIBCPP_HIDE_FROM_ABI iterator end() noexcept {
529     return iterator(__containers_.keys.end(), __containers_.values.end());
530   }
531 
end()532   _LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept {
533     return const_iterator(__containers_.keys.end(), __containers_.values.end());
534   }
535 
rbegin()536   _LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
rbegin()537   _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
rend()538   _LIBCPP_HIDE_FROM_ABI reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
rend()539   _LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
540 
cbegin()541   _LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return begin(); }
cend()542   _LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return end(); }
crbegin()543   _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
crend()544   _LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
545 
546   // [flat.map.capacity], capacity
empty()547   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __containers_.keys.empty(); }
548 
size()549   _LIBCPP_HIDE_FROM_ABI size_type size() const noexcept { return __containers_.keys.size(); }
550 
max_size()551   _LIBCPP_HIDE_FROM_ABI size_type max_size() const noexcept {
552     return std::min<size_type>(__containers_.keys.max_size(), __containers_.values.max_size());
553   }
554 
555   // [flat.map.access], element access
556   _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](const key_type& __x)
557     requires is_constructible_v<mapped_type>
558   {
559     return try_emplace(__x).first->second;
560   }
561 
562   _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](key_type&& __x)
563     requires is_constructible_v<mapped_type>
564   {
565     return try_emplace(std::move(__x)).first->second;
566   }
567 
568   template <class _Kp>
569     requires(__is_compare_transparent && is_constructible_v<key_type, _Kp> && is_constructible_v<mapped_type> &&
570              !is_convertible_v<_Kp &&, const_iterator> && !is_convertible_v<_Kp &&, iterator>)
571   _LIBCPP_HIDE_FROM_ABI mapped_type& operator[](_Kp&& __x) {
572     return try_emplace(std::forward<_Kp>(__x)).first->second;
573   }
574 
at(const key_type & __x)575   _LIBCPP_HIDE_FROM_ABI mapped_type& at(const key_type& __x) {
576     auto __it = find(__x);
577     if (__it == end()) {
578       std::__throw_out_of_range("flat_map::at(const key_type&): Key does not exist");
579     }
580     return __it->second;
581   }
582 
at(const key_type & __x)583   _LIBCPP_HIDE_FROM_ABI const mapped_type& at(const key_type& __x) const {
584     auto __it = find(__x);
585     if (__it == end()) {
586       std::__throw_out_of_range("flat_map::at(const key_type&) const: Key does not exist");
587     }
588     return __it->second;
589   }
590 
591   template <class _Kp>
592     requires __is_compare_transparent
at(const _Kp & __x)593   _LIBCPP_HIDE_FROM_ABI mapped_type& at(const _Kp& __x) {
594     auto __it = find(__x);
595     if (__it == end()) {
596       std::__throw_out_of_range("flat_map::at(const K&): Key does not exist");
597     }
598     return __it->second;
599   }
600 
601   template <class _Kp>
602     requires __is_compare_transparent
at(const _Kp & __x)603   _LIBCPP_HIDE_FROM_ABI const mapped_type& at(const _Kp& __x) const {
604     auto __it = find(__x);
605     if (__it == end()) {
606       std::__throw_out_of_range("flat_map::at(const K&) const: Key does not exist");
607     }
608     return __it->second;
609   }
610 
611   // [flat.map.modifiers], modifiers
612   template <class... _Args>
613     requires is_constructible_v<pair<key_type, mapped_type>, _Args...>
emplace(_Args &&...__args)614   _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> emplace(_Args&&... __args) {
615     std::pair<key_type, mapped_type> __pair(std::forward<_Args>(__args)...);
616     return __try_emplace(std::move(__pair.first), std::move(__pair.second));
617   }
618 
619   template <class... _Args>
620     requires is_constructible_v<pair<key_type, mapped_type>, _Args...>
emplace_hint(const_iterator __hint,_Args &&...__args)621   _LIBCPP_HIDE_FROM_ABI iterator emplace_hint(const_iterator __hint, _Args&&... __args) {
622     std::pair<key_type, mapped_type> __pair(std::forward<_Args>(__args)...);
623     return __try_emplace_hint(__hint, std::move(__pair.first), std::move(__pair.second)).first;
624   }
625 
insert(const value_type & __x)626   _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> insert(const value_type& __x) { return emplace(__x); }
627 
insert(value_type && __x)628   _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> insert(value_type&& __x) { return emplace(std::move(__x)); }
629 
insert(const_iterator __hint,const value_type & __x)630   _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, const value_type& __x) {
631     return emplace_hint(__hint, __x);
632   }
633 
insert(const_iterator __hint,value_type && __x)634   _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, value_type&& __x) {
635     return emplace_hint(__hint, std::move(__x));
636   }
637 
638   template <class _Pp>
639     requires is_constructible_v<pair<key_type, mapped_type>, _Pp>
insert(_Pp && __x)640   _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> insert(_Pp&& __x) {
641     return emplace(std::forward<_Pp>(__x));
642   }
643 
644   template <class _Pp>
645     requires is_constructible_v<pair<key_type, mapped_type>, _Pp>
insert(const_iterator __hint,_Pp && __x)646   _LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, _Pp&& __x) {
647     return emplace_hint(__hint, std::forward<_Pp>(__x));
648   }
649 
650   template <class _InputIterator>
651     requires __has_input_iterator_category<_InputIterator>::value
insert(_InputIterator __first,_InputIterator __last)652   _LIBCPP_HIDE_FROM_ABI void insert(_InputIterator __first, _InputIterator __last) {
653     if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) {
654       __reserve(__last - __first);
655     }
656     __append_sort_merge_unique</*WasSorted = */ false>(std::move(__first), std::move(__last));
657   }
658 
659   template <class _InputIterator>
660     requires __has_input_iterator_category<_InputIterator>::value
insert(sorted_unique_t,_InputIterator __first,_InputIterator __last)661   void insert(sorted_unique_t, _InputIterator __first, _InputIterator __last) {
662     if constexpr (sized_sentinel_for<_InputIterator, _InputIterator>) {
663       __reserve(__last - __first);
664     }
665 
666     __append_sort_merge_unique</*WasSorted = */ true>(std::move(__first), std::move(__last));
667   }
668 
669   template <_ContainerCompatibleRange<value_type> _Range>
insert_range(_Range && __range)670   _LIBCPP_HIDE_FROM_ABI void insert_range(_Range&& __range) {
671     if constexpr (ranges::sized_range<_Range>) {
672       __reserve(ranges::size(__range));
673     }
674 
675     __append_sort_merge_unique</*WasSorted = */ false>(ranges::begin(__range), ranges::end(__range));
676   }
677 
insert(initializer_list<value_type> __il)678   _LIBCPP_HIDE_FROM_ABI void insert(initializer_list<value_type> __il) { insert(__il.begin(), __il.end()); }
679 
insert(sorted_unique_t,initializer_list<value_type> __il)680   _LIBCPP_HIDE_FROM_ABI void insert(sorted_unique_t, initializer_list<value_type> __il) {
681     insert(sorted_unique, __il.begin(), __il.end());
682   }
683 
extract()684   _LIBCPP_HIDE_FROM_ABI containers extract() && {
685     auto __guard = std::__make_scope_guard([&]() noexcept { clear() /* noexcept */; });
686     auto __ret   = std::move(__containers_);
687     return __ret;
688   }
689 
replace(key_container_type && __key_cont,mapped_container_type && __mapped_cont)690   _LIBCPP_HIDE_FROM_ABI void replace(key_container_type&& __key_cont, mapped_container_type&& __mapped_cont) {
691     _LIBCPP_ASSERT_VALID_INPUT_RANGE(
692         __key_cont.size() == __mapped_cont.size(), "flat_map keys and mapped containers have different size");
693 
694     _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
695         __is_sorted_and_unique(__key_cont), "Either the key container is not sorted or it contains duplicates");
696     auto __guard         = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
697     __containers_.keys   = std::move(__key_cont);
698     __containers_.values = std::move(__mapped_cont);
699     __guard.__complete();
700   }
701 
702   template <class... _Args>
703     requires is_constructible_v<mapped_type, _Args...>
try_emplace(const key_type & __key,_Args &&...__args)704   _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> try_emplace(const key_type& __key, _Args&&... __args) {
705     return __try_emplace(__key, std::forward<_Args>(__args)...);
706   }
707 
708   template <class... _Args>
709     requires is_constructible_v<mapped_type, _Args...>
try_emplace(key_type && __key,_Args &&...__args)710   _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> try_emplace(key_type&& __key, _Args&&... __args) {
711     return __try_emplace(std::move(__key), std::forward<_Args>(__args)...);
712   }
713 
714   template <class _Kp, class... _Args>
715     requires(__is_compare_transparent && is_constructible_v<key_type, _Kp> &&
716              is_constructible_v<mapped_type, _Args...> && !is_convertible_v<_Kp &&, const_iterator> &&
717              !is_convertible_v<_Kp &&, iterator>)
try_emplace(_Kp && __key,_Args &&...__args)718   _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> try_emplace(_Kp&& __key, _Args&&... __args) {
719     return __try_emplace(std::forward<_Kp>(__key), std::forward<_Args>(__args)...);
720   }
721 
722   template <class... _Args>
723     requires is_constructible_v<mapped_type, _Args...>
try_emplace(const_iterator __hint,const key_type & __key,_Args &&...__args)724   _LIBCPP_HIDE_FROM_ABI iterator try_emplace(const_iterator __hint, const key_type& __key, _Args&&... __args) {
725     return __try_emplace_hint(__hint, __key, std::forward<_Args>(__args)...).first;
726   }
727 
728   template <class... _Args>
729     requires is_constructible_v<mapped_type, _Args...>
try_emplace(const_iterator __hint,key_type && __key,_Args &&...__args)730   _LIBCPP_HIDE_FROM_ABI iterator try_emplace(const_iterator __hint, key_type&& __key, _Args&&... __args) {
731     return __try_emplace_hint(__hint, std::move(__key), std::forward<_Args>(__args)...).first;
732   }
733 
734   template <class _Kp, class... _Args>
735     requires __is_compare_transparent && is_constructible_v<key_type, _Kp> && is_constructible_v<mapped_type, _Args...>
try_emplace(const_iterator __hint,_Kp && __key,_Args &&...__args)736   _LIBCPP_HIDE_FROM_ABI iterator try_emplace(const_iterator __hint, _Kp&& __key, _Args&&... __args) {
737     return __try_emplace_hint(__hint, std::forward<_Kp>(__key), std::forward<_Args>(__args)...).first;
738   }
739 
740   template <class _Mapped>
741     requires is_assignable_v<mapped_type&, _Mapped> && is_constructible_v<mapped_type, _Mapped>
insert_or_assign(const key_type & __key,_Mapped && __obj)742   _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> insert_or_assign(const key_type& __key, _Mapped&& __obj) {
743     return __insert_or_assign(__key, std::forward<_Mapped>(__obj));
744   }
745 
746   template <class _Mapped>
747     requires is_assignable_v<mapped_type&, _Mapped> && is_constructible_v<mapped_type, _Mapped>
insert_or_assign(key_type && __key,_Mapped && __obj)748   _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> insert_or_assign(key_type&& __key, _Mapped&& __obj) {
749     return __insert_or_assign(std::move(__key), std::forward<_Mapped>(__obj));
750   }
751 
752   template <class _Kp, class _Mapped>
753     requires __is_compare_transparent && is_constructible_v<key_type, _Kp> && is_assignable_v<mapped_type&, _Mapped> &&
754              is_constructible_v<mapped_type, _Mapped>
insert_or_assign(_Kp && __key,_Mapped && __obj)755   _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> insert_or_assign(_Kp&& __key, _Mapped&& __obj) {
756     return __insert_or_assign(std::forward<_Kp>(__key), std::forward<_Mapped>(__obj));
757   }
758 
759   template <class _Mapped>
760     requires is_assignable_v<mapped_type&, _Mapped> && is_constructible_v<mapped_type, _Mapped>
insert_or_assign(const_iterator __hint,const key_type & __key,_Mapped && __obj)761   _LIBCPP_HIDE_FROM_ABI iterator insert_or_assign(const_iterator __hint, const key_type& __key, _Mapped&& __obj) {
762     return __insert_or_assign(__hint, __key, std::forward<_Mapped>(__obj));
763   }
764 
765   template <class _Mapped>
766     requires is_assignable_v<mapped_type&, _Mapped> && is_constructible_v<mapped_type, _Mapped>
insert_or_assign(const_iterator __hint,key_type && __key,_Mapped && __obj)767   _LIBCPP_HIDE_FROM_ABI iterator insert_or_assign(const_iterator __hint, key_type&& __key, _Mapped&& __obj) {
768     return __insert_or_assign(__hint, std::move(__key), std::forward<_Mapped>(__obj));
769   }
770 
771   template <class _Kp, class _Mapped>
772     requires __is_compare_transparent && is_constructible_v<key_type, _Kp> && is_assignable_v<mapped_type&, _Mapped> &&
773              is_constructible_v<mapped_type, _Mapped>
insert_or_assign(const_iterator __hint,_Kp && __key,_Mapped && __obj)774   _LIBCPP_HIDE_FROM_ABI iterator insert_or_assign(const_iterator __hint, _Kp&& __key, _Mapped&& __obj) {
775     return __insert_or_assign(__hint, std::forward<_Kp>(__key), std::forward<_Mapped>(__obj));
776   }
777 
erase(iterator __position)778   _LIBCPP_HIDE_FROM_ABI iterator erase(iterator __position) {
779     return __erase(__position.__key_iter_, __position.__mapped_iter_);
780   }
781 
erase(const_iterator __position)782   _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __position) {
783     return __erase(__position.__key_iter_, __position.__mapped_iter_);
784   }
785 
erase(const key_type & __x)786   _LIBCPP_HIDE_FROM_ABI size_type erase(const key_type& __x) {
787     auto __iter = find(__x);
788     if (__iter != end()) {
789       erase(__iter);
790       return 1;
791     }
792     return 0;
793   }
794 
795   template <class _Kp>
796     requires(__is_compare_transparent && !is_convertible_v<_Kp &&, iterator> &&
797              !is_convertible_v<_Kp &&, const_iterator>)
erase(_Kp && __x)798   _LIBCPP_HIDE_FROM_ABI size_type erase(_Kp&& __x) {
799     auto [__first, __last] = equal_range(__x);
800     auto __res             = __last - __first;
801     erase(__first, __last);
802     return __res;
803   }
804 
erase(const_iterator __first,const_iterator __last)805   _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last) {
806     auto __on_failure = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
807     auto __key_it     = __containers_.keys.erase(__first.__key_iter_, __last.__key_iter_);
808     auto __mapped_it  = __containers_.values.erase(__first.__mapped_iter_, __last.__mapped_iter_);
809     __on_failure.__complete();
810     return iterator(std::move(__key_it), std::move(__mapped_it));
811   }
812 
swap(flat_map & __y)813   _LIBCPP_HIDE_FROM_ABI void swap(flat_map& __y) noexcept {
814     // warning: The spec has unconditional noexcept, which means that
815     // if any of the following functions throw an exception,
816     // std::terminate will be called.
817     // This is discussed in P2767, which hasn't been voted on yet.
818     ranges::swap(__compare_, __y.__compare_);
819     ranges::swap(__containers_.keys, __y.__containers_.keys);
820     ranges::swap(__containers_.values, __y.__containers_.values);
821   }
822 
clear()823   _LIBCPP_HIDE_FROM_ABI void clear() noexcept {
824     __containers_.keys.clear();
825     __containers_.values.clear();
826   }
827 
828   // observers
key_comp()829   _LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __compare_; }
value_comp()830   _LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return value_compare(__compare_); }
831 
keys()832   _LIBCPP_HIDE_FROM_ABI const key_container_type& keys() const noexcept { return __containers_.keys; }
values()833   _LIBCPP_HIDE_FROM_ABI const mapped_container_type& values() const noexcept { return __containers_.values; }
834 
835   // map operations
find(const key_type & __x)836   _LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __x) { return __find_impl(*this, __x); }
837 
find(const key_type & __x)838   _LIBCPP_HIDE_FROM_ABI const_iterator find(const key_type& __x) const { return __find_impl(*this, __x); }
839 
840   template <class _Kp>
841     requires __is_compare_transparent
find(const _Kp & __x)842   _LIBCPP_HIDE_FROM_ABI iterator find(const _Kp& __x) {
843     return __find_impl(*this, __x);
844   }
845 
846   template <class _Kp>
847     requires __is_compare_transparent
find(const _Kp & __x)848   _LIBCPP_HIDE_FROM_ABI const_iterator find(const _Kp& __x) const {
849     return __find_impl(*this, __x);
850   }
851 
count(const key_type & __x)852   _LIBCPP_HIDE_FROM_ABI size_type count(const key_type& __x) const { return contains(__x) ? 1 : 0; }
853 
854   template <class _Kp>
855     requires __is_compare_transparent
count(const _Kp & __x)856   _LIBCPP_HIDE_FROM_ABI size_type count(const _Kp& __x) const {
857     return contains(__x) ? 1 : 0;
858   }
859 
contains(const key_type & __x)860   _LIBCPP_HIDE_FROM_ABI bool contains(const key_type& __x) const { return find(__x) != end(); }
861 
862   template <class _Kp>
863     requires __is_compare_transparent
contains(const _Kp & __x)864   _LIBCPP_HIDE_FROM_ABI bool contains(const _Kp& __x) const {
865     return find(__x) != end();
866   }
867 
lower_bound(const key_type & __x)868   _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __x) { return __lower_bound<iterator>(*this, __x); }
869 
lower_bound(const key_type & __x)870   _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const key_type& __x) const {
871     return __lower_bound<const_iterator>(*this, __x);
872   }
873 
874   template <class _Kp>
875     requires __is_compare_transparent
lower_bound(const _Kp & __x)876   _LIBCPP_HIDE_FROM_ABI iterator lower_bound(const _Kp& __x) {
877     return __lower_bound<iterator>(*this, __x);
878   }
879 
880   template <class _Kp>
881     requires __is_compare_transparent
lower_bound(const _Kp & __x)882   _LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Kp& __x) const {
883     return __lower_bound<const_iterator>(*this, __x);
884   }
885 
upper_bound(const key_type & __x)886   _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __x) { return __upper_bound<iterator>(*this, __x); }
887 
upper_bound(const key_type & __x)888   _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const key_type& __x) const {
889     return __upper_bound<const_iterator>(*this, __x);
890   }
891 
892   template <class _Kp>
893     requires __is_compare_transparent
upper_bound(const _Kp & __x)894   _LIBCPP_HIDE_FROM_ABI iterator upper_bound(const _Kp& __x) {
895     return __upper_bound<iterator>(*this, __x);
896   }
897 
898   template <class _Kp>
899     requires __is_compare_transparent
upper_bound(const _Kp & __x)900   _LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Kp& __x) const {
901     return __upper_bound<const_iterator>(*this, __x);
902   }
903 
equal_range(const key_type & __x)904   _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __x) {
905     return __equal_range_impl(*this, __x);
906   }
907 
equal_range(const key_type & __x)908   _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const key_type& __x) const {
909     return __equal_range_impl(*this, __x);
910   }
911 
912   template <class _Kp>
913     requires __is_compare_transparent
equal_range(const _Kp & __x)914   _LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const _Kp& __x) {
915     return __equal_range_impl(*this, __x);
916   }
917   template <class _Kp>
918     requires __is_compare_transparent
equal_range(const _Kp & __x)919   _LIBCPP_HIDE_FROM_ABI pair<const_iterator, const_iterator> equal_range(const _Kp& __x) const {
920     return __equal_range_impl(*this, __x);
921   }
922 
923   friend _LIBCPP_HIDE_FROM_ABI bool operator==(const flat_map& __x, const flat_map& __y) {
924     return ranges::equal(__x, __y);
925   }
926 
927   friend _LIBCPP_HIDE_FROM_ABI auto operator<=>(const flat_map& __x, const flat_map& __y) {
928     return std::lexicographical_compare_three_way(
929         __x.begin(), __x.end(), __y.begin(), __y.end(), std::__synth_three_way);
930   }
931 
swap(flat_map & __x,flat_map & __y)932   friend _LIBCPP_HIDE_FROM_ABI void swap(flat_map& __x, flat_map& __y) noexcept { __x.swap(__y); }
933 
934 private:
935   struct __ctor_uses_allocator_tag {
936     explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_tag() = default;
937   };
938   struct __ctor_uses_allocator_empty_tag {
939     explicit _LIBCPP_HIDE_FROM_ABI __ctor_uses_allocator_empty_tag() = default;
940   };
941 
942   template <class _Allocator, class _KeyCont, class _MappedCont, class... _CompArg>
943     requires __allocator_ctor_constraint<_Allocator>
944   _LIBCPP_HIDE_FROM_ABI
flat_map(__ctor_uses_allocator_tag,const _Allocator & __alloc,_KeyCont && __key_cont,_MappedCont && __mapped_cont,_CompArg &&...__comp)945   flat_map(__ctor_uses_allocator_tag,
946            const _Allocator& __alloc,
947            _KeyCont&& __key_cont,
948            _MappedCont&& __mapped_cont,
949            _CompArg&&... __comp)
950       : __containers_{.keys = std::make_obj_using_allocator<key_container_type>(
951                           __alloc, std::forward<_KeyCont>(__key_cont)),
952                       .values = std::make_obj_using_allocator<mapped_container_type>(
953                           __alloc, std::forward<_MappedCont>(__mapped_cont))},
954         __compare_(std::forward<_CompArg>(__comp)...) {}
955 
956   template <class _Allocator, class... _CompArg>
957     requires __allocator_ctor_constraint<_Allocator>
flat_map(__ctor_uses_allocator_empty_tag,const _Allocator & __alloc,_CompArg &&...__comp)958   _LIBCPP_HIDE_FROM_ABI flat_map(__ctor_uses_allocator_empty_tag, const _Allocator& __alloc, _CompArg&&... __comp)
959       : __containers_{.keys   = std::make_obj_using_allocator<key_container_type>(__alloc),
960                       .values = std::make_obj_using_allocator<mapped_container_type>(__alloc)},
961         __compare_(std::forward<_CompArg>(__comp)...) {}
962 
__is_sorted_and_unique(auto && __key_container)963   _LIBCPP_HIDE_FROM_ABI bool __is_sorted_and_unique(auto&& __key_container) const {
964     auto __greater_or_equal_to = [this](const auto& __x, const auto& __y) { return !__compare_(__x, __y); };
965     return ranges::adjacent_find(__key_container, __greater_or_equal_to) == ranges::end(__key_container);
966   }
967 
968   // This function is only used in constructors. So there is not exception handling in this function.
969   // If the function exits via an exception, there will be no flat_map object constructed, thus, there
970   // is no invariant state to preserve
__sort_and_unique()971   _LIBCPP_HIDE_FROM_ABI void __sort_and_unique() {
972     auto __zv = ranges::views::zip(__containers_.keys, __containers_.values);
973     // To be consistent with std::map's behaviour, we use stable_sort instead of sort.
974     // As a result, if there are duplicated keys, the first value in the original order will be taken.
975     ranges::stable_sort(__zv, __compare_, [](const auto& __p) -> decltype(auto) { return std::get<0>(__p); });
976     auto __dup_start = ranges::unique(__zv, __key_equiv(__compare_)).begin();
977     auto __dist      = ranges::distance(__zv.begin(), __dup_start);
978     __containers_.keys.erase(__containers_.keys.begin() + __dist, __containers_.keys.end());
979     __containers_.values.erase(__containers_.values.begin() + __dist, __containers_.values.end());
980   }
981 
982   template <class _InputIterator, class _Sentinel>
__append(_InputIterator __first,_Sentinel __last)983   _LIBCPP_HIDE_FROM_ABI size_type __append(_InputIterator __first, _Sentinel __last) {
984     size_type __num_of_appended = 0;
985     for (; __first != __last; ++__first) {
986       value_type __kv = *__first;
987       __containers_.keys.insert(__containers_.keys.end(), std::move(__kv.first));
988       __containers_.values.insert(__containers_.values.end(), std::move(__kv.second));
989       ++__num_of_appended;
990     }
991     return __num_of_appended;
992   }
993 
994   template <bool _WasSorted, class _InputIterator, class _Sentinel>
__append_sort_merge_unique(_InputIterator __first,_Sentinel __last)995   _LIBCPP_HIDE_FROM_ABI void __append_sort_merge_unique(_InputIterator __first, _Sentinel __last) {
996     auto __on_failure        = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
997     size_t __num_of_appended = __append(std::move(__first), std::move(__last));
998     if (__num_of_appended != 0) {
999       auto __zv                  = ranges::views::zip(__containers_.keys, __containers_.values);
1000       auto __append_start_offset = __containers_.keys.size() - __num_of_appended;
1001       auto __end                 = __zv.end();
1002       auto __compare_key         = [this](const auto& __p1, const auto& __p2) {
1003         return __compare_(std::get<0>(__p1), std::get<0>(__p2));
1004       };
1005       if constexpr (!_WasSorted) {
1006         ranges::stable_sort(__zv.begin() + __append_start_offset, __end, __compare_key);
1007       } else {
1008         _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(
1009             __is_sorted_and_unique(__containers_.keys | ranges::views::drop(__append_start_offset)),
1010             "Either the key container is not sorted or it contains duplicates");
1011       }
1012       ranges::inplace_merge(__zv.begin(), __zv.begin() + __append_start_offset, __end, __compare_key);
1013 
1014       auto __dup_start = ranges::unique(__zv, __key_equiv(__compare_)).begin();
1015       auto __dist      = ranges::distance(__zv.begin(), __dup_start);
1016       __containers_.keys.erase(__containers_.keys.begin() + __dist, __containers_.keys.end());
1017       __containers_.values.erase(__containers_.values.begin() + __dist, __containers_.values.end());
1018     }
1019     __on_failure.__complete();
1020   }
1021 
1022   template <class _Self, class _Kp>
__find_impl(_Self && __self,const _Kp & __key)1023   _LIBCPP_HIDE_FROM_ABI static auto __find_impl(_Self&& __self, const _Kp& __key) {
1024     auto __it   = __self.lower_bound(__key);
1025     auto __last = __self.end();
1026     if (__it == __last || __self.__compare_(__key, __it->first)) {
1027       return __last;
1028     }
1029     return __it;
1030   }
1031 
1032   template <class _Self, class _Kp>
__key_equal_range(_Self && __self,const _Kp & __key)1033   _LIBCPP_HIDE_FROM_ABI static auto __key_equal_range(_Self&& __self, const _Kp& __key) {
1034     auto __it   = ranges::lower_bound(__self.__containers_.keys, __key, __self.__compare_);
1035     auto __last = __self.__containers_.keys.end();
1036     if (__it == __last || __self.__compare_(__key, *__it)) {
1037       return std::make_pair(__it, __it);
1038     }
1039     return std::make_pair(__it, std::next(__it));
1040   }
1041 
1042   template <class _Self, class _Kp>
__equal_range_impl(_Self && __self,const _Kp & __key)1043   _LIBCPP_HIDE_FROM_ABI static auto __equal_range_impl(_Self&& __self, const _Kp& __key) {
1044     auto [__key_first, __key_last] = __key_equal_range(__self, __key);
1045 
1046     const auto __make_mapped_iter = [&](const auto& __key_iter) {
1047       return __self.__containers_.values.begin() +
1048              static_cast<ranges::range_difference_t<mapped_container_type>>(
1049                  ranges::distance(__self.__containers_.keys.begin(), __key_iter));
1050     };
1051 
1052     using __iterator_type = ranges::iterator_t<decltype(__self)>;
1053     return std::make_pair(__iterator_type(__key_first, __make_mapped_iter(__key_first)),
1054                           __iterator_type(__key_last, __make_mapped_iter(__key_last)));
1055   }
1056 
1057   template <class _Res, class _Self, class _Kp>
__lower_bound(_Self && __self,_Kp & __x)1058   _LIBCPP_HIDE_FROM_ABI static _Res __lower_bound(_Self&& __self, _Kp& __x) {
1059     return __binary_search<_Res>(__self, ranges::lower_bound, __x);
1060   }
1061 
1062   template <class _Res, class _Self, class _Kp>
__upper_bound(_Self && __self,_Kp & __x)1063   _LIBCPP_HIDE_FROM_ABI static _Res __upper_bound(_Self&& __self, _Kp& __x) {
1064     return __binary_search<_Res>(__self, ranges::upper_bound, __x);
1065   }
1066 
1067   template <class _Res, class _Self, class _Fn, class _Kp>
__binary_search(_Self && __self,_Fn __search_fn,_Kp & __x)1068   _LIBCPP_HIDE_FROM_ABI static _Res __binary_search(_Self&& __self, _Fn __search_fn, _Kp& __x) {
1069     auto __key_iter = __search_fn(__self.__containers_.keys, __x, __self.__compare_);
1070     auto __mapped_iter =
1071         __self.__containers_.values.begin() +
1072         static_cast<ranges::range_difference_t<mapped_container_type>>(
1073             ranges::distance(__self.__containers_.keys.begin(), __key_iter));
1074 
1075     return _Res(std::move(__key_iter), std::move(__mapped_iter));
1076   }
1077 
1078   template <class _KeyArg, class... _MArgs>
__try_emplace(_KeyArg && __key,_MArgs &&...__mapped_args)1079   _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __try_emplace(_KeyArg&& __key, _MArgs&&... __mapped_args) {
1080     auto __key_it    = ranges::lower_bound(__containers_.keys, __key, __compare_);
1081     auto __mapped_it = __containers_.values.begin() + ranges::distance(__containers_.keys.begin(), __key_it);
1082 
1083     if (__key_it == __containers_.keys.end() || __compare_(__key, *__key_it)) {
1084       return pair<iterator, bool>(
1085           __try_emplace_exact_hint(
1086               std::move(__key_it),
1087               std::move(__mapped_it),
1088               std::forward<_KeyArg>(__key),
1089               std::forward<_MArgs>(__mapped_args)...),
1090           true);
1091     } else {
1092       return pair<iterator, bool>(iterator(std::move(__key_it), std::move(__mapped_it)), false);
1093     }
1094   }
1095 
1096   template <class _Kp>
__is_hint_correct(const_iterator __hint,_Kp && __key)1097   _LIBCPP_HIDE_FROM_ABI bool __is_hint_correct(const_iterator __hint, _Kp&& __key) {
1098     if (__hint != cbegin() && !__compare_((__hint - 1)->first, __key)) {
1099       return false;
1100     }
1101     if (__hint != cend() && __compare_(__hint->first, __key)) {
1102       return false;
1103     }
1104     return true;
1105   }
1106 
1107   template <class _Kp, class... _Args>
__try_emplace_hint(const_iterator __hint,_Kp && __key,_Args &&...__args)1108   _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __try_emplace_hint(const_iterator __hint, _Kp&& __key, _Args&&... __args) {
1109     if (__is_hint_correct(__hint, __key)) {
1110       if (__hint == cend() || __compare_(__key, __hint->first)) {
1111         return {
1112             __try_emplace_exact_hint(
1113                 __hint.__key_iter_, __hint.__mapped_iter_, std::forward<_Kp>(__key), std::forward<_Args>(__args)...),
1114             true};
1115       } else {
1116         // key equals
1117         auto __dist = __hint - cbegin();
1118         return {iterator(__containers_.keys.begin() + __dist, __containers_.values.begin() + __dist), false};
1119       }
1120     } else {
1121       return __try_emplace(std::forward<_Kp>(__key), std::forward<_Args>(__args)...);
1122     }
1123   }
1124 
1125   template <class _IterK, class _IterM, class _KeyArg, class... _MArgs>
1126   _LIBCPP_HIDE_FROM_ABI iterator
__try_emplace_exact_hint(_IterK && __it_key,_IterM && __it_mapped,_KeyArg && __key,_MArgs &&...__mapped_args)1127   __try_emplace_exact_hint(_IterK&& __it_key, _IterM&& __it_mapped, _KeyArg&& __key, _MArgs&&... __mapped_args) {
1128     auto __on_key_failed = std::__make_exception_guard([&]() noexcept {
1129       if constexpr (__container_traits<_KeyContainer>::__emplacement_has_strong_exception_safety_guarantee) {
1130         // Nothing to roll back!
1131       } else {
1132         // we need to clear both because we don't know the state of our keys anymore
1133         clear() /* noexcept */;
1134       }
1135     });
1136     auto __key_it        = __containers_.keys.emplace(__it_key, std::forward<_KeyArg>(__key));
1137     __on_key_failed.__complete();
1138 
1139     auto __on_value_failed = std::__make_exception_guard([&]() noexcept {
1140       if constexpr (!__container_traits<_MappedContainer>::__emplacement_has_strong_exception_safety_guarantee) {
1141         // we need to clear both because we don't know the state of our values anymore
1142         clear() /* noexcept */;
1143       } else {
1144         // In this case, we know the values are just like before we attempted emplacement,
1145         // and we also know that the keys have been emplaced successfully. Just roll back the keys.
1146 #  if _LIBCPP_HAS_EXCEPTIONS
1147         try {
1148 #  endif // _LIBCPP_HAS_EXCEPTIONS
1149           __containers_.keys.erase(__key_it);
1150 #  if _LIBCPP_HAS_EXCEPTIONS
1151         } catch (...) {
1152           // Now things are funky for real. We're failing to rollback the keys.
1153           // Just give up and clear the whole thing.
1154           //
1155           // Also, swallow the exception that happened during the rollback and let the
1156           // original value-emplacement exception propagate normally.
1157           clear() /* noexcept */;
1158         }
1159 #  endif // _LIBCPP_HAS_EXCEPTIONS
1160       }
1161     });
1162     auto __mapped_it = __containers_.values.emplace(__it_mapped, std::forward<_MArgs>(__mapped_args)...);
1163     __on_value_failed.__complete();
1164 
1165     return iterator(std::move(__key_it), std::move(__mapped_it));
1166   }
1167 
1168   template <class _Kp, class _Mapped>
__insert_or_assign(_Kp && __key,_Mapped && __mapped)1169   _LIBCPP_HIDE_FROM_ABI pair<iterator, bool> __insert_or_assign(_Kp&& __key, _Mapped&& __mapped) {
1170     auto __r = try_emplace(std::forward<_Kp>(__key), std::forward<_Mapped>(__mapped));
1171     if (!__r.second) {
1172       __r.first->second = std::forward<_Mapped>(__mapped);
1173     }
1174     return __r;
1175   }
1176 
1177   template <class _Kp, class _Mapped>
__insert_or_assign(const_iterator __hint,_Kp && __key,_Mapped && __mapped)1178   _LIBCPP_HIDE_FROM_ABI iterator __insert_or_assign(const_iterator __hint, _Kp&& __key, _Mapped&& __mapped) {
1179     auto __r = __try_emplace_hint(__hint, std::forward<_Kp>(__key), std::forward<_Mapped>(__mapped));
1180     if (!__r.second) {
1181       __r.first->second = std::forward<_Mapped>(__mapped);
1182     }
1183     return __r.first;
1184   }
1185 
__reserve(size_t __size)1186   _LIBCPP_HIDE_FROM_ABI void __reserve(size_t __size) {
1187     if constexpr (requires { __containers_.keys.reserve(__size); }) {
1188       __containers_.keys.reserve(__size);
1189     }
1190 
1191     if constexpr (requires { __containers_.values.reserve(__size); }) {
1192       __containers_.values.reserve(__size);
1193     }
1194   }
1195 
1196   template <class _KIter, class _MIter>
__erase(_KIter __key_iter_to_remove,_MIter __mapped_iter_to_remove)1197   _LIBCPP_HIDE_FROM_ABI iterator __erase(_KIter __key_iter_to_remove, _MIter __mapped_iter_to_remove) {
1198     auto __on_failure  = std::__make_exception_guard([&]() noexcept { clear() /* noexcept */; });
1199     auto __key_iter    = __containers_.keys.erase(__key_iter_to_remove);
1200     auto __mapped_iter = __containers_.values.erase(__mapped_iter_to_remove);
1201     __on_failure.__complete();
1202     return iterator(std::move(__key_iter), std::move(__mapped_iter));
1203   }
1204 
1205   template <class _Key2, class _Tp2, class _Compare2, class _KeyContainer2, class _MappedContainer2, class _Predicate>
1206   friend typename flat_map<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>::size_type
1207   erase_if(flat_map<_Key2, _Tp2, _Compare2, _KeyContainer2, _MappedContainer2>&, _Predicate);
1208 
1209   containers __containers_;
1210   [[no_unique_address]] key_compare __compare_;
1211 
1212   struct __key_equiv {
__key_equiv__key_equiv1213     _LIBCPP_HIDE_FROM_ABI __key_equiv(key_compare __c) : __comp_(__c) {}
operator__key_equiv1214     _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const {
1215       return !__comp_(std::get<0>(__x), std::get<0>(__y)) && !__comp_(std::get<0>(__y), std::get<0>(__x));
1216     }
1217     key_compare __comp_;
1218   };
1219 };
1220 
1221 template <class _KeyContainer, class _MappedContainer, class _Compare = less<typename _KeyContainer::value_type>>
1222   requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
1223            !__is_allocator<_MappedContainer>::value &&
1224            is_invocable_v<const _Compare&,
1225                           const typename _KeyContainer::value_type&,
1226                           const typename _KeyContainer::value_type&>)
1227 flat_map(_KeyContainer, _MappedContainer, _Compare = _Compare())
1228     -> flat_map<typename _KeyContainer::value_type,
1229                 typename _MappedContainer::value_type,
1230                 _Compare,
1231                 _KeyContainer,
1232                 _MappedContainer>;
1233 
1234 template <class _KeyContainer, class _MappedContainer, class _Allocator>
1235   requires(uses_allocator_v<_KeyContainer, _Allocator> && uses_allocator_v<_MappedContainer, _Allocator> &&
1236            !__is_allocator<_KeyContainer>::value && !__is_allocator<_MappedContainer>::value)
1237 flat_map(_KeyContainer, _MappedContainer, _Allocator)
1238     -> flat_map<typename _KeyContainer::value_type,
1239                 typename _MappedContainer::value_type,
1240                 less<typename _KeyContainer::value_type>,
1241                 _KeyContainer,
1242                 _MappedContainer>;
1243 
1244 template <class _KeyContainer, class _MappedContainer, class _Compare, class _Allocator>
1245   requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
1246            !__is_allocator<_MappedContainer>::value && uses_allocator_v<_KeyContainer, _Allocator> &&
1247            uses_allocator_v<_MappedContainer, _Allocator> &&
1248            is_invocable_v<const _Compare&,
1249                           const typename _KeyContainer::value_type&,
1250                           const typename _KeyContainer::value_type&>)
1251 flat_map(_KeyContainer, _MappedContainer, _Compare, _Allocator)
1252     -> flat_map<typename _KeyContainer::value_type,
1253                 typename _MappedContainer::value_type,
1254                 _Compare,
1255                 _KeyContainer,
1256                 _MappedContainer>;
1257 
1258 template <class _KeyContainer, class _MappedContainer, class _Compare = less<typename _KeyContainer::value_type>>
1259   requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
1260            !__is_allocator<_MappedContainer>::value &&
1261            is_invocable_v<const _Compare&,
1262                           const typename _KeyContainer::value_type&,
1263                           const typename _KeyContainer::value_type&>)
1264 flat_map(sorted_unique_t, _KeyContainer, _MappedContainer, _Compare = _Compare())
1265     -> flat_map<typename _KeyContainer::value_type,
1266                 typename _MappedContainer::value_type,
1267                 _Compare,
1268                 _KeyContainer,
1269                 _MappedContainer>;
1270 
1271 template <class _KeyContainer, class _MappedContainer, class _Allocator>
1272   requires(uses_allocator_v<_KeyContainer, _Allocator> && uses_allocator_v<_MappedContainer, _Allocator> &&
1273            !__is_allocator<_KeyContainer>::value && !__is_allocator<_MappedContainer>::value)
1274 flat_map(sorted_unique_t, _KeyContainer, _MappedContainer, _Allocator)
1275     -> flat_map<typename _KeyContainer::value_type,
1276                 typename _MappedContainer::value_type,
1277                 less<typename _KeyContainer::value_type>,
1278                 _KeyContainer,
1279                 _MappedContainer>;
1280 
1281 template <class _KeyContainer, class _MappedContainer, class _Compare, class _Allocator>
1282   requires(!__is_allocator<_Compare>::value && !__is_allocator<_KeyContainer>::value &&
1283            !__is_allocator<_MappedContainer>::value && uses_allocator_v<_KeyContainer, _Allocator> &&
1284            uses_allocator_v<_MappedContainer, _Allocator> &&
1285            is_invocable_v<const _Compare&,
1286                           const typename _KeyContainer::value_type&,
1287                           const typename _KeyContainer::value_type&>)
1288 flat_map(sorted_unique_t, _KeyContainer, _MappedContainer, _Compare, _Allocator)
1289     -> flat_map<typename _KeyContainer::value_type,
1290                 typename _MappedContainer::value_type,
1291                 _Compare,
1292                 _KeyContainer,
1293                 _MappedContainer>;
1294 
1295 template <class _InputIterator, class _Compare = less<__iter_key_type<_InputIterator>>>
1296   requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value)
1297 flat_map(_InputIterator, _InputIterator, _Compare = _Compare())
1298     -> flat_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Compare>;
1299 
1300 template <class _InputIterator, class _Compare = less<__iter_key_type<_InputIterator>>>
1301   requires(__has_input_iterator_category<_InputIterator>::value && !__is_allocator<_Compare>::value)
1302 flat_map(sorted_unique_t, _InputIterator, _InputIterator, _Compare = _Compare())
1303     -> flat_map<__iter_key_type<_InputIterator>, __iter_mapped_type<_InputIterator>, _Compare>;
1304 
1305 template <ranges::input_range _Range,
1306           class _Compare   = less<__range_key_type<_Range>>,
1307           class _Allocator = allocator<byte>,
1308           class            = __enable_if_t<!__is_allocator<_Compare>::value && __is_allocator<_Allocator>::value>>
1309 flat_map(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator())
1310     -> flat_map<
1311         __range_key_type<_Range>,
1312         __range_mapped_type<_Range>,
1313         _Compare,
1314         vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
1315         vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
1316 
1317 template <ranges::input_range _Range, class _Allocator, class = __enable_if_t<__is_allocator<_Allocator>::value>>
1318 flat_map(from_range_t, _Range&&, _Allocator)
1319     -> flat_map<
1320         __range_key_type<_Range>,
1321         __range_mapped_type<_Range>,
1322         less<__range_key_type<_Range>>,
1323         vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
1324         vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
1325 
1326 template <class _Key, class _Tp, class _Compare = less<_Key>>
1327   requires(!__is_allocator<_Compare>::value)
1328 flat_map(initializer_list<pair<_Key, _Tp>>, _Compare = _Compare()) -> flat_map<_Key, _Tp, _Compare>;
1329 
1330 template <class _Key, class _Tp, class _Compare = less<_Key>>
1331   requires(!__is_allocator<_Compare>::value)
1332 flat_map(sorted_unique_t, initializer_list<pair<_Key, _Tp>>, _Compare = _Compare()) -> flat_map<_Key, _Tp, _Compare>;
1333 
1334 template <class _Key, class _Tp, class _Compare, class _KeyContainer, class _MappedContainer, class _Allocator>
1335 struct uses_allocator<flat_map<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>, _Allocator>
1336     : bool_constant<uses_allocator_v<_KeyContainer, _Allocator> && uses_allocator_v<_MappedContainer, _Allocator>> {};
1337 
1338 template <class _Key, class _Tp, class _Compare, class _KeyContainer, class _MappedContainer, class _Predicate>
1339 _LIBCPP_HIDE_FROM_ABI typename flat_map<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::size_type
1340 erase_if(flat_map<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>& __flat_map, _Predicate __pred) {
1341   auto __zv     = ranges::views::zip(__flat_map.__containers_.keys, __flat_map.__containers_.values);
1342   auto __first  = __zv.begin();
1343   auto __last   = __zv.end();
1344   auto __guard  = std::__make_exception_guard([&] { __flat_map.clear(); });
1345   auto __it     = std::remove_if(__first, __last, [&](auto&& __zipped) -> bool {
1346     using _Ref = typename flat_map<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::const_reference;
1347     return __pred(_Ref(std::get<0>(__zipped), std::get<1>(__zipped)));
1348   });
1349   auto __res    = __last - __it;
1350   auto __offset = __it - __first;
1351 
1352   const auto __erase_container = [&](auto& __cont) { __cont.erase(__cont.begin() + __offset, __cont.end()); };
1353 
1354   __erase_container(__flat_map.__containers_.keys);
1355   __erase_container(__flat_map.__containers_.values);
1356 
1357   __guard.__complete();
1358   return __res;
1359 }
1360 
1361 _LIBCPP_END_NAMESPACE_STD
1362 
1363 #endif // _LIBCPP_STD_VER >= 23
1364 
1365 _LIBCPP_POP_MACROS
1366 
1367 #endif // _LIBCPP___FLAT_MAP_FLAT_MAP_H
1368