Skip to content

Commit 9066da5

Browse files
committed
[libc++] implement std::flat_multimap
1 parent f467af6 commit 9066da5

File tree

90 files changed

+10055
-4
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+10055
-4
lines changed

libcxx/docs/Status/Cxx23Papers.csv

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
"`P2443R1 <https://wg21.link/P2443R1>`__","``views::chunk_by``","2022-02 (Virtual)","|Complete|","18.0",""
5353
"","","","","",""
5454
"`P0009R18 <https://wg21.link/P0009R18>`__","mdspan: A Non-Owning Multidimensional Array Reference","2022-07 (Virtual)","|Complete|","18.0",""
55-
"`P0429R9 <https://wg21.link/P0429R9>`__","A Standard ``flat_map``","2022-07 (Virtual)","|In progress|","",""
55+
"`P0429R9 <https://wg21.link/P0429R9>`__","A Standard ``flat_map``","2022-07 (Virtual)","|Complete|","20.0",""
5656
"`P1169R4 <https://wg21.link/P1169R4>`__","``static operator()``","2022-07 (Virtual)","|Complete|","16.0",""
5757
"`P1222R4 <https://wg21.link/P1222R4>`__","A Standard ``flat_set``","2022-07 (Virtual)","","",""
5858
"`P1223R5 <https://wg21.link/P1223R5>`__","``ranges::find_last()``, ``ranges::find_last_if()``, and ``ranges::find_last_if_not()``","2022-07 (Virtual)","|Complete|","19.0",""

libcxx/include/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,9 @@ set(files
359359
__filesystem/space_info.h
360360
__filesystem/u8path.h
361361
__flat_map/flat_map.h
362+
__flat_map/flat_multimap.h
362363
__flat_map/sorted_unique.h
364+
__flat_map/sorted_equivalent.h
363365
__format/buffer.h
364366
__format/concepts.h
365367
__format/container_adaptor.h

libcxx/include/__flat_map/flat_multimap.h

+1,182
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
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+
#ifndef _LIBCPP___FLAT_MAP_SORTED_EQUIVALENT_H
10+
#define _LIBCPP___FLAT_MAP_SORTED_EQUIVALENT_H
11+
12+
#include <__config>
13+
14+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
15+
# pragma GCC system_header
16+
#endif
17+
18+
#if _LIBCPP_STD_VER >= 23
19+
20+
_LIBCPP_BEGIN_NAMESPACE_STD
21+
22+
struct sorted_equivalent_t {
23+
explicit sorted_equivalent_t() = default;
24+
};
25+
inline constexpr sorted_equivalent_t sorted_equivalent{};
26+
27+
_LIBCPP_END_NAMESPACE_STD
28+
29+
#endif // _LIBCPP_STD_VER >= 23
30+
31+
#endif // _LIBCPP___FLAT_MAP_SORTED_EQUIVALENT_H

libcxx/include/flat_map

+21
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,33 @@ namespace std {
3535
class Predicate>
3636
typename flat_map<Key, T, Compare, KeyContainer, MappedContainer>::size_type
3737
erase_if(flat_map<Key, T, Compare, KeyContainer, MappedContainer>& c, Predicate pred);
38+
39+
// [flat.multimap], class template flat_multimap
40+
template<class Key, class T, class Compare = less<Key>,
41+
class KeyContainer = vector<Key>, class MappedContainer = vector<T>>
42+
class flat_multimap;
43+
44+
struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; };
45+
inline constexpr sorted_equivalent_t sorted_equivalent{};
46+
47+
template<class Key, class T, class Compare, class KeyContainer, class MappedContainer,
48+
class Allocator>
49+
struct uses_allocator<flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>,
50+
Allocator>;
51+
52+
// [flat.multimap.erasure], erasure for flat_multimap
53+
template<class Key, class T, class Compare, class KeyContainer, class MappedContainer,
54+
class Predicate>
55+
typename flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>::size_type
56+
erase_if(flat_multimap<Key, T, Compare, KeyContainer, MappedContainer>& c, Predicate pred);
3857
*/
3958

4059
#include <__assert> // all public C++ headers provide the assertion handler
4160
#include <__config>
4261
#include <__flat_map/flat_map.h>
62+
#include <__flat_map/flat_multimap.h>
4363
#include <__flat_map/sorted_unique.h>
64+
#include <__flat_map/sorted_equivalent.h>
4465
#include <version>
4566

4667
// standard required includes

libcxx/include/module.modulemap

+2
Original file line numberDiff line numberDiff line change
@@ -1232,7 +1232,9 @@ module std [system] {
12321232

12331233
module flat_map {
12341234
module flat_map { header "__flat_map/flat_map.h" }
1235+
module flat_multimap { header "__flat_map/flat_multimap.h" }
12351236
module sorted_unique { header "__flat_map/sorted_unique.h" }
1237+
module sorted_equivalent { header "__flat_map/sorted_equivalent.h" }
12361238

12371239
header "flat_map"
12381240
export *

libcxx/include/version

+1
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ __cpp_lib_void_t 201411L <type_traits>
479479
# define __cpp_lib_format_ranges 202207L
480480
// # define __cpp_lib_formatters 202302L
481481
# define __cpp_lib_forward_like 202207L
482+
# define __cpp_lib_flat_map 202207L
482483
# define __cpp_lib_invoke_r 202106L
483484
# define __cpp_lib_ios_noreplace 202207L
484485
# if __has_builtin(__builtin_is_implicit_lifetime)

libcxx/modules/std/flat_map.inc

+1-3
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,12 @@ export namespace std {
2020
// [flat.map.erasure], erasure for flat_map
2121
using std::erase_if;
2222

23-
#endif // _LIBCPP_STD_VER >= 23
24-
#if 0
2523
// [flat.multimap], class template flat_multimap
2624
using std::flat_multimap;
2725

2826
using std::sorted_equivalent;
2927
using std::sorted_equivalent_t;
3028

3129
// [flat.multimap.erasure], erasure for flat_multimap
32-
#endif
30+
#endif // _LIBCPP_STD_VER >= 23
3331
} // namespace std
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10+
11+
// <flat_map>
12+
13+
// struct sorted_equivalent_t { explicit sorted_equivalent_t() = default; };
14+
// inline constexpr sorted_equivalent_t sorted_equivalent{};
15+
16+
#include <cassert>
17+
#include <concepts>
18+
#include <flat_map>
19+
#include <type_traits>
20+
21+
template <class T>
22+
void implicit_test(T) {}
23+
24+
template <class T>
25+
concept HasImplicitDefaultCtor = requires { implicit_test<T>({}); };
26+
27+
static_assert(std::is_default_constructible_v<std::sorted_equivalent_t>);
28+
static_assert(std::is_trivially_default_constructible_v<std::sorted_equivalent_t>);
29+
static_assert(!HasImplicitDefaultCtor<std::sorted_equivalent_t>);
30+
31+
constexpr bool test() {
32+
{
33+
[[maybe_unused]] std::sorted_equivalent_t s;
34+
}
35+
{
36+
[[maybe_unused]] std::same_as<const std::sorted_equivalent_t&> decltype(auto) s = (std::sorted_equivalent);
37+
}
38+
{
39+
[[maybe_unused]] std::same_as<const std::sorted_equivalent_t> decltype(auto) copy = std::sorted_equivalent;
40+
}
41+
42+
return true;
43+
}
44+
45+
int main(int, char**) {
46+
test();
47+
static_assert(test());
48+
49+
return 0;
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10+
11+
// <flat_map>
12+
13+
// class flat_multimap
14+
15+
// [[nodiscard]] bool empty() const noexcept;
16+
17+
#include <flat_map>
18+
#include <cassert>
19+
#include <deque>
20+
#include <functional>
21+
#include <utility>
22+
#include <vector>
23+
24+
#include "MinSequenceContainer.h"
25+
#include "test_macros.h"
26+
#include "min_allocator.h"
27+
28+
template <class KeyContainer, class ValueContainer>
29+
void test() {
30+
using M = std::flat_multimap<int, double, std::less<int>, KeyContainer, ValueContainer>;
31+
M m;
32+
ASSERT_SAME_TYPE(decltype(m.empty()), bool);
33+
ASSERT_NOEXCEPT(m.empty());
34+
assert(m.empty());
35+
assert(std::as_const(m).empty());
36+
m = {{1, 1.0}, {1, 2.0}};
37+
assert(!m.empty());
38+
m.clear();
39+
assert(m.empty());
40+
}
41+
42+
int main(int, char**) {
43+
test<std::vector<int>, std::vector<double>>();
44+
test<std::deque<int>, std::vector<double>>();
45+
test<MinSequenceContainer<int>, MinSequenceContainer<double>>();
46+
test<std::vector<int, min_allocator<int>>, std::vector<double, min_allocator<double>>>();
47+
48+
return 0;
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10+
11+
// <flat_map>
12+
13+
// class flat_multimap
14+
15+
// [[nodiscard]] bool empty() const noexcept;
16+
17+
#include <flat_map>
18+
19+
#include "test_macros.h"
20+
21+
int main(int, char**) {
22+
std::flat_multimap<int, int> c;
23+
c.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
24+
25+
return 0;
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10+
11+
// <flat_map>
12+
13+
// class flat_multimap
14+
15+
// size_type max_size() const noexcept;
16+
17+
#include <cassert>
18+
#include <deque>
19+
#include <flat_map>
20+
#include <functional>
21+
#include <limits>
22+
#include <type_traits>
23+
#include <vector>
24+
25+
#include "MinSequenceContainer.h"
26+
#include "test_allocator.h"
27+
#include "test_macros.h"
28+
29+
int main(int, char**) {
30+
{
31+
using A1 = limited_allocator<int, 10>;
32+
using A2 = limited_allocator<int, 20>;
33+
using C = std::flat_multimap<int, int, std::less<int>, std::vector<int, A1>, std::vector<int, A2>>;
34+
ASSERT_SAME_TYPE(C::difference_type, std::ptrdiff_t);
35+
ASSERT_SAME_TYPE(C::size_type, std::size_t);
36+
const C c;
37+
ASSERT_NOEXCEPT(c.max_size());
38+
ASSERT_SAME_TYPE(decltype(c.max_size()), C::size_type);
39+
assert(c.max_size() <= 10);
40+
LIBCPP_ASSERT(c.max_size() == 10);
41+
}
42+
{
43+
using A1 = limited_allocator<int, 10>;
44+
using A2 = limited_allocator<int, 20>;
45+
using C = std::flat_multimap<int, int, std::less<int>, std::vector<int, A2>, std::vector<int, A1>>;
46+
ASSERT_SAME_TYPE(C::difference_type, std::ptrdiff_t);
47+
ASSERT_SAME_TYPE(C::size_type, std::size_t);
48+
const C c;
49+
ASSERT_NOEXCEPT(c.max_size());
50+
ASSERT_SAME_TYPE(decltype(c.max_size()), C::size_type);
51+
assert(c.max_size() <= 10);
52+
LIBCPP_ASSERT(c.max_size() == 10);
53+
}
54+
{
55+
using A = limited_allocator<int, (size_t)-1>;
56+
using C = std::flat_multimap<int, int, std::less<int>, std::vector<int, A>, std::vector<int, A>>;
57+
ASSERT_SAME_TYPE(C::difference_type, std::ptrdiff_t);
58+
ASSERT_SAME_TYPE(C::size_type, std::size_t);
59+
const C::size_type max_dist = static_cast<C::size_type>(std::numeric_limits<C::difference_type>::max());
60+
const C c;
61+
ASSERT_NOEXCEPT(c.max_size());
62+
ASSERT_SAME_TYPE(decltype(c.max_size()), C::size_type);
63+
assert(c.max_size() <= max_dist);
64+
LIBCPP_ASSERT(c.max_size() == max_dist);
65+
}
66+
{
67+
typedef std::flat_multimap<char, char> C;
68+
ASSERT_SAME_TYPE(C::difference_type, std::ptrdiff_t);
69+
ASSERT_SAME_TYPE(C::size_type, std::size_t);
70+
const C::size_type max_dist = static_cast<C::size_type>(std::numeric_limits<C::difference_type>::max());
71+
const C c;
72+
ASSERT_NOEXCEPT(c.max_size());
73+
ASSERT_SAME_TYPE(decltype(c.max_size()), C::size_type);
74+
assert(c.max_size() <= max_dist);
75+
assert(c.max_size() <= alloc_max_size(std::allocator<char>()));
76+
}
77+
return 0;
78+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10+
11+
// <flat_map>
12+
13+
// class flat_multimap
14+
15+
// size_type size() const noexcept;
16+
17+
#include <cassert>
18+
#include <deque>
19+
#include <flat_map>
20+
#include <functional>
21+
#include <vector>
22+
23+
#include "MinSequenceContainer.h"
24+
#include "test_macros.h"
25+
#include "min_allocator.h"
26+
27+
template <class KeyContainer, class ValueContainer>
28+
void test() {
29+
using M = std::flat_multimap<int, char, std::less<int>, KeyContainer, ValueContainer>;
30+
{
31+
const M m = {{1, 'a'}, {1, 'b'}, {4, 'd'}, {5, 'e'}, {5, 'h'}};
32+
ASSERT_SAME_TYPE(decltype(m.size()), std::size_t);
33+
ASSERT_NOEXCEPT(m.size());
34+
assert(m.size() == 5);
35+
}
36+
{
37+
const M m = {{1, 'a'}};
38+
ASSERT_SAME_TYPE(decltype(m.size()), std::size_t);
39+
ASSERT_NOEXCEPT(m.size());
40+
assert(m.size() == 1);
41+
}
42+
{
43+
const M m;
44+
ASSERT_SAME_TYPE(decltype(m.size()), std::size_t);
45+
ASSERT_NOEXCEPT(m.size());
46+
assert(m.size() == 0);
47+
}
48+
{
49+
M m;
50+
std::size_t s = 1000;
51+
for (auto i = 0u; i < s; ++i) {
52+
m.emplace(i, 'a');
53+
}
54+
for (auto i = 0u; i < s; ++i) {
55+
m.emplace(i, 'b');
56+
}
57+
ASSERT_SAME_TYPE(decltype(m.size()), std::size_t);
58+
ASSERT_NOEXCEPT(m.size());
59+
assert(m.size() == 2 * s);
60+
}
61+
}
62+
63+
int main(int, char**) {
64+
test<std::vector<int>, std::vector<char>>();
65+
test<std::deque<int>, std::vector<char>>();
66+
test<MinSequenceContainer<int>, MinSequenceContainer<char>>();
67+
test<std::vector<int, min_allocator<int>>, std::vector<char, min_allocator<char>>>();
68+
69+
return 0;
70+
}

0 commit comments

Comments
 (0)