Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/libcxx/include/__flat_map/flat_multimap.h
213766 views
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_;
117
_LIBCPP_HIDE_FROM_ABI value_compare(key_compare __c) : __comp_(__c) {}
118
friend flat_multimap;
119
120
public:
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
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.
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>
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>
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
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>
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
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
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
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
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>
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>
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())
282
: __containers_(), __compare_(__comp) {
283
insert(__first, __last);
284
}
285
286
template <class _InputIterator, class _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>
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>
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>
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>
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>
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())
328
: __containers_(), __compare_(__comp) {
329
insert(sorted_equivalent, __first, __last);
330
}
331
template <class _InputIterator, class _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>
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
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>
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>
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>
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
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
403
_LIBCPP_HIDE_FROM_ABI iterator begin() noexcept {
404
return iterator(__containers_.keys.begin(), __containers_.values.begin());
405
}
406
407
_LIBCPP_HIDE_FROM_ABI const_iterator begin() const noexcept {
408
return const_iterator(__containers_.keys.begin(), __containers_.values.begin());
409
}
410
411
_LIBCPP_HIDE_FROM_ABI iterator end() noexcept {
412
return iterator(__containers_.keys.end(), __containers_.values.end());
413
}
414
415
_LIBCPP_HIDE_FROM_ABI const_iterator end() const noexcept {
416
return const_iterator(__containers_.keys.end(), __containers_.values.end());
417
}
418
419
_LIBCPP_HIDE_FROM_ABI reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
420
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
421
_LIBCPP_HIDE_FROM_ABI reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
422
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
423
424
_LIBCPP_HIDE_FROM_ABI const_iterator cbegin() const noexcept { return begin(); }
425
_LIBCPP_HIDE_FROM_ABI const_iterator cend() const noexcept { return end(); }
426
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
427
_LIBCPP_HIDE_FROM_ABI const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
428
429
// [flat.map.capacity], capacity
430
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI bool empty() const noexcept { return __containers_.keys.empty(); }
431
432
_LIBCPP_HIDE_FROM_ABI size_type size() const noexcept { return __containers_.keys.size(); }
433
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>
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...>
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
493
_LIBCPP_HIDE_FROM_ABI iterator insert(const value_type& __x) { return emplace(__x); }
494
495
_LIBCPP_HIDE_FROM_ABI iterator insert(value_type&& __x) { return emplace(std::move(__x)); }
496
497
_LIBCPP_HIDE_FROM_ABI iterator insert(const_iterator __hint, const value_type& __x) {
498
return emplace_hint(__hint, __x);
499
}
500
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>
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>
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
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
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>
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
545
_LIBCPP_HIDE_FROM_ABI void insert(initializer_list<value_type> __il) { insert(__il.begin(), __il.end()); }
546
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
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
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
568
_LIBCPP_HIDE_FROM_ABI iterator erase(iterator __position) {
569
return __erase(__position.__key_iter_, __position.__mapped_iter_);
570
}
571
572
_LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __position) {
573
return __erase(__position.__key_iter_, __position.__mapped_iter_);
574
}
575
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>)
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
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
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
610
_LIBCPP_HIDE_FROM_ABI void clear() noexcept {
611
__containers_.keys.clear();
612
__containers_.values.clear();
613
}
614
615
// observers
616
_LIBCPP_HIDE_FROM_ABI key_compare key_comp() const { return __compare_; }
617
_LIBCPP_HIDE_FROM_ABI value_compare value_comp() const { return value_compare(__compare_); }
618
619
_LIBCPP_HIDE_FROM_ABI const key_container_type& keys() const noexcept { return __containers_.keys; }
620
_LIBCPP_HIDE_FROM_ABI const mapped_container_type& values() const noexcept { return __containers_.values; }
621
622
// map operations
623
_LIBCPP_HIDE_FROM_ABI iterator find(const key_type& __x) { return __find_impl(*this, __x); }
624
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
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
635
_LIBCPP_HIDE_FROM_ABI const_iterator find(const _Kp& __x) const {
636
return __find_impl(*this, __x);
637
}
638
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
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
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
655
_LIBCPP_HIDE_FROM_ABI bool contains(const _Kp& __x) const {
656
return find(__x) != end();
657
}
658
659
_LIBCPP_HIDE_FROM_ABI iterator lower_bound(const key_type& __x) { return __lower_bound<iterator>(*this, __x); }
660
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
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
673
_LIBCPP_HIDE_FROM_ABI const_iterator lower_bound(const _Kp& __x) const {
674
return __lower_bound<const_iterator>(*this, __x);
675
}
676
677
_LIBCPP_HIDE_FROM_ABI iterator upper_bound(const key_type& __x) { return __upper_bound<iterator>(*this, __x); }
678
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
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
691
_LIBCPP_HIDE_FROM_ABI const_iterator upper_bound(const _Kp& __x) const {
692
return __upper_bound<const_iterator>(*this, __x);
693
}
694
695
_LIBCPP_HIDE_FROM_ABI pair<iterator, iterator> equal_range(const key_type& __x) {
696
return __equal_range_impl(*this, __x);
697
}
698
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
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
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
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
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>
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
754
_LIBCPP_HIDE_FROM_ABI bool __is_sorted(auto&& __key_container) const {
755
return ranges::is_sorted(__key_container, __compare_);
756
}
757
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>
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>
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>
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>
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>
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>
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
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>
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 {
858
_LIBCPP_HIDE_FROM_ABI __key_equiv(key_compare __c) : __comp_(__c) {}
859
_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
1013