Skip to content

Commit c28c508

Browse files
[libc++] Implement part of P2562R1: constexpr ranges::stable_partition (#129839)
1 parent 12c5a46 commit c28c508

File tree

6 files changed

+35
-13
lines changed

6 files changed

+35
-13
lines changed

libcxx/include/__algorithm/ranges_stable_partition.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
4444
namespace ranges {
4545
struct __stable_partition {
4646
template <class _Iter, class _Sent, class _Proj, class _Pred>
47-
_LIBCPP_HIDE_FROM_ABI static subrange<__remove_cvref_t<_Iter>>
47+
_LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX26 subrange<__remove_cvref_t<_Iter>>
4848
__stable_partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) {
4949
auto __last_iter = ranges::next(__first, __last);
5050

@@ -60,15 +60,16 @@ struct __stable_partition {
6060
class _Proj = identity,
6161
indirect_unary_predicate<projected<_Iter, _Proj>> _Pred>
6262
requires permutable<_Iter>
63-
_LIBCPP_HIDE_FROM_ABI subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const {
63+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 subrange<_Iter>
64+
operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const {
6465
return __stable_partition_fn_impl(__first, __last, __pred, __proj);
6566
}
6667

6768
template <bidirectional_range _Range,
6869
class _Proj = identity,
6970
indirect_unary_predicate<projected<iterator_t<_Range>, _Proj>> _Pred>
7071
requires permutable<iterator_t<_Range>>
71-
_LIBCPP_HIDE_FROM_ABI borrowed_subrange_t<_Range>
72+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 borrowed_subrange_t<_Range>
7273
operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const {
7374
return __stable_partition_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj);
7475
}

libcxx/include/algorithm

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -627,12 +627,14 @@ namespace ranges {
627627
template<bidirectional_iterator I, sentinel_for<I> S, class Proj = identity,
628628
indirect_unary_predicate<projected<I, Proj>> Pred>
629629
requires permutable<I>
630-
subrange<I> stable_partition(I first, S last, Pred pred, Proj proj = {}); // since C++20
630+
constexpr subrange<I> // constexpr since C++26
631+
stable_partition(I first, S last, Pred pred, Proj proj = {}); // since C++20
631632
632633
template<bidirectional_range R, class Proj = identity,
633634
indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred>
634635
requires permutable<iterator_t<R>>
635-
borrowed_subrange_t<R> stable_partition(R&& r, Pred pred, Proj proj = {}); // since C++20
636+
constexpr borrowed_subrange_t<R> // constexpr since C++26
637+
stable_partition(R&& r, Pred pred, Proj proj = {}); // since C++20
636638
637639
template<input_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2,
638640
class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity>

libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/ranges_stable_partition.pass.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@
1313
// template<bidirectional_iterator I, sentinel_for<I> S, class Proj = identity,
1414
// indirect_unary_predicate<projected<I, Proj>> Pred>
1515
// requires permutable<I>
16-
// subrange<I> stable_partition(I first, S last, Pred pred, Proj proj = {}); // Since C++20
16+
// constexpr subrange<I> // constexpr since C++26
17+
// stable_partition(I first, S last, Pred pred, Proj proj = {}); // Since C++20
1718
//
1819
// template<bidirectional_range R, class Proj = identity,
1920
// indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred>
2021
// requires permutable<iterator_t<R>>
21-
// borrowed_subrange_t<R> stable_partition(R&& r, Pred pred, Proj proj = {}); // Since C++20
22+
// constexpr borrowed_subrange_t<R> // constexpr since C++26
23+
// stable_partition(R&& r, Pred pred, Proj proj = {}); // Since C++20
2224

2325
#include <algorithm>
2426
#include <array>
@@ -85,7 +87,8 @@ static_assert(!HasStablePartitionRange<R<PermutableNotForwardIterator>, UnaryPre
8587
static_assert(!HasStablePartitionRange<R<PermutableNotSwappable>, UnaryPred>);
8688

8789
template <class Iter, class Sent, std::size_t N, class Pred>
88-
void test_one(std::array<int, N> input, Pred pred, std::size_t partition_point, std::array<int, N> expected) {
90+
TEST_CONSTEXPR_CXX26 void
91+
test_one(std::array<int, N> input, Pred pred, std::size_t partition_point, std::array<int, N> expected) {
8992
auto neg_pred = [&](int x) { return !pred(x); };
9093

9194
{ // (iterator, sentinel) overload.
@@ -121,7 +124,7 @@ void test_one(std::array<int, N> input, Pred pred, std::size_t partition_point,
121124
}
122125

123126
template <class Iter, class Sent>
124-
void test_iterators_2() {
127+
TEST_CONSTEXPR_CXX26 void test_iterators_2() {
125128
auto is_odd = [](int x) { return x % 2 != 0; };
126129

127130
// Empty sequence.
@@ -157,19 +160,19 @@ void test_iterators_2() {
157160
}
158161

159162
template <class Iter>
160-
void test_iterators_1() {
163+
TEST_CONSTEXPR_CXX26 void test_iterators_1() {
161164
test_iterators_2<Iter, Iter>();
162165
test_iterators_2<Iter, sentinel_wrapper<Iter>>();
163166
}
164167

165-
void test_iterators() {
168+
TEST_CONSTEXPR_CXX26 void test_iterators() {
166169
test_iterators_1<bidirectional_iterator<int*>>();
167170
test_iterators_1<random_access_iterator<int*>>();
168171
test_iterators_1<contiguous_iterator<int*>>();
169172
test_iterators_1<int*>();
170173
}
171174

172-
void test() {
175+
TEST_CONSTEXPR_CXX26 bool test() {
173176
test_iterators();
174177

175178
{ // The algorithm is stable (equivalent elements remain in the same order).
@@ -238,11 +241,15 @@ void test() {
238241
}
239242
}
240243
}
244+
245+
return true;
241246
}
242247

243248
int main(int, char**) {
244249
test();
245-
// Note: `stable_partition` is not `constexpr`.
250+
#if TEST_STD_VER >= 26
251+
static_assert(test());
252+
#endif
246253

247254
return 0;
248255
}

libcxx/test/std/algorithms/ranges_robust_against_dangling.pass.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,12 @@ constexpr bool test_all() {
197197
dangling_1st(std::ranges::shuffle, in, rand_gen());
198198
dangling_1st(std::ranges::unique, in);
199199
dangling_1st(std::ranges::partition, in, unary_pred);
200+
#if TEST_STD_VER < 26
200201
if (!std::is_constant_evaluated())
202+
#endif
203+
{
201204
dangling_1st(std::ranges::stable_partition, in, unary_pred);
205+
}
202206
dangling_1st(std::ranges::sort, in);
203207
if (!std::is_constant_evaluated())
204208
dangling_1st(std::ranges::stable_sort, in);

libcxx/test/std/algorithms/ranges_robust_against_omitting_invoke.pass.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,12 @@ constexpr bool test_all() {
164164
// For `shuffle`, whether the given generator is invoked via `std::invoke` is not observable.
165165
test(std::ranges::unique, in, &Foo::binary_pred, &Bar::val);
166166
test(std::ranges::partition, in, &Foo::unary_pred, &Bar::val);
167+
#if TEST_STD_VER < 26
167168
if (!std::is_constant_evaluated())
169+
#endif
170+
{
168171
test(std::ranges::stable_partition, in, &Foo::unary_pred, &Bar::val);
172+
}
169173
test(std::ranges::sort, in, &Foo::binary_pred, &Bar::val);
170174
if (!std::is_constant_evaluated())
171175
test(std::ranges::stable_sort, in, &Foo::binary_pred, &Bar::val);

libcxx/test/std/algorithms/ranges_robust_against_proxy_iterators.pass.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,12 @@ constexpr void run_tests() {
167167
}
168168
test(std::ranges::unique, in);
169169
test(std::ranges::partition, in, unary_pred);
170+
#if TEST_STD_VER < 26
170171
if (!std::is_constant_evaluated())
172+
#endif
173+
{
171174
test(std::ranges::stable_partition, in, unary_pred);
175+
}
172176
test(std::ranges::sort, in);
173177
if (!std::is_constant_evaluated())
174178
test(std::ranges::stable_sort, in);

0 commit comments

Comments
 (0)