diff --git a/libcxx/include/__algorithm/ranges_stable_partition.h b/libcxx/include/__algorithm/ranges_stable_partition.h index cfc02e1e97b3..d8cfc8d94145 100644 --- a/libcxx/include/__algorithm/ranges_stable_partition.h +++ b/libcxx/include/__algorithm/ranges_stable_partition.h @@ -44,7 +44,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD namespace ranges { struct __stable_partition { template - _LIBCPP_HIDE_FROM_ABI static subrange<__remove_cvref_t<_Iter>> + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR_SINCE_CXX26 subrange<__remove_cvref_t<_Iter>> __stable_partition_fn_impl(_Iter&& __first, _Sent&& __last, _Pred&& __pred, _Proj&& __proj) { auto __last_iter = ranges::next(__first, __last); @@ -60,7 +60,8 @@ struct __stable_partition { class _Proj = identity, indirect_unary_predicate> _Pred> requires permutable<_Iter> - _LIBCPP_HIDE_FROM_ABI subrange<_Iter> operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 subrange<_Iter> + operator()(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) const { return __stable_partition_fn_impl(__first, __last, __pred, __proj); } @@ -68,7 +69,7 @@ struct __stable_partition { class _Proj = identity, indirect_unary_predicate, _Proj>> _Pred> requires permutable> - _LIBCPP_HIDE_FROM_ABI borrowed_subrange_t<_Range> + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 borrowed_subrange_t<_Range> operator()(_Range&& __range, _Pred __pred, _Proj __proj = {}) const { return __stable_partition_fn_impl(ranges::begin(__range), ranges::end(__range), __pred, __proj); } diff --git a/libcxx/include/algorithm b/libcxx/include/algorithm index 0c7cea11d1a9..8758aed2a04f 100644 --- a/libcxx/include/algorithm +++ b/libcxx/include/algorithm @@ -627,12 +627,14 @@ namespace ranges { template S, class Proj = identity, indirect_unary_predicate> Pred> requires permutable - subrange stable_partition(I first, S last, Pred pred, Proj proj = {}); // since C++20 + constexpr subrange // constexpr since C++26 + stable_partition(I first, S last, Pred pred, Proj proj = {}); // since C++20 template, Proj>> Pred> requires permutable> - borrowed_subrange_t stable_partition(R&& r, Pred pred, Proj proj = {}); // since C++20 + constexpr borrowed_subrange_t // constexpr since C++26 + stable_partition(R&& r, Pred pred, Proj proj = {}); // since C++20 template S1, forward_iterator I2, sentinel_for S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> diff --git a/libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/ranges_stable_partition.pass.cpp b/libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/ranges_stable_partition.pass.cpp index 5c721059424d..615cac8c6723 100644 --- a/libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/ranges_stable_partition.pass.cpp +++ b/libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/ranges_stable_partition.pass.cpp @@ -13,12 +13,14 @@ // template S, class Proj = identity, // indirect_unary_predicate> Pred> // requires permutable -// subrange stable_partition(I first, S last, Pred pred, Proj proj = {}); // Since C++20 +// constexpr subrange // constexpr since C++26 +// stable_partition(I first, S last, Pred pred, Proj proj = {}); // Since C++20 // // template, Proj>> Pred> // requires permutable> -// borrowed_subrange_t stable_partition(R&& r, Pred pred, Proj proj = {}); // Since C++20 +// constexpr borrowed_subrange_t // constexpr since C++26 +// stable_partition(R&& r, Pred pred, Proj proj = {}); // Since C++20 #include #include @@ -85,7 +87,8 @@ static_assert(!HasStablePartitionRange, UnaryPre static_assert(!HasStablePartitionRange, UnaryPred>); template -void test_one(std::array input, Pred pred, std::size_t partition_point, std::array expected) { +TEST_CONSTEXPR_CXX26 void +test_one(std::array input, Pred pred, std::size_t partition_point, std::array expected) { auto neg_pred = [&](int x) { return !pred(x); }; { // (iterator, sentinel) overload. @@ -121,7 +124,7 @@ void test_one(std::array input, Pred pred, std::size_t partition_point, } template -void test_iterators_2() { +TEST_CONSTEXPR_CXX26 void test_iterators_2() { auto is_odd = [](int x) { return x % 2 != 0; }; // Empty sequence. @@ -157,19 +160,19 @@ void test_iterators_2() { } template -void test_iterators_1() { +TEST_CONSTEXPR_CXX26 void test_iterators_1() { test_iterators_2(); test_iterators_2>(); } -void test_iterators() { +TEST_CONSTEXPR_CXX26 void test_iterators() { test_iterators_1>(); test_iterators_1>(); test_iterators_1>(); test_iterators_1(); } -void test() { +TEST_CONSTEXPR_CXX26 bool test() { test_iterators(); { // The algorithm is stable (equivalent elements remain in the same order). @@ -238,11 +241,15 @@ void test() { } } } + + return true; } int main(int, char**) { test(); - // Note: `stable_partition` is not `constexpr`. +#if TEST_STD_VER >= 26 + static_assert(test()); +#endif return 0; } diff --git a/libcxx/test/std/algorithms/ranges_robust_against_dangling.pass.cpp b/libcxx/test/std/algorithms/ranges_robust_against_dangling.pass.cpp index 0624a6c2d49c..e8930309c866 100644 --- a/libcxx/test/std/algorithms/ranges_robust_against_dangling.pass.cpp +++ b/libcxx/test/std/algorithms/ranges_robust_against_dangling.pass.cpp @@ -197,8 +197,12 @@ constexpr bool test_all() { dangling_1st(std::ranges::shuffle, in, rand_gen()); dangling_1st(std::ranges::unique, in); dangling_1st(std::ranges::partition, in, unary_pred); +#if TEST_STD_VER < 26 if (!std::is_constant_evaluated()) +#endif + { dangling_1st(std::ranges::stable_partition, in, unary_pred); + } dangling_1st(std::ranges::sort, in); if (!std::is_constant_evaluated()) dangling_1st(std::ranges::stable_sort, in); diff --git a/libcxx/test/std/algorithms/ranges_robust_against_omitting_invoke.pass.cpp b/libcxx/test/std/algorithms/ranges_robust_against_omitting_invoke.pass.cpp index acd7640b418e..3105a3220c07 100644 --- a/libcxx/test/std/algorithms/ranges_robust_against_omitting_invoke.pass.cpp +++ b/libcxx/test/std/algorithms/ranges_robust_against_omitting_invoke.pass.cpp @@ -164,8 +164,12 @@ constexpr bool test_all() { // For `shuffle`, whether the given generator is invoked via `std::invoke` is not observable. test(std::ranges::unique, in, &Foo::binary_pred, &Bar::val); test(std::ranges::partition, in, &Foo::unary_pred, &Bar::val); +#if TEST_STD_VER < 26 if (!std::is_constant_evaluated()) +#endif + { test(std::ranges::stable_partition, in, &Foo::unary_pred, &Bar::val); + } test(std::ranges::sort, in, &Foo::binary_pred, &Bar::val); if (!std::is_constant_evaluated()) test(std::ranges::stable_sort, in, &Foo::binary_pred, &Bar::val); diff --git a/libcxx/test/std/algorithms/ranges_robust_against_proxy_iterators.pass.cpp b/libcxx/test/std/algorithms/ranges_robust_against_proxy_iterators.pass.cpp index ca1433b77875..578fecdd0aa8 100644 --- a/libcxx/test/std/algorithms/ranges_robust_against_proxy_iterators.pass.cpp +++ b/libcxx/test/std/algorithms/ranges_robust_against_proxy_iterators.pass.cpp @@ -167,8 +167,12 @@ constexpr void run_tests() { } test(std::ranges::unique, in); test(std::ranges::partition, in, unary_pred); +#if TEST_STD_VER < 26 if (!std::is_constant_evaluated()) +#endif + { test(std::ranges::stable_partition, in, unary_pred); + } test(std::ranges::sort, in); if (!std::is_constant_evaluated()) test(std::ranges::stable_sort, in);