-
Notifications
You must be signed in to change notification settings - Fork 12.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[libc++] implement std::flat_multimap
#113835
base: main
Are you sure you want to change the base?
Conversation
You can test this locally with the following command:git-clang-format --diff 213b849c5e2118e44f3b13de43749c4ddb26598f 373b39c6b3f63c813569b4087e4672a3c8fd4589 --extensions ,inc,h,cpp -- libcxx/include/__flat_map/flat_multimap.h libcxx/include/__flat_map/key_value_iterator.h libcxx/include/__flat_map/sorted_equivalent.h libcxx/test/std/containers/container.adaptors/flat.map.syn/sorted_equivalent.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.capacity/empty.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.capacity/empty.verify.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.capacity/max_size.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.capacity/size.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/alloc.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/assign_initializer_list.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/compare.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/containers.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/copy.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/copy_alloc.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/copy_assign.addressof.compile.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/copy_assign.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/deduct.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/deduct.verify.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/deduct_pmr.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/default.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/default_noexcept.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/dtor_noexcept.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/initializer_list.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/iter_iter.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/iter_iter_stability.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/move.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/move_alloc.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/move_assign.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/move_assign_clears.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/move_assign_noexcept.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/move_exceptions.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/move_noexcept.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/pmr.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/range.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/sorted_container.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/sorted_initializer_list.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.cons/sorted_iter_iter.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.erasure/erase_if.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.erasure/erase_if_exceptions.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.iterators/iterator.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.iterators/iterator_comparison.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.iterators/iterator_concept_conformance.compile.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.iterators/range_concept_conformance.compile.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.iterators/reverse_iterator.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/clear.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/emplace.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/emplace_hint.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/erase_iter.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/erase_iter_iter.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/erase_key.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/erase_key_transparent.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/extract.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_cv.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_initializer_list.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_iter_cv.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_iter_iter.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_iter_rv.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_range.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_range_stability.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_rv.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_sorted_initializer_list.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_sorted_iter_iter.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_transparent.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/replace.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/swap_exception.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/swap_free.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/swap_member.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.observers/comp.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.observers/keys_values.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.operations/contains.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.operations/contains_transparent.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.operations/count.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.operations/count_transparent.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.operations/equal_range.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.operations/equal_range_transparent.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.operations/find.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.operations/find_transparent.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.operations/lower_bound.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.operations/lower_bound_transparent.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.operations/upper_bound.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.operations/upper_bound_transparent.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/helpers.h libcxx/test/std/containers/container.adaptors/flat.multimap/incomplete_type.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/op_compare.pass.cpp libcxx/test/std/containers/container.adaptors/flat.multimap/types.compile.pass.cpp libcxx/test/std/language.support/support.limits/support.limits.general/flat_map.version.compile.pass.cpp libcxx/include/__flat_map/flat_map.h libcxx/include/flat_map libcxx/include/version libcxx/modules/std/flat_map.inc libcxx/test/std/containers/container.adaptors/flat.map/flat.map.cons/iter_iter_stability.pass.cpp libcxx/test/std/containers/container.adaptors/flat.map/flat.map.iterators/reverse_iterator.pass.cpp libcxx/test/std/containers/container.adaptors/flat.map/incomplete_type.pass.cpp libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp View the diff from clang-format here.diff --git a/libcxx/include/__flat_map/flat_map.h b/libcxx/include/__flat_map/flat_map.h
index 13877749d2..b66bc1cb66 100644
--- a/libcxx/include/__flat_map/flat_map.h
+++ b/libcxx/include/__flat_map/flat_map.h
@@ -1189,20 +1189,22 @@ template <ranges::input_range _Range,
class _Compare = less<__range_key_type<_Range>>,
class _Allocator = allocator<byte>,
class = __enable_if_t<!__is_allocator<_Compare>::value && __is_allocator<_Allocator>::value>>
-flat_map(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) -> flat_map<
- __range_key_type<_Range>,
- __range_mapped_type<_Range>,
- _Compare,
- vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
- vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
+flat_map(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator())
+ -> flat_map<
+ __range_key_type<_Range>,
+ __range_mapped_type<_Range>,
+ _Compare,
+ vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
+ vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
template <ranges::input_range _Range, class _Allocator, class = __enable_if_t<__is_allocator<_Allocator>::value>>
-flat_map(from_range_t, _Range&&, _Allocator) -> flat_map<
- __range_key_type<_Range>,
- __range_mapped_type<_Range>,
- less<__range_key_type<_Range>>,
- vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
- vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
+flat_map(from_range_t, _Range&&, _Allocator)
+ -> flat_map<
+ __range_key_type<_Range>,
+ __range_mapped_type<_Range>,
+ less<__range_key_type<_Range>>,
+ vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
+ vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
template <class _Key, class _Tp, class _Compare = less<_Key>>
requires(!__is_allocator<_Compare>::value)
diff --git a/libcxx/include/__flat_map/flat_multimap.h b/libcxx/include/__flat_map/flat_multimap.h
index 7bfa230956..bd4c08903f 100644
--- a/libcxx/include/__flat_map/flat_multimap.h
+++ b/libcxx/include/__flat_map/flat_multimap.h
@@ -1011,20 +1011,22 @@ template <ranges::input_range _Range,
class _Compare = less<__range_key_type<_Range>>,
class _Allocator = allocator<byte>,
class = __enable_if_t<!__is_allocator<_Compare>::value && __is_allocator<_Allocator>::value>>
-flat_multimap(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator()) -> flat_multimap<
- __range_key_type<_Range>,
- __range_mapped_type<_Range>,
- _Compare,
- vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
- vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
+flat_multimap(from_range_t, _Range&&, _Compare = _Compare(), _Allocator = _Allocator())
+ -> flat_multimap<
+ __range_key_type<_Range>,
+ __range_mapped_type<_Range>,
+ _Compare,
+ vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
+ vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
template <ranges::input_range _Range, class _Allocator, class = __enable_if_t<__is_allocator<_Allocator>::value>>
-flat_multimap(from_range_t, _Range&&, _Allocator) -> flat_multimap<
- __range_key_type<_Range>,
- __range_mapped_type<_Range>,
- less<__range_key_type<_Range>>,
- vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
- vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
+flat_multimap(from_range_t, _Range&&, _Allocator)
+ -> flat_multimap<
+ __range_key_type<_Range>,
+ __range_mapped_type<_Range>,
+ less<__range_key_type<_Range>>,
+ vector<__range_key_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_key_type<_Range>>>,
+ vector<__range_mapped_type<_Range>, __allocator_traits_rebind_t<_Allocator, __range_mapped_type<_Range>>>>;
template <class _Key, class _Tp, class _Compare = less<_Key>>
requires(!__is_allocator<_Compare>::value)
diff --git a/libcxx/include/flat_map b/libcxx/include/flat_map
index 84345719b8..043f8ed956 100644
--- a/libcxx/include/flat_map
+++ b/libcxx/include/flat_map
@@ -61,8 +61,8 @@ namespace std {
#include <__flat_map/flat_map.h>
#include <__flat_map/flat_multimap.h>
#include <__flat_map/key_value_iterator.h>
-#include <__flat_map/sorted_unique.h>
#include <__flat_map/sorted_equivalent.h>
+#include <__flat_map/sorted_unique.h>
#include <version>
// standard required includes
diff --git a/libcxx/test/std/containers/container.adaptors/flat.map.syn/sorted_equivalent.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.map.syn/sorted_equivalent.pass.cpp
index d9ee3fbd28..559d0c2ff9 100644
--- a/libcxx/test/std/containers/container.adaptors/flat.map.syn/sorted_equivalent.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/flat.map.syn/sorted_equivalent.pass.cpp
@@ -29,15 +29,9 @@ static_assert(std::is_trivially_default_constructible_v<std::sorted_equivalent_t
static_assert(!HasImplicitDefaultCtor<std::sorted_equivalent_t>);
constexpr bool test() {
- {
- [[maybe_unused]] std::sorted_equivalent_t s;
- }
- {
- [[maybe_unused]] std::same_as<const std::sorted_equivalent_t&> decltype(auto) s = (std::sorted_equivalent);
- }
- {
- [[maybe_unused]] std::same_as<const std::sorted_equivalent_t> decltype(auto) copy = std::sorted_equivalent;
- }
+ { [[maybe_unused]] std::sorted_equivalent_t s; }
+ { [[maybe_unused]] std::same_as<const std::sorted_equivalent_t&> decltype(auto) s = (std::sorted_equivalent); }
+ { [[maybe_unused]] std::same_as<const std::sorted_equivalent_t> decltype(auto) copy = std::sorted_equivalent; }
return true;
}
diff --git a/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.erasure/erase_if_exceptions.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.erasure/erase_if_exceptions.pass.cpp
index d691535c24..13b57202f7 100644
--- a/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.erasure/erase_if_exceptions.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.erasure/erase_if_exceptions.pass.cpp
@@ -124,8 +124,8 @@ int main(int, char**) {
}
}
{
- using M =
- std::flat_multimap<ThrowingAssignment, int, ThrowingComparator, std::deque<ThrowingAssignment>, std::deque<int>>;
+ using M = std::
+ flat_multimap<ThrowingAssignment, int, ThrowingComparator, std::deque<ThrowingAssignment>, std::deque<int>>;
for (int first_throw = 1; first_throw < 99; ++first_throw) {
for (int second_throw = 1; second_throw < 99; ++second_throw) {
g_counter = {0, 0, 0};
diff --git a/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_cv.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_cv.pass.cpp
index 3646595624..88c173d8a6 100644
--- a/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_cv.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.modifiers/insert_cv.pass.cpp
@@ -49,14 +49,14 @@ void test() {
const VT v3(3, 3.5);
r = m.insert(v3);
- assert(r == m.begin()+ 2);
+ assert(r == m.begin() + 2);
assert(m.size() == 3);
assert(r->first == 3);
assert(r->second == 3.5);
const VT v4(3, 4.5);
r = m.insert(v4);
- assert(r == m.begin()+ 3);
+ assert(r == m.begin() + 3);
assert(m.size() == 4);
assert(r->first == 3);
assert(r->second == 4.5);
diff --git a/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.operations/find_transparent.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.operations/find_transparent.pass.cpp
index 7bbdcd3894..be8c6f2e35 100644
--- a/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.operations/find_transparent.pass.cpp
+++ b/libcxx/test/std/containers/container.adaptors/flat.multimap/flat.multimap.operations/find_transparent.pass.cpp
@@ -88,7 +88,7 @@ int main(int, char**) {
{
bool transparent_used = false;
TransparentComparator c(transparent_used);
- std::flat_multimap<int, int, TransparentComparator> m(std::sorted_equivalent, {{1, 1}, {2, 2}, {3,3}, {3, 3}}, c);
+ std::flat_multimap<int, int, TransparentComparator> m(std::sorted_equivalent, {{1, 1}, {2, 2}, {3, 3}, {3, 3}}, c);
assert(!transparent_used);
auto it = m.find(Transparent<int>{3});
assert(it != m.end());
|
c929bc1
to
9066da5
Compare
@llvm/pr-subscribers-libcxx Author: Hui (huixie90) Changesfixes #105190 Patch is 418.31 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/113835.diff 90 Files Affected:
diff --git a/libcxx/docs/Status/Cxx23Papers.csv b/libcxx/docs/Status/Cxx23Papers.csv
index 6f1626da73507e..d6d45051cca283 100644
--- a/libcxx/docs/Status/Cxx23Papers.csv
+++ b/libcxx/docs/Status/Cxx23Papers.csv
@@ -52,7 +52,7 @@
"`P2443R1 <https://wg21.link/P2443R1>`__","``views::chunk_by``","2022-02 (Virtual)","|Complete|","18.0",""
"","","","","",""
"`P0009R18 <https://wg21.link/P0009R18>`__","mdspan: A Non-Owning Multidimensional Array Reference","2022-07 (Virtual)","|Complete|","18.0",""
-"`P0429R9 <https://wg21.link/P0429R9>`__","A Standard ``flat_map``","2022-07 (Virtual)","|In progress|","",""
+"`P0429R9 <https://wg21.link/P0429R9>`__","A Standard ``flat_map``","2022-07 (Virtual)","|Complete|","20.0",""
"`P1169R4 <https://wg21.link/P1169R4>`__","``static operator()``","2022-07 (Virtual)","|Complete|","16.0",""
"`P1222R4 <https://wg21.link/P1222R4>`__","A Standard ``flat_set``","2022-07 (Virtual)","","",""
"`P1223R5 <https://wg21.link/P1223R5>`__","``ranges::find_last()``, ``ranges::find_last_if()``, and ``ranges::find_last_if_not()``","2022-07 (Virtual)","|Complete|","19.0",""
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 87eaf64b245017..f8aaa1027034ce 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -359,7 +359,9 @@ set(files
__filesystem/space_info.h
__filesystem/u8path.h
__flat_map/flat_map.h
+ __flat_map/flat_multimap.h
__flat_map/sorted_unique.h
+ __flat_map/sorted_equivalent.h
__format/buffer.h
__format/concepts.h
__format/container_adaptor.h
diff --git a/libcxx/include/__flat_map/flat_multimap.h b/libcxx/include/__flat_map/flat_multimap.h
new file mode 100644
index 00000000000000..ac46a8597e3780
--- /dev/null
+++ b/libcxx/include/__flat_map/flat_multimap.h
@@ -0,0 +1,1182 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___FLAT_MAP_FLAT_MULTIMAP_H
+#define _LIBCPP___FLAT_MAP_FLAT_MULTIMAP_H
+
+#include <__algorithm/lexicographical_compare_three_way.h>
+#include <__algorithm/ranges_equal.h>
+#include <__algorithm/ranges_equal_range.h>
+#include <__algorithm/ranges_inplace_merge.h>
+#include <__algorithm/ranges_is_sorted.h>
+#include <__algorithm/ranges_lower_bound.h>
+#include <__algorithm/ranges_partition_point.h>
+#include <__algorithm/ranges_stable_sort.h>
+#include <__algorithm/ranges_unique.h>
+#include <__algorithm/ranges_upper_bound.h>
+#include <__compare/synth_three_way.h>
+#include <__concepts/convertible_to.h>
+#include <__concepts/swappable.h>
+#include <__config>
+#include <__flat_map/sorted_equivalent.h>
+#include <__functional/invoke.h>
+#include <__functional/is_transparent.h>
+#include <__functional/operations.h>
+#include <__iterator/concepts.h>
+#include <__iterator/distance.h>
+#include <__iterator/iterator_traits.h>
+#include <__iterator/ranges_iterator_traits.h>
+#include <__iterator/reverse_iterator.h>
+#include <__memory/allocator_traits.h>
+#include <__memory/uses_allocator.h>
+#include <__memory/uses_allocator_construction.h>
+#include <__ranges/concepts.h>
+#include <__ranges/container_compatible_range.h>
+#include <__ranges/drop_view.h>
+#include <__ranges/ref_view.h>
+#include <__ranges/subrange.h>
+#include <__ranges/zip_view.h>
+#include <__type_traits/conjunction.h>
+#include <__type_traits/container_traits.h>
+#include <__type_traits/invoke.h>
+#include <__type_traits/is_allocator.h>
+#include <__type_traits/is_nothrow_constructible.h>
+#include <__type_traits/is_same.h>
+#include <__type_traits/maybe_const.h>
+#include <__utility/exception_guard.h>
+#include <__utility/pair.h>
+#include <initializer_list>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#if _LIBCPP_STD_VER >= 23
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _Key,
+ class _Tp,
+ class _Compare = less<_Key>,
+ class _KeyContainer = vector<_Key>,
+ class _MappedContainer = vector<_Tp>>
+class flat_multimap {
+ template <bool _Const>
+ struct __iterator;
+
+ template <class, class, class, class, class>
+ friend class flat_multimap;
+
+ static_assert(is_same_v<_Key, typename _KeyContainer::value_type>);
+ static_assert(is_same_v<_Tp, typename _MappedContainer::value_type>);
+ static_assert(!is_same_v<_KeyContainer, std::vector<bool>>, "vector<bool> is not a sequence container");
+ static_assert(!is_same_v<_MappedContainer, std::vector<bool>>, "vector<bool> is not a sequence container");
+
+public:
+ // types
+ using key_type = _Key;
+ using mapped_type = _Tp;
+ using value_type = pair<key_type, mapped_type>;
+ using key_compare = __type_identity_t<_Compare>;
+ using reference = pair<const key_type&, mapped_type&>;
+ using const_reference = pair<const key_type&, const mapped_type&>;
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+ using iterator = __iterator<false>; // see [container.requirements]
+ using const_iterator = __iterator<true>; // see [container.requirements]
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ using key_container_type = _KeyContainer;
+ using mapped_container_type = _MappedContainer;
+
+ class value_compare {
+ private:
+ key_compare __comp_;
+ value_compare(key_compare __c) : __comp_(__c) {}
+ friend flat_multimap;
+
+ public:
+ _LIBCPP_HIDE_FROM_ABI bool operator()(const_reference __x, const_reference __y) const {
+ return __comp_(__x.first, __y.first);
+ }
+ };
+
+ struct containers {
+ key_container_type keys;
+ mapped_container_type values;
+ };
+
+private:
+ template <class _Allocator>
+ _LIBCPP_HIDE_FROM_ABI static constexpr bool __allocator_ctor_constraint =
+ _And<uses_allocator<key_container_type, _Allocator>, uses_allocator<mapped_container_type, _Allocator>>::value;
+
+ _LIBCPP_HIDE_FROM_ABI static constexpr bool __is_compare_transparent = __is_transparent_v<_Compare, _Compare>;
+
+ template <bool _Const>
+ struct __iterator {
+ private:
+ using __key_iterator = ranges::iterator_t<const key_container_type>;
+ using __mapped_iterator = ranges::iterator_t<__maybe_const<_Const, mapped_container_type>>;
+ using __reference = pair<iter_reference_t<__key_iterator>, iter_reference_t<__mapped_iterator>>;
+
+ struct __arrow_proxy {
+ __reference __ref_;
+ _LIBCPP_HIDE_FROM_ABI __reference* operator->() { return std::addressof(__ref_); }
+ };
+
+ __key_iterator __key_iter_;
+ __mapped_iterator __mapped_iter_;
+
+ friend flat_multimap;
+
+ public:
+ using iterator_concept = random_access_iterator_tag;
+ // `flat_multimap::iterator` only satisfy "Cpp17InputIterator" named requirements, because
+ // its `reference` is not a reference type.
+ // However, to avoid surprising runtime behaviour when it is used with the
+ // Cpp17 algorithms or operations, iterator_category is set to random_access_iterator_tag.
+ using iterator_category = random_access_iterator_tag;
+ using value_type = flat_multimap::value_type;
+ using difference_type = flat_multimap::difference_type;
+
+ _LIBCPP_HIDE_FROM_ABI __iterator() = default;
+
+ _LIBCPP_HIDE_FROM_ABI __iterator(__iterator<!_Const> __i)
+ requires _Const && convertible_to<ranges::iterator_t<key_container_type>, __key_iterator> &&
+ convertible_to<ranges::iterator_t<mapped_container_type>, __mapped_iterator>
+ : __key_iter_(std::move(__i.__key_iter_)), __mapped_iter_(std::move(__i.__mapped_iter_)) {}
+
+ _LIBCPP_HIDE_FROM_ABI __iterator(__key_iterator __key_iter, __mapped_iterator __mapped_iter)
+ : __key_iter_(std::move(__key_iter)), __mapped_iter_(std::move(__mapped_iter)) {}
+
+ _LIBCPP_HIDE_FROM_ABI __reference operator*() const { return __reference(*__key_iter_, *__mapped_iter_); }
+ _LIBCPP_HIDE_FROM_ABI __arrow_proxy operator->() const { return __arrow_proxy(**this); }
+
+ _LIBCPP_HIDE_FROM_ABI __iterator& operator++() {
+ ++__key_iter_;
+ ++__mapped_iter_;
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI __iterator operator++(int) {
+ __iterator __tmp(*this);
+ ++*this;
+ return __tmp;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI __iterator& operator--() {
+ --__key_iter_;
+ --__mapped_iter_;
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI __iterator operator--(int) {
+ __iterator __tmp(*this);
+ --*this;
+ return __tmp;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI __iterator& operator+=(difference_type __x) {
+ __key_iter_ += __x;
+ __mapped_iter_ += __x;
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI __iterator& operator-=(difference_type __x) {
+ __key_iter_ -= __x;
+ __mapped_iter_ -= __x;
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI __reference operator[](difference_type __n) const { return *(*this + __n); }
+
+ _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) {
+ return __x.__key_iter_ == __y.__key_iter_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend bool operator<(const __iterator& __x, const __iterator& __y) {
+ return __x.__key_iter_ < __y.__key_iter_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend bool operator>(const __iterator& __x, const __iterator& __y) { return __y < __x; }
+
+ _LIBCPP_HIDE_FROM_ABI friend bool operator<=(const __iterator& __x, const __iterator& __y) { return !(__y < __x); }
+
+ _LIBCPP_HIDE_FROM_ABI friend bool operator>=(const __iterator& __x, const __iterator& __y) { return !(__x < __y); }
+
+ _LIBCPP_HIDE_FROM_ABI friend auto operator<=>(const __iterator& __x, const __iterator& __y)
+ requires three_way_comparable<__key_iterator>
+ {
+ return __x.__key_iter_ <=> __y.__key_iter_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend __iterator operator+(const __iterator& __i, difference_type __n) {
+ auto __tmp = __i;
+ __tmp += __n;
+ return __tmp;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend __iterator operator+(difference_type __n, const __iterator& __i) { return __i + __n; }
+
+ _LIBCPP_HIDE_FROM_ABI friend __iterator operator-(const __iterator& __i, difference_type __n) {
+ auto __tmp = __i;
+ __tmp -= __n;
+ return __tmp;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI friend difference_type operator-(const __iterator& __x, const __iterator& __y) {
+ return difference_type(__x.__key_iter_ - __y.__key_iter_);
+ }
+ };
+
+public:
+ // [flat.map.cons], construct/copy/destroy
+ _LIBCPP_HIDE_FROM_ABI flat_multimap() noexcept(
+ is_nothrow_default_constructible_v<_KeyContainer> && is_nothrow_default_constructible_v<_MappedContainer> &&
+ is_nothrow_default_constructible_v<_Compare>)
+ : __containers_(), __compare_() {}
+
+ _LIBCPP_HIDE_FROM_ABI flat_multimap(const flat_multimap&) = default;
+
+ // The copy/move constructors are not specified in the spec, which means they should be defaulted.
+ // However, the move constructor can potentially leave a moved-from object in an inconsistent
+ // state if an exception is thrown.
+ _LIBCPP_HIDE_FROM_ABI flat_multimap(flat_multimap&& __other) noexcept(
+ is_nothrow_move_constructible_v<_KeyContainer> && is_nothrow_move_constructible_v<_MappedContainer> &&
+ is_nothrow_move_constructible_v<_Compare>)
+# if _LIBCPP_HAS_EXCEPTIONS
+ try
+# endif // _LIBCPP_HAS_EXCEPTIONS
+ : __containers_(std::move(__other.__containers_)), __compare_(std::move(__other.__compare_)) {
+ __other.clear();
+# if _LIBCPP_HAS_EXCEPTIONS
+ } catch (...) {
+ __other.clear();
+ // gcc does not like the `throw` keyword in a conditional noexcept function
+ if constexpr (!(is_nothrow_move_constructible_v<_KeyContainer> &&
+ is_nothrow_move_constructible_v<_MappedContainer> && is_nothrow_move_constructible_v<_Compare>)) {
+ throw;
+ }
+# endif // _LIBCPP_HAS_EXCEPTIONS
+ }
+
+ template <class _Allocator>
+ requires __allocator_ctor_constraint<_Allocator>
+ _LIBCPP_HIDE_FROM_ABI flat_multimap(const flat_multimap& __other, const _Allocator& __alloc)
+ : flat_multimap(__ctor_uses_allocator_tag{},
+ __alloc,
+ __other.__containers_.keys,
+ __other.__containers_.values,
+ __other.__compare_) {}
+
+ template <class _Allocator>
+ requires __allocator_ctor_constraint<_Allocator>
+ _LIBCPP_HIDE_FROM_ABI flat_multimap(flat_multimap&& __other, const _Allocator& __alloc)
+# if _LIBCPP_HAS_EXCEPTIONS
+ try
+# endif // _LIBCPP_HAS_EXCEPTIONS
+ : flat_multimap(__ctor_uses_allocator_tag{},
+ __alloc,
+ std::move(__other.__containers_.keys),
+ std::move(__other.__containers_.values),
+ std::move(__other.__compare_)) {
+ __other.clear();
+# if _LIBCPP_HAS_EXCEPTIONS
+ } catch (...) {
+ __other.clear();
+ throw;
+# endif // _LIBCPP_HAS_EXCEPTIONS
+ }
+
+ _LIBCPP_HIDE_FROM_ABI flat_multimap(
+ key_container_type __key_cont, mapped_container_type __mapped_cont, const key_compare& __comp = key_compare())
+ : __containers_{.keys = std::move(__key_cont), .values = std::move(__mapped_cont)}, __compare_(__comp) {
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
+ "flat_multimap keys and mapped containers have different size");
+ __sort();
+ }
+
+ template <class _Allocator>
+ requires __allocator_ctor_constraint<_Allocator>
+ _LIBCPP_HIDE_FROM_ABI flat_multimap(
+ const key_container_type& __key_cont, const mapped_container_type& __mapped_cont, const _Allocator& __alloc)
+ : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont) {
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
+ "flat_multimap keys and mapped containers have different size");
+ __sort();
+ }
+
+ template <class _Allocator>
+ requires __allocator_ctor_constraint<_Allocator>
+ _LIBCPP_HIDE_FROM_ABI
+ flat_multimap(const key_container_type& __key_cont,
+ const mapped_container_type& __mapped_cont,
+ const key_compare& __comp,
+ const _Allocator& __alloc)
+ : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont, __comp) {
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
+ "flat_multimap keys and mapped containers have different size");
+ __sort();
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ flat_multimap(sorted_equivalent_t,
+ key_container_type __key_cont,
+ mapped_container_type __mapped_cont,
+ const key_compare& __comp = key_compare())
+ : __containers_{.keys = std::move(__key_cont), .values = std::move(__mapped_cont)}, __compare_(__comp) {
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
+ "flat_multimap keys and mapped containers have different size");
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__is_sorted(__containers_.keys), "Key container is not sorted");
+ }
+
+ template <class _Allocator>
+ requires __allocator_ctor_constraint<_Allocator>
+ _LIBCPP_HIDE_FROM_ABI
+ flat_multimap(sorted_equivalent_t,
+ const key_container_type& __key_cont,
+ const mapped_container_type& __mapped_cont,
+ const _Allocator& __alloc)
+ : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont) {
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
+ "flat_multimap keys and mapped containers have different size");
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__is_sorted(__containers_.keys), "Key container is not sorted");
+ }
+
+ template <class _Allocator>
+ requires __allocator_ctor_constraint<_Allocator>
+ _LIBCPP_HIDE_FROM_ABI
+ flat_multimap(sorted_equivalent_t,
+ const key_container_type& __key_cont,
+ const mapped_container_type& __mapped_cont,
+ const key_compare& __comp,
+ const _Allocator& __alloc)
+ : flat_multimap(__ctor_uses_allocator_tag{}, __alloc, __key_cont, __mapped_cont, __comp) {
+ _LIBCPP_ASSERT_VALID_INPUT_RANGE(__containers_.keys.size() == __containers_.values.size(),
+ "flat_multimap keys and mapped containers have different size");
+ _LIBCPP_ASSERT_SEMANTIC_REQUIREMENT(__is_sorted(__containers_.keys), "Key container is not sorted");
+ }
+
+ _LIBCPP_HIDE_FROM_ABI explicit flat_multimap(const key_compare& __comp) : __containers_(), __compare_(__comp) {}
+
+ template <class _Allocator>
+ requires __allocator_ctor_constraint<_Allocator>
+ _LIBCPP_HIDE_FROM_ABI flat_multimap(const key_compare& __comp, const _Allocator& __alloc)
+ : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {}
+
+ template <class _Allocator>
+ requires __allocator_ctor_constraint<_Allocator>
+ _LIBCPP_HIDE_FROM_ABI explicit flat_multimap(const _Allocator& __alloc)
+ : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) {}
+
+ template <class _InputIterator>
+ requires __has_input_iterator_category<_InputIterator>::value
+ _LIBCPP_HIDE_FROM_ABI
+ flat_multimap(_InputIterator __first, _InputIterator __last, const key_compare& __comp = key_compare())
+ : __containers_(), __compare_(__comp) {
+ insert(__first, __last);
+ }
+
+ template <class _InputIterator, class _Allocator>
+ requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)
+ _LIBCPP_HIDE_FROM_ABI
+ flat_multimap(_InputIterator __first, _InputIterator __last, const key_compare& __comp, const _Allocator& __alloc)
+ : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {
+ insert(__first, __last);
+ }
+
+ template <class _InputIterator, class _Allocator>
+ requires(__has_input_iterator_category<_InputIterator>::value && __allocator_ctor_constraint<_Allocator>)
+ _LIBCPP_HIDE_FROM_ABI flat_multimap(_InputIterator __first, _InputIterator __last, const _Allocator& __alloc)
+ : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) {
+ insert(__first, __last);
+ }
+
+ template <_ContainerCompatibleRange<value_type> _Range>
+ _LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t __fr, _Range&& __rg)
+ : flat_multimap(__fr, std::forward<_Range>(__rg), key_compare()) {}
+
+ template <_ContainerCompatibleRange<value_type> _Range, class _Allocator>
+ requires __allocator_ctor_constraint<_Allocator>
+ _LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t, _Range&& __rg, const _Allocator& __alloc)
+ : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc) {
+ insert_range(std::forward<_Range>(__rg));
+ }
+
+ template <_ContainerCompatibleRange<value_type> _Range>
+ _LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t, _Range&& __rg, const key_compare& __comp) : flat_multimap(__comp) {
+ insert_range(std::forward<_Range>(__rg));
+ }
+
+ template <_ContainerCompatibleRange<value_type> _Range, class _Allocator>
+ requires __allocator_ctor_constraint<_Allocator>
+ _LIBCPP_HIDE_FROM_ABI flat_multimap(from_range_t, _Range&& __rg, const key_compare& __comp, const _Allocator& __alloc)
+ : flat_multimap(__ctor_uses_allocator_empty_tag{}, __alloc, __comp) {
+ insert_range(std::forward<_Range>(__rg));
+ }
+
+ template <class _InputIterator>
+ requires __has_input_iterator_category<_InputIterator>::value
+ _LIBCPP_HIDE_F...
[truncated]
|
_LIBCPP_HIDE_FROM_ABI typename flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>::size_type | ||
erase_if(flat_multimap<_Key, _Tp, _Compare, _KeyContainer, _MappedContainer>& __flat_multimap, _Predicate __pred) { | ||
// todo | ||
auto __zv = ranges::views::zip(__flat_multimap.__containers_.keys, __flat_multimap.__containers_.values); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No change requested - I failed to find a way to implementing erase_if
for flat_meow
without touching implementation-specific internal names, which means that erase_if
is unlikely or even impossible to work with user-defined specializations of flat_meow
.
Do you think there should be an LWG issue for this, possibly forbidding program-defined specializations?
|
||
public: | ||
// [flat.map.cons], construct/copy/destroy | ||
_LIBCPP_HIDE_FROM_ABI flat_multimap() noexcept( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per live review: I am not annoyed by some amount of duplication between flat_map
and flat_multimap
for the constructor definitions. IMO this is probably close to the best we can achieve. But if you have a solution in mind to share more between the two classes, feel free to propose it.
template <class _Res, class _Self, class _Kp> | ||
_LIBCPP_HIDE_FROM_ABI static _Res __lower_bound(_Self&& __self, _Kp& __x) { | ||
return __binary_search<_Res>(__self, ranges::lower_bound, __x); | ||
} | ||
|
||
template <class _Res, class _Self, class _Kp> | ||
_LIBCPP_HIDE_FROM_ABI static _Res __upper_bound(_Self&& __self, _Kp& __x) { | ||
return __binary_search<_Res>(__self, ranges::upper_bound, __x); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO if you introduce a helper to compute the corresponding mapped_iter from a key_iter, the __binary_search
function below basically disappears.
|
||
template <class _IterK, class _IterM, class _KeyArg, class... _MArgs> | ||
_LIBCPP_HIDE_FROM_ABI iterator | ||
__emplace_exact_pos(_IterK&& __it_key, _IterM&& __it_mapped, _KeyArg&& __key, _MArgs&&... __mapped_args) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is an exact copy-paste from flat_map
, it's probably a good idea to extract this one into a free function and share it between the two implementations. Especially since this code is pretty tricky.
9066da5
to
5dfffc2
Compare
5dfffc2
to
ab78162
Compare
7e3ce58
to
481bee9
Compare
fix byte include
481bee9
to
373b39c
Compare
fixes #105190