[libcxx-commits] [libcxx] c28c508 - [libc++] Implement part of P2562R1: constexpr `ranges::stable_partition` (#129839)

via libcxx-commits libcxx-commits at lists.llvm.org
Wed Mar 5 17:23:59 PST 2025


Author: A. Jiang
Date: 2025-03-06T09:23:55+08:00
New Revision: c28c5089628a443e0f848c2860f5e59e68efe301

URL: https://github.com/llvm/llvm-project/commit/c28c5089628a443e0f848c2860f5e59e68efe301
DIFF: https://github.com/llvm/llvm-project/commit/c28c5089628a443e0f848c2860f5e59e68efe301.diff

LOG: [libc++] Implement part of P2562R1: constexpr `ranges::stable_partition` (#129839)

Added: 
    

Modified: 
    libcxx/include/__algorithm/ranges_stable_partition.h
    libcxx/include/algorithm
    libcxx/test/std/algorithms/alg.modifying.operations/alg.partitions/ranges_stable_partition.pass.cpp
    libcxx/test/std/algorithms/ranges_robust_against_dangling.pass.cpp
    libcxx/test/std/algorithms/ranges_robust_against_omitting_invoke.pass.cpp
    libcxx/test/std/algorithms/ranges_robust_against_proxy_iterators.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__algorithm/ranges_stable_partition.h b/libcxx/include/__algorithm/ranges_stable_partition.h
index cfc02e1e97b3f..d8cfc8d941450 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 <class _Iter, class _Sent, class _Proj, class _Pred>
-  _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<projected<_Iter, _Proj>> _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<projected<iterator_t<_Range>, _Proj>> _Pred>
     requires permutable<iterator_t<_Range>>
-  _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 0c7cea11d1a91..8758aed2a04f9 100644
--- a/libcxx/include/algorithm
+++ b/libcxx/include/algorithm
@@ -627,12 +627,14 @@ namespace ranges {
   template<bidirectional_iterator I, sentinel_for<I> S, class Proj = identity,
            indirect_unary_predicate<projected<I, Proj>> Pred>
     requires permutable<I>
-    subrange<I> stable_partition(I first, S last, Pred pred, Proj proj = {});               // since C++20
+    constexpr subrange<I>                                                                   // constexpr since C++26
+      stable_partition(I first, S last, Pred pred, Proj proj = {});                         // since C++20
 
   template<bidirectional_range R, class Proj = identity,
            indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred>
     requires permutable<iterator_t<R>>
-    borrowed_subrange_t<R> stable_partition(R&& r, Pred pred, Proj proj = {});              // since C++20
+    constexpr borrowed_subrange_t<R>                                                        // constexpr since C++26
+      stable_partition(R&& r, Pred pred, Proj proj = {});                                   // since C++20
 
   template<input_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> 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 5c721059424da..615cac8c67239 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<bidirectional_iterator I, sentinel_for<I> S, class Proj = identity,
 //          indirect_unary_predicate<projected<I, Proj>> Pred>
 //   requires permutable<I>
-//   subrange<I> stable_partition(I first, S last, Pred pred, Proj proj = {});                      // Since C++20
+//   constexpr subrange<I>                                                         // constexpr since C++26
+//     stable_partition(I first, S last, Pred pred, Proj proj = {});               // Since C++20
 //
 // template<bidirectional_range R, class Proj = identity,
 //          indirect_unary_predicate<projected<iterator_t<R>, Proj>> Pred>
 //   requires permutable<iterator_t<R>>
-//   borrowed_subrange_t<R> stable_partition(R&& r, Pred pred, Proj proj = {});                     // Since C++20
+//   constexpr borrowed_subrange_t<R>                                              // constexpr since C++26
+//     stable_partition(R&& r, Pred pred, Proj proj = {});                         // Since C++20
 
 #include <algorithm>
 #include <array>
@@ -85,7 +87,8 @@ static_assert(!HasStablePartitionRange<R<PermutableNotForwardIterator>, UnaryPre
 static_assert(!HasStablePartitionRange<R<PermutableNotSwappable>, UnaryPred>);
 
 template <class Iter, class Sent, std::size_t N, class Pred>
-void test_one(std::array<int, N> input, Pred pred, std::size_t partition_point, std::array<int, N> expected) {
+TEST_CONSTEXPR_CXX26 void
+test_one(std::array<int, N> input, Pred pred, std::size_t partition_point, std::array<int, N> expected) {
   auto neg_pred = [&](int x) { return !pred(x); };
 
   { // (iterator, sentinel) overload.
@@ -121,7 +124,7 @@ void test_one(std::array<int, N> input, Pred pred, std::size_t partition_point,
 }
 
 template <class Iter, class Sent>
-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 <class Iter>
-void test_iterators_1() {
+TEST_CONSTEXPR_CXX26 void test_iterators_1() {
   test_iterators_2<Iter, Iter>();
   test_iterators_2<Iter, sentinel_wrapper<Iter>>();
 }
 
-void test_iterators() {
+TEST_CONSTEXPR_CXX26 void test_iterators() {
   test_iterators_1<bidirectional_iterator<int*>>();
   test_iterators_1<random_access_iterator<int*>>();
   test_iterators_1<contiguous_iterator<int*>>();
   test_iterators_1<int*>();
 }
 
-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 0624a6c2d49c7..e8930309c8662 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 acd7640b418eb..3105a3220c078 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 ca1433b778751..578fecdd0aa83 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);


        


More information about the libcxx-commits mailing list