Skip to content

Commit 9eb4fc7

Browse files
authored
[libc++] constexpr flat_set (llvm#140360)
Fixes llvm#128675
1 parent 113ea3d commit 9eb4fc7

File tree

68 files changed

+1464
-724
lines changed

Some content is hidden

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

68 files changed

+1464
-724
lines changed

libcxx/include/__flat_set/flat_set.h

Lines changed: 166 additions & 112 deletions
Large diffs are not rendered by default.

libcxx/include/__flat_set/utils.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ struct __flat_set_utils {
3838
// When an exception is thrown during the emplacement, the function will clear the set if the container does not
3939
// have strong exception safety guarantee on emplacement.
4040
template <class _Set, class _Iter, class _KeyArg>
41-
_LIBCPP_HIDE_FROM_ABI static auto __emplace_exact_pos(_Set& __set, _Iter&& __iter, _KeyArg&& __key) {
41+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static auto
42+
__emplace_exact_pos(_Set& __set, _Iter&& __iter, _KeyArg&& __key) {
4243
using _KeyContainer = typename decay_t<_Set>::container_type;
4344
auto __on_failure = std::__make_exception_guard([&]() noexcept {
4445
if constexpr (!__container_traits<_KeyContainer>::__emplacement_has_strong_exception_safety_guarantee) {
@@ -51,12 +52,13 @@ struct __flat_set_utils {
5152
}
5253

5354
template <class _Set, class _InputIterator>
54-
_LIBCPP_HIDE_FROM_ABI static void __append(_Set& __set, _InputIterator __first, _InputIterator __last) {
55+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static void
56+
__append(_Set& __set, _InputIterator __first, _InputIterator __last) {
5557
__set.__keys_.insert(__set.__keys_.end(), std::move(__first), std::move(__last));
5658
}
5759

5860
template <class _Set, class _Range>
59-
_LIBCPP_HIDE_FROM_ABI static void __append(_Set& __set, _Range&& __rng) {
61+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 static void __append(_Set& __set, _Range&& __rng) {
6062
if constexpr (requires { __set.__keys_.insert_range(__set.__keys_.end(), std::forward<_Range>(__rng)); }) {
6163
// C++23 Sequence Container should have insert_range member function
6264
// Note that not all Sequence Containers provide append_range.

libcxx/include/module.modulemap.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,6 +1319,9 @@ module std [system] {
13191319
export std.flat_map.sorted_unique
13201320
export std.flat_map.sorted_equivalent
13211321
export *
1322+
export std.algorithm.ranges_sort
1323+
export std.ranges.zip_view
1324+
export std.tuple
13221325
}
13231326

13241327
module format {

libcxx/test/libcxx/containers/container.adaptors/flat.set/insert.temporary.pass.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
#include "../flat_helpers.h"
2222
#include "test_macros.h"
2323

24-
bool test() {
24+
constexpr bool test() {
2525
using M = std::flat_set<TrackCopyMove>;
2626
{
2727
M m;
@@ -43,6 +43,9 @@ bool test() {
4343

4444
int main(int, char**) {
4545
test();
46+
#if TEST_STD_VER >= 26
47+
static_assert(test());
48+
#endif
4649

4750
return 0;
4851
}

libcxx/test/libcxx/containers/container.adaptors/flat.set/insert_range.pass.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,33 @@
2424
#include <vector>
2525

2626
#include "../flat_helpers.h"
27+
#include "test_iterators.h"
2728
#include "test_macros.h"
2829

29-
void test() {
30+
constexpr bool test() {
3031
NotQuiteSequenceContainer<int> v;
3132
std::flat_set s(v);
32-
std::istringstream ints("0 1 1 0");
33-
auto r = std::ranges::subrange(std::istream_iterator<int>(ints), std::istream_iterator<int>()) |
34-
std::views::transform([](int i) { return i * i; });
33+
34+
int ar[] = {0, 1, 1, 0};
35+
using Iter = cpp20_input_iterator<const int*>;
36+
using Sent = sentinel_wrapper<Iter>;
37+
using R = std::ranges::subrange<Iter, Sent>;
38+
auto r = R(Iter(ar), Sent(Iter(ar + 4)));
39+
3540
static_assert(
3641
![](auto& t) { return requires { t.insert_range(t.end(), r); }; }(v),
3742
"This test is to test the case where the underlying container does not provide insert_range");
3843
s.insert_range(r);
3944
assert(std::ranges::equal(s, std::vector<int>{0, 1}));
45+
46+
return true;
4047
}
4148

4249
int main(int, char**) {
4350
test();
51+
#if TEST_STD_VER >= 26
52+
static_assert(test());
53+
#endif
4454

4555
return 0;
4656
}

libcxx/test/std/containers/container.adaptors/flat.set/flat.set.capacity/empty.pass.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#include "min_allocator.h"
2525

2626
template <class KeyContainer>
27-
void test_one() {
27+
constexpr void test_one() {
2828
using Key = typename KeyContainer::value_type;
2929
using M = std::flat_set<Key, std::less<int>, KeyContainer>;
3030
M m;
@@ -38,15 +38,23 @@ void test_one() {
3838
assert(m.empty());
3939
}
4040

41-
void test() {
41+
constexpr bool test() {
4242
test_one<std::vector<int>>();
43-
test_one<std::deque<int>>();
43+
#ifndef __cpp_lib_constexpr_deque
44+
if (!TEST_IS_CONSTANT_EVALUATED)
45+
#endif
46+
test_one<std::deque<int>>();
4447
test_one<MinSequenceContainer<int>>();
4548
test_one<std::vector<int, min_allocator<int>>>();
49+
50+
return true;
4651
}
4752

4853
int main(int, char**) {
4954
test();
55+
#if TEST_STD_VER >= 26
56+
static_assert(test());
57+
#endif
5058

5159
return 0;
5260
}

libcxx/test/std/containers/container.adaptors/flat.set/flat.set.capacity/max_size.pass.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#include "test_allocator.h"
2525
#include "test_macros.h"
2626

27-
void test() {
27+
constexpr bool test() {
2828
{
2929
using A1 = limited_allocator<int, 10>;
3030
using C = std::flat_set<int, std::less<int>, std::vector<int, A1>>;
@@ -59,10 +59,15 @@ void test() {
5959
assert(c.max_size() <= max_dist);
6060
assert(c.max_size() <= alloc_max_size(std::allocator<char>()));
6161
}
62+
63+
return true;
6264
}
6365

6466
int main(int, char**) {
6567
test();
68+
#if TEST_STD_VER >= 26
69+
static_assert(test());
70+
#endif
6671

6772
return 0;
6873
}

libcxx/test/std/containers/container.adaptors/flat.set/flat.set.capacity/size.pass.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@
1616
#include <deque>
1717
#include <flat_set>
1818
#include <functional>
19+
#include <type_traits>
1920
#include <vector>
2021

2122
#include "MinSequenceContainer.h"
2223
#include "test_macros.h"
2324
#include "min_allocator.h"
2425

2526
template <class KeyContainer>
26-
void test_one() {
27+
constexpr void test_one() {
2728
using M = std::flat_set<int, std::less<int>, KeyContainer>;
2829
using S = typename M::size_type;
2930
{
@@ -46,7 +47,7 @@ void test_one() {
4647
}
4748
{
4849
M m;
49-
S s = 1000000;
50+
S s = TEST_IS_CONSTANT_EVALUATED ? 100 : 1000000;
5051
for (auto i = 0u; i < s; ++i) {
5152
m.emplace(i);
5253
}
@@ -56,15 +57,23 @@ void test_one() {
5657
}
5758
}
5859

59-
void test() {
60+
constexpr bool test() {
6061
test_one<std::vector<int>>();
61-
test_one<std::deque<int>>();
62+
#ifndef __cpp_lib_constexpr_deque
63+
if (!TEST_IS_CONSTANT_EVALUATED)
64+
#endif
65+
test_one<std::deque<int>>();
6266
test_one<MinSequenceContainer<int>>();
6367
test_one<std::vector<int, min_allocator<int>>>();
68+
69+
return true;
6470
}
6571

6672
int main(int, char**) {
6773
test();
74+
#if TEST_STD_VER >= 26
75+
static_assert(test());
76+
#endif
6877

6978
return 0;
7079
}

libcxx/test/std/containers/container.adaptors/flat.set/flat.set.cons/alloc.pass.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,27 @@
1414
// explicit flat_set(const Allocator& a);
1515

1616
#include <cassert>
17+
#include <deque>
1718
#include <flat_set>
1819
#include <functional>
1920
#include <vector>
2021

22+
#include "MinSequenceContainer.h"
2123
#include "test_macros.h"
2224
#include "test_allocator.h"
2325
#include "../../../test_compare.h"
2426

25-
void test() {
27+
template <template <class...> class KeyContainer>
28+
constexpr void test() {
2629
{
2730
// The constructors in this subclause shall not participate in overload
2831
// resolution unless uses_allocator_v<container_type, Alloc> is true.
2932

3033
using C = test_less<int>;
3134
using A1 = test_allocator<int>;
3235
using A2 = other_allocator<int>;
33-
using V1 = std::vector<int, A1>;
34-
using V2 = std::vector<int, A2>;
36+
using V1 = KeyContainer<int, A1>;
37+
using V2 = KeyContainer<int, A2>;
3538
using M1 = std::flat_set<int, C, V1>;
3639
using M2 = std::flat_set<int, C, V2>;
3740
static_assert(std::is_constructible_v<M1, const A1&>);
@@ -41,14 +44,14 @@ void test() {
4144
}
4245
{
4346
// explicit
44-
using M = std::flat_set<int, std::less<int>, std::vector<int, test_allocator<int>>>;
47+
using M = std::flat_set<int, std::less<int>, KeyContainer<int, test_allocator<int>>>;
4548

4649
static_assert(std::is_constructible_v<M, test_allocator<int>>);
4750
static_assert(!std::is_convertible_v<test_allocator<int>, M>);
4851
}
4952
{
5053
using A = test_allocator<short>;
51-
using M = std::flat_set<int, std::less<int>, std::vector<int, test_allocator<int>>>;
54+
using M = std::flat_set<int, std::less<int>, KeyContainer<int, test_allocator<int>>>;
5255
M m(A(0, 5));
5356
assert(m.empty());
5457
assert(m.begin() == m.end());
@@ -57,8 +60,21 @@ void test() {
5760
}
5861
}
5962

63+
constexpr bool test() {
64+
test<std::vector>();
65+
#ifndef __cpp_lib_constexpr_deque
66+
if (!TEST_IS_CONSTANT_EVALUATED)
67+
#endif
68+
test<std::deque>();
69+
70+
return true;
71+
}
72+
6073
int main(int, char**) {
6174
test();
75+
#if TEST_STD_VER >= 26
76+
static_assert(test());
77+
#endif
6278

6379
return 0;
6480
}

libcxx/test/std/containers/container.adaptors/flat.set/flat.set.cons/assign_initializer_list.pass.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
#include "min_allocator.h"
2525

2626
template <class KeyContainer>
27-
void test_one() {
27+
constexpr void test_one() {
2828
using Key = typename KeyContainer::value_type;
2929
using M = std::flat_set<Key, std::less<Key>, KeyContainer>;
3030
{
@@ -45,17 +45,25 @@ void test_one() {
4545
}
4646
}
4747

48-
void test() {
48+
constexpr bool test() {
4949
test_one<std::vector<int>>();
5050
test_one<std::vector<int>>();
51-
test_one<std::deque<int>>();
51+
#ifndef __cpp_lib_constexpr_deque
52+
if (!TEST_IS_CONSTANT_EVALUATED)
53+
#endif
54+
test_one<std::deque<int>>();
5255
test_one<MinSequenceContainer<int>>();
5356
test_one<std::vector<int, min_allocator<int>>>();
5457
test_one<std::vector<int, min_allocator<int>>>();
58+
59+
return true;
5560
}
5661

5762
int main(int, char**) {
5863
test();
64+
#if TEST_STD_VER >= 26
65+
static_assert(test());
66+
#endif
5967

6068
return 0;
6169
}

0 commit comments

Comments
 (0)