Skip to content

Commit 831fcb5

Browse files
authored
[libc++] constexpr flat_map (#137453)
Fixes #128673
1 parent 77941eb commit 831fcb5

File tree

85 files changed

+2703
-1231
lines changed

Some content is hidden

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

85 files changed

+2703
-1231
lines changed

libcxx/docs/ReleaseNotes/21.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ Implemented Papers
4747
- P1222R4: A Standard ``flat_set`` (`Github <https://github.com/llvm/llvm-project/issues/105193>`__)
4848
- P2897R7: ``aligned_accessor``: An mdspan accessor expressing pointer over-alignment (`Github <https://github.com/llvm/llvm-project/issues/118372>`__)
4949
- P3247R2: Deprecate the notion of trivial types (`Github <https://github.com/llvm/llvm-project/issues/118387>`__)
50+
- P3372R3: ``constexpr`` containers and adaptors (`Github <https://github.com/llvm/llvm-project/issues/128673>`__) (Only ``constexpr flat_map`` is implemented)
5051
- P2441R2: ``views::join_with`` (`Github <https://github.com/llvm/llvm-project/issues/105185>`__)
5152
- P2711R1: Making multi-param constructors of ``views`` ``explicit`` (`Github <https://github.com/llvm/llvm-project/issues/105252>`__)
5253
- P2770R0: Stashing stashing ``iterators`` for proper flattening (`Github <https://github.com/llvm/llvm-project/issues/105250>`__)

libcxx/docs/Status/Cxx2cPapers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@
104104
"`P3137R3 <https://wg21.link/P3137R3>`__","``views::to_input``","2025-02 (Hagenberg)","","",""
105105
"`P0472R3 <https://wg21.link/P0472R3>`__","Put ``std::monostate`` in ``<utility>``","2025-02 (Hagenberg)","|Complete|","21",""
106106
"`P3349R1 <https://wg21.link/P3349R1>`__","Converting contiguous iterators to pointers","2025-02 (Hagenberg)","","",""
107-
"`P3372R3 <https://wg21.link/P3372R3>`__","constexpr containers and adaptors","2025-02 (Hagenberg)","","",""
107+
"`P3372R3 <https://wg21.link/P3372R3>`__","constexpr containers and adaptors","2025-02 (Hagenberg)","|In Progress|","",""
108108
"`P3378R2 <https://wg21.link/P3378R2>`__","constexpr exception types","2025-02 (Hagenberg)","","",""
109109
"`P3441R2 <https://wg21.link/P3441R2>`__","Rename ``simd_split`` to ``simd_chunk``","2025-02 (Hagenberg)","","",""
110110
"`P3287R3 <https://wg21.link/P3287R3>`__","Exploration of namespaces for ``std::simd``","2025-02 (Hagenberg)","","",""

libcxx/include/__flat_map/flat_map.h

Lines changed: 234 additions & 157 deletions
Large diffs are not rendered by default.

libcxx/include/__flat_map/key_value_iterator.h

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ struct __key_value_iterator {
4646

4747
struct __arrow_proxy {
4848
__reference __ref_;
49-
_LIBCPP_HIDE_FROM_ABI __reference* operator->() { return std::addressof(__ref_); }
49+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __reference* operator->() { return std::addressof(__ref_); }
5050
};
5151

5252
__key_iterator __key_iter_;
@@ -69,99 +69,113 @@ struct __key_value_iterator {
6969

7070
_LIBCPP_HIDE_FROM_ABI __key_value_iterator() = default;
7171

72-
_LIBCPP_HIDE_FROM_ABI __key_value_iterator(__key_value_iterator<_Owner, _KeyContainer, _MappedContainer, !_Const> __i)
72+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
73+
__key_value_iterator(__key_value_iterator<_Owner, _KeyContainer, _MappedContainer, !_Const> __i)
7374
requires _Const && convertible_to<typename _KeyContainer::iterator, __key_iterator> &&
7475
convertible_to<typename _MappedContainer::iterator, __mapped_iterator>
7576
: __key_iter_(std::move(__i.__key_iter_)), __mapped_iter_(std::move(__i.__mapped_iter_)) {}
7677

77-
_LIBCPP_HIDE_FROM_ABI __key_value_iterator(__key_iterator __key_iter, __mapped_iterator __mapped_iter)
78+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26
79+
__key_value_iterator(__key_iterator __key_iter, __mapped_iterator __mapped_iter)
7880
: __key_iter_(std::move(__key_iter)), __mapped_iter_(std::move(__mapped_iter)) {}
7981

80-
_LIBCPP_HIDE_FROM_ABI __reference operator*() const { return __reference(*__key_iter_, *__mapped_iter_); }
81-
_LIBCPP_HIDE_FROM_ABI __arrow_proxy operator->() const { return __arrow_proxy{**this}; }
82+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __reference operator*() const {
83+
return __reference(*__key_iter_, *__mapped_iter_);
84+
}
85+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __arrow_proxy operator->() const { return __arrow_proxy{**this}; }
8286

83-
_LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator++() {
87+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator& operator++() {
8488
++__key_iter_;
8589
++__mapped_iter_;
8690
return *this;
8791
}
8892

89-
_LIBCPP_HIDE_FROM_ABI __key_value_iterator operator++(int) {
93+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator operator++(int) {
9094
__key_value_iterator __tmp(*this);
9195
++*this;
9296
return __tmp;
9397
}
9498

95-
_LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator--() {
99+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator& operator--() {
96100
--__key_iter_;
97101
--__mapped_iter_;
98102
return *this;
99103
}
100104

101-
_LIBCPP_HIDE_FROM_ABI __key_value_iterator operator--(int) {
105+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator operator--(int) {
102106
__key_value_iterator __tmp(*this);
103107
--*this;
104108
return __tmp;
105109
}
106110

107-
_LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator+=(difference_type __x) {
111+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator& operator+=(difference_type __x) {
108112
__key_iter_ += __x;
109113
__mapped_iter_ += __x;
110114
return *this;
111115
}
112116

113-
_LIBCPP_HIDE_FROM_ABI __key_value_iterator& operator-=(difference_type __x) {
117+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __key_value_iterator& operator-=(difference_type __x) {
114118
__key_iter_ -= __x;
115119
__mapped_iter_ -= __x;
116120
return *this;
117121
}
118122

119-
_LIBCPP_HIDE_FROM_ABI __reference operator[](difference_type __n) const { return *(*this + __n); }
123+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 __reference operator[](difference_type __n) const {
124+
return *(*this + __n);
125+
}
120126

121-
_LIBCPP_HIDE_FROM_ABI friend constexpr bool
127+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool
122128
operator==(const __key_value_iterator& __x, const __key_value_iterator& __y) {
123129
return __x.__key_iter_ == __y.__key_iter_;
124130
}
125131

126-
_LIBCPP_HIDE_FROM_ABI friend bool operator<(const __key_value_iterator& __x, const __key_value_iterator& __y) {
132+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool
133+
operator<(const __key_value_iterator& __x, const __key_value_iterator& __y) {
127134
return __x.__key_iter_ < __y.__key_iter_;
128135
}
129136

130-
_LIBCPP_HIDE_FROM_ABI friend bool operator>(const __key_value_iterator& __x, const __key_value_iterator& __y) {
137+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool
138+
operator>(const __key_value_iterator& __x, const __key_value_iterator& __y) {
131139
return __y < __x;
132140
}
133141

134-
_LIBCPP_HIDE_FROM_ABI friend bool operator<=(const __key_value_iterator& __x, const __key_value_iterator& __y) {
142+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool
143+
operator<=(const __key_value_iterator& __x, const __key_value_iterator& __y) {
135144
return !(__y < __x);
136145
}
137146

138-
_LIBCPP_HIDE_FROM_ABI friend bool operator>=(const __key_value_iterator& __x, const __key_value_iterator& __y) {
147+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend bool
148+
operator>=(const __key_value_iterator& __x, const __key_value_iterator& __y) {
139149
return !(__x < __y);
140150
}
141151

142-
_LIBCPP_HIDE_FROM_ABI friend auto operator<=>(const __key_value_iterator& __x, const __key_value_iterator& __y)
152+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend auto
153+
operator<=>(const __key_value_iterator& __x, const __key_value_iterator& __y)
143154
requires three_way_comparable<__key_iterator>
144155
{
145156
return __x.__key_iter_ <=> __y.__key_iter_;
146157
}
147158

148-
_LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator+(const __key_value_iterator& __i, difference_type __n) {
159+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend __key_value_iterator
160+
operator+(const __key_value_iterator& __i, difference_type __n) {
149161
auto __tmp = __i;
150162
__tmp += __n;
151163
return __tmp;
152164
}
153165

154-
_LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator+(difference_type __n, const __key_value_iterator& __i) {
166+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend __key_value_iterator
167+
operator+(difference_type __n, const __key_value_iterator& __i) {
155168
return __i + __n;
156169
}
157170

158-
_LIBCPP_HIDE_FROM_ABI friend __key_value_iterator operator-(const __key_value_iterator& __i, difference_type __n) {
171+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend __key_value_iterator
172+
operator-(const __key_value_iterator& __i, difference_type __n) {
159173
auto __tmp = __i;
160174
__tmp -= __n;
161175
return __tmp;
162176
}
163177

164-
_LIBCPP_HIDE_FROM_ABI friend difference_type
178+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 friend difference_type
165179
operator-(const __key_value_iterator& __x, const __key_value_iterator& __y) {
166180
return difference_type(__x.__key_iter_ - __y.__key_iter_);
167181
}

libcxx/include/__flat_map/utils.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ struct __flat_map_utils {
3535
// roll back the changes it made to the map. If it cannot roll back the changes, it will
3636
// clear the map.
3737
template <class _Map, class _IterK, class _IterM, class _KeyArg, class... _MArgs>
38-
_LIBCPP_HIDE_FROM_ABI static typename _Map::iterator __emplace_exact_pos(
38+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static typename _Map::iterator __emplace_exact_pos(
3939
_Map& __map, _IterK&& __it_key, _IterM&& __it_mapped, _KeyArg&& __key, _MArgs&&... __mapped_args) {
4040
auto __on_key_failed = std::__make_exception_guard([&]() noexcept {
4141
using _KeyContainer = typename _Map::key_container_type;
@@ -82,7 +82,7 @@ struct __flat_map_utils {
8282
// TODO: We could optimize this, see
8383
// https://github.com/llvm/llvm-project/issues/108624
8484
template <class _Map, class _InputIterator, class _Sentinel>
85-
_LIBCPP_HIDE_FROM_ABI static typename _Map::size_type
85+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static typename _Map::size_type
8686
__append(_Map& __map, _InputIterator __first, _Sentinel __last) {
8787
typename _Map::size_type __num_appended = 0;
8888
for (; __first != __last; ++__first) {

libcxx/include/module.modulemap.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,6 +1298,9 @@ module std [system] {
12981298

12991299
header "flat_map"
13001300
export *
1301+
export std.algorithm.ranges_sort
1302+
export std.ranges.zip_view
1303+
export std.tuple
13011304
}
13021305

13031306
module flat_set {

libcxx/test/std/containers/Emplaceable.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,34 +22,34 @@ class Emplaceable {
2222
double double_;
2323

2424
public:
25-
TEST_CONSTEXPR Emplaceable() : int_(0), double_(0) {}
26-
TEST_CONSTEXPR Emplaceable(int i, double d) : int_(i), double_(d) {}
27-
TEST_CONSTEXPR_CXX14 Emplaceable(Emplaceable&& x) : int_(x.int_), double_(x.double_) {
25+
TEST_CONSTEXPR_CXX20 Emplaceable() : int_(0), double_(0) {}
26+
TEST_CONSTEXPR_CXX20 Emplaceable(int i, double d) : int_(i), double_(d) {}
27+
TEST_CONSTEXPR_CXX20 Emplaceable(Emplaceable&& x) : int_(x.int_), double_(x.double_) {
2828
x.int_ = 0;
2929
x.double_ = 0;
3030
}
31-
TEST_CONSTEXPR_CXX14 Emplaceable& operator=(Emplaceable&& x) {
31+
TEST_CONSTEXPR_CXX20 Emplaceable& operator=(Emplaceable&& x) {
3232
int_ = x.int_;
3333
x.int_ = 0;
3434
double_ = x.double_;
3535
x.double_ = 0;
3636
return *this;
3737
}
3838

39-
TEST_CONSTEXPR bool operator==(const Emplaceable& x) const { return int_ == x.int_ && double_ == x.double_; }
40-
TEST_CONSTEXPR bool operator<(const Emplaceable& x) const {
39+
TEST_CONSTEXPR_CXX20 bool operator==(const Emplaceable& x) const { return int_ == x.int_ && double_ == x.double_; }
40+
TEST_CONSTEXPR_CXX20 bool operator<(const Emplaceable& x) const {
4141
return int_ < x.int_ || (int_ == x.int_ && double_ < x.double_);
4242
}
4343

44-
TEST_CONSTEXPR int get() const { return int_; }
44+
TEST_CONSTEXPR_CXX20 int get() const { return int_; }
4545
};
4646

4747
template <>
4848
struct std::hash<Emplaceable> {
4949
typedef Emplaceable argument_type;
5050
typedef std::size_t result_type;
5151

52-
TEST_CONSTEXPR std::size_t operator()(const Emplaceable& x) const { return static_cast<std::size_t>(x.get()); }
52+
TEST_CONSTEXPR_CXX20 std::size_t operator()(const Emplaceable& x) const { return static_cast<std::size_t>(x.get()); }
5353
};
5454

5555
#endif // TEST_STD_VER >= 11

libcxx/test/std/containers/container.adaptors/flat.map/flat.map.access/at.pass.cpp

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818
#include <flat_map>
1919
#include <functional>
2020
#include <stdexcept>
21+
#include <type_traits>
2122
#include <vector>
2223

2324
#include "MinSequenceContainer.h"
2425
#include "min_allocator.h"
2526
#include "test_macros.h"
2627

2728
template <class KeyContainer, class ValueContainer>
28-
void test() {
29+
constexpr void test() {
2930
using P = std::pair<int, double>;
3031
P ar[] = {
3132
P(1, 1.5),
@@ -49,10 +50,12 @@ void test() {
4950
assert(m.at(4) == 4.5);
5051
assert(m.at(5) == 5.5);
5152
#ifndef TEST_HAS_NO_EXCEPTIONS
52-
try {
53-
TEST_IGNORE_NODISCARD m.at(6);
54-
assert(false);
55-
} catch (std::out_of_range&) {
53+
if (!TEST_IS_CONSTANT_EVALUATED) {
54+
try {
55+
TEST_IGNORE_NODISCARD m.at(6);
56+
assert(false);
57+
} catch (std::out_of_range&) {
58+
}
5659
}
5760
#endif
5861
assert(m.at(7) == 7.5);
@@ -70,10 +73,12 @@ void test() {
7073
assert(m.at(4) == 4.5);
7174
assert(m.at(5) == 5.5);
7275
#ifndef TEST_HAS_NO_EXCEPTIONS
73-
try {
74-
TEST_IGNORE_NODISCARD m.at(6);
75-
assert(false);
76-
} catch (std::out_of_range&) {
76+
if (!TEST_IS_CONSTANT_EVALUATED) {
77+
try {
78+
TEST_IGNORE_NODISCARD m.at(6);
79+
assert(false);
80+
} catch (std::out_of_range&) {
81+
}
7782
}
7883
#endif
7984
assert(m.at(7) == 7.5);
@@ -82,11 +87,25 @@ void test() {
8287
}
8388
}
8489

85-
int main(int, char**) {
90+
constexpr bool test() {
8691
test<std::vector<int>, std::vector<double>>();
87-
test<std::deque<int>, std::vector<double>>();
92+
#ifndef __cpp_lib_constexpr_deque
93+
if (!TEST_IS_CONSTANT_EVALUATED)
94+
#endif
95+
{
96+
test<std::deque<int>, std::vector<double>>();
97+
}
8898
test<MinSequenceContainer<int>, MinSequenceContainer<double>>();
8999
test<std::vector<int, min_allocator<int>>, std::vector<double, min_allocator<double>>>();
90100

101+
return true;
102+
}
103+
104+
int main(int, char**) {
105+
test();
106+
#if TEST_STD_VER >= 26
107+
static_assert(test());
108+
#endif
109+
91110
return 0;
92111
}

libcxx/test/std/containers/container.adaptors/flat.map/flat.map.access/at_transparent.pass.cpp

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ static_assert(!CanAt<NonTransparentMap>);
3535
static_assert(!CanAt<const NonTransparentMap>);
3636

3737
template <class KeyContainer, class ValueContainer>
38-
void test() {
38+
constexpr void test() {
3939
using P = std::pair<int, double>;
4040
P ar[] = {
4141
P(1, 1.5),
@@ -60,10 +60,12 @@ void test() {
6060
assert(m.at(Transparent<int>{4}) == 4.5);
6161
assert(m.at(Transparent<int>{5}) == 5.5);
6262
#ifndef TEST_HAS_NO_EXCEPTIONS
63-
try {
64-
TEST_IGNORE_NODISCARD m.at(Transparent<int>{6});
65-
assert(false);
66-
} catch (std::out_of_range&) {
63+
if (!TEST_IS_CONSTANT_EVALUATED) {
64+
try {
65+
TEST_IGNORE_NODISCARD m.at(Transparent<int>{6});
66+
assert(false);
67+
} catch (std::out_of_range&) {
68+
}
6769
}
6870
#endif
6971
assert(m.at(Transparent<int>{7}) == 7.5);
@@ -81,10 +83,12 @@ void test() {
8183
assert(m.at(Transparent<int>{4}) == 4.5);
8284
assert(m.at(Transparent<int>{5}) == 5.5);
8385
#ifndef TEST_HAS_NO_EXCEPTIONS
84-
try {
85-
TEST_IGNORE_NODISCARD m.at(Transparent<int>{6});
86-
assert(false);
87-
} catch (std::out_of_range&) {
86+
if (!TEST_IS_CONSTANT_EVALUATED) {
87+
try {
88+
TEST_IGNORE_NODISCARD m.at(Transparent<int>{6});
89+
assert(false);
90+
} catch (std::out_of_range&) {
91+
}
8892
}
8993
#endif
9094
assert(m.at(Transparent<int>{7}) == 7.5);
@@ -93,9 +97,14 @@ void test() {
9397
}
9498
}
9599

96-
int main(int, char**) {
100+
constexpr bool test() {
97101
test<std::vector<int>, std::vector<double>>();
98-
test<std::deque<int>, std::vector<double>>();
102+
#ifndef __cpp_lib_constexpr_deque
103+
if (!TEST_IS_CONSTANT_EVALUATED)
104+
#endif
105+
{
106+
test<std::deque<int>, std::vector<double>>();
107+
}
99108
test<MinSequenceContainer<int>, MinSequenceContainer<double>>();
100109
test<std::vector<int, min_allocator<int>>, std::vector<double, min_allocator<double>>>();
101110
{
@@ -114,5 +123,14 @@ int main(int, char**) {
114123
assert(x == 1);
115124
}
116125

126+
return true;
127+
}
128+
129+
int main(int, char**) {
130+
test();
131+
#if TEST_STD_VER >= 26
132+
static_assert(test());
133+
#endif
134+
117135
return 0;
118136
}

0 commit comments

Comments
 (0)