[libcxx-commits] [libcxx] [libc++][pstl] Generic implementation of parallel std::is_sorted (PR #176129)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jan 15 02:51:55 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Michael G. Kazakov (mikekazakov)

<details>
<summary>Changes</summary>

This PR implements a generic backend-agnostic parallel `std::is_sorted` based on `std::transform_reduce`.

While this approach is suboptimal comparing a direct backend-specific implementation, since it doesn't support early termination and requires a reduction operation, it does show speedup when the dataset is large enough and the comparator is not absolutely trivial. For instance, this was measured on Apple M1 with `libdispatch` backend:

```
 | -------------------------------------------------------------------------------------------
 | Benchmark                                                 Time             CPU   Iterations
 | -------------------------------------------------------------------------------------------
 | std::is_sorted(vector<int>, pred)/8                    10.7 ns         9.77 ns     65611878
 | std::is_sorted(vector<int>, pred)/1024                 1362 ns         1348 ns       499533
 | std::is_sorted(vector<int>, pred)/8192                11113 ns        10852 ns        64454
 | std::is_sorted(vector<int>, pred)/65536               90459 ns        87574 ns         8203
 | std::is_sorted(vector<int>, pred)/1048576           1429824 ns      1396586 ns          498
 | std::is_sorted(vector<int>, pred)/16777216         23026696 ns     22378839 ns           31
 | std::is_sorted(vector<int>, pred)/134217728       191726083 ns    185843667 ns            3
 | std::is_sorted(par, vector<int>, pred)/8               49.1 ns         47.6 ns     14658274
 | std::is_sorted(par, vector<int>, pred)/1024            1902 ns         1742 ns       395710
 | std::is_sorted(par, vector<int>, pred)/8192           11427 ns        10409 ns        65290
 | std::is_sorted(par, vector<int>, pred)/65536          55246 ns        51234 ns        12937
 | std::is_sorted(par, vector<int>, pred)/1048576       527596 ns       473740 ns         1363
 | std::is_sorted(par, vector<int>, pred)/16777216     8287237 ns      5356766 ns          124
 | std::is_sorted(par, vector<int>, pred)/134217728   58021476 ns     46045357 ns           14
 `-----------------------------

  auto std_is_sorted_pred = [](auto first, auto last) {
    return std::is_sorted(first, last, [](auto x, auto y) {
      benchmark::DoNotOptimize(x);
      benchmark::DoNotOptimize(y);
      return sqrt(x) < sqrt(y);
    });
  };
  auto std_is_sorted_pred_par = [](auto first, auto last) {
    return std::is_sorted(std::execution::par, first, last, [](auto x, auto y) {
      benchmark::DoNotOptimize(x);
      benchmark::DoNotOptimize(y);
      return sqrt(x) < sqrt(y);
    });
  };
```

---
Full diff: https://github.com/llvm/llvm-project/pull/176129.diff


5 Files Affected:

- (modified) libcxx/include/__algorithm/pstl.h (+24) 
- (modified) libcxx/include/__pstl/backend_fwd.h (+6) 
- (modified) libcxx/include/__pstl/backends/default.h (+30) 
- (added) libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/pstl.is_sorted.pass.cpp (+188) 
- (added) libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/pstl.is_sorted_comp.pass.cpp (+189) 


``````````diff
diff --git a/libcxx/include/__algorithm/pstl.h b/libcxx/include/__algorithm/pstl.h
index 7169dd85df602..a79bac3200d6b 100644
--- a/libcxx/include/__algorithm/pstl.h
+++ b/libcxx/include/__algorithm/pstl.h
@@ -654,6 +654,30 @@ _LIBCPP_HIDE_FROM_ABI _ForwardOutIterator transform(
       std::move(__op));
 }
 
+template <class _ExecutionPolicy,
+          class _ForwardIterator,
+          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
+          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI bool is_sorted(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last) {
+  _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "is_sorted requires ForwardIterators");
+  using _Implementation = __pstl::__dispatch<__pstl::__is_sorted, __pstl::__current_configuration, _RawPolicy>;
+  return __pstl::__handle_exception<_Implementation>(
+      std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), less{});
+}
+
+template <class _ExecutionPolicy,
+          class _ForwardIterator,
+          class _Comp,
+          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
+          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+_LIBCPP_HIDE_FROM_ABI bool
+is_sorted(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Comp __comp) {
+  _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "is_sorted requires ForwardIterators");
+  using _Implementation = __pstl::__dispatch<__pstl::__is_sorted, __pstl::__current_configuration, _RawPolicy>;
+  return __pstl::__handle_exception<_Implementation>(
+      std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__comp));
+}
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP_HAS_EXPERIMENTAL_PSTL && _LIBCPP_STD_VER >= 17
diff --git a/libcxx/include/__pstl/backend_fwd.h b/libcxx/include/__pstl/backend_fwd.h
index a7d53b6a1c989..a52e6db954d0c 100644
--- a/libcxx/include/__pstl/backend_fwd.h
+++ b/libcxx/include/__pstl/backend_fwd.h
@@ -297,6 +297,12 @@ struct __reduce;
 // operator()(_Policy&&, _ForwardIterator __first, _ForwardIterator __last,
 //                       _Tp __init, _BinaryOperation __op) const noexcept;
 
+template <class _Backend, class _ExecutionPolicy>
+struct __is_sorted;
+// template <class _Policy, class _ForwardIterator, class _Comp>
+// optional<bool>
+// operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Comp&& __comp) const noexcept;
+
 } // namespace __pstl
 _LIBCPP_END_NAMESPACE_STD
 
diff --git a/libcxx/include/__pstl/backends/default.h b/libcxx/include/__pstl/backends/default.h
index 43b1f1ce3870a..9fa642b080f64 100644
--- a/libcxx/include/__pstl/backends/default.h
+++ b/libcxx/include/__pstl/backends/default.h
@@ -13,6 +13,7 @@
 #include <__algorithm/equal.h>
 #include <__algorithm/fill_n.h>
 #include <__algorithm/for_each_n.h>
+#include <__algorithm/is_sorted.h>
 #include <__config>
 #include <__functional/identity.h>
 #include <__functional/not_fn.h>
@@ -388,6 +389,35 @@ struct __reduce<__default_backend_tag, _ExecutionPolicy> {
   }
 };
 
+template <class _ExecutionPolicy>
+struct __is_sorted<__default_backend_tag, _ExecutionPolicy> {
+  template <class _Policy, class _ForwardIterator, class _Comp>
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI optional<bool>
+  operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _Comp&& __comp) const noexcept {
+    if constexpr (__has_random_access_iterator_category<_ForwardIterator>::value) {
+      if (__first == __last)
+        return true; // Empty, sorted by definition
+      _ForwardIterator __first2 = __first + 1;
+      if (__first2 == __last)
+        return true; // Only one element, sorted by definition
+      --__last;
+      using _TransformReduce = __dispatch<__transform_reduce_binary, __current_configuration, _ExecutionPolicy>;
+      using _Ref             = __iterator_reference<_ForwardIterator>;
+      return _TransformReduce()(
+          __policy,
+          std::move(__first),
+          std::move(__last),
+          std::move(__first2),
+          true,
+          std::logical_and{},
+          [&](_Ref __first, _Ref __second) -> bool { return !__comp(__second, __first); });
+    } else {
+      // Currently anything outside random access iterators has to be processed serially
+      return std::is_sorted(std::move(__first), std::move(__last), std::forward<_Comp>(__comp));
+    }
+  }
+};
+
 //////////////////////////////////////////////////////////////
 // transform family
 //////////////////////////////////////////////////////////////
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/pstl.is_sorted.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/pstl.is_sorted.pass.cpp
new file mode 100644
index 0000000000000..9bffa588f0858
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/pstl.is_sorted.pass.cpp
@@ -0,0 +1,188 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// template<class ExecutionPolicy, class ForwardIterator,
+//   bool is_sorted(ExecutionPolicy&& exec,
+//                  ForwardIterator first, ForwardIterator last);
+
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <numeric>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+
+template <class Iter>
+struct Test {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    {
+      int a[]     = {0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a)));
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {0, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {0, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {1, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {1, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+
+    {
+      int a[]     = {0, 0, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {0, 0, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {0, 1, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {0, 1, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {1, 0, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {1, 0, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {1, 1, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {1, 1, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+
+    {
+      int a[]     = {0, 0, 0, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {0, 0, 0, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {0, 0, 1, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {0, 0, 1, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {0, 1, 0, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {0, 1, 0, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {0, 1, 1, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {0, 1, 1, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {1, 0, 0, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {1, 0, 0, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {1, 0, 1, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {1, 0, 1, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {1, 1, 0, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {1, 1, 0, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {1, 1, 1, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+    {
+      int a[]     = {1, 1, 1, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa)));
+    }
+  }
+};
+
+int main(int, char**) {
+  types::for_each(types::concatenate_t<types::forward_iterator_list<int*>,
+                                       types::bidirectional_iterator_list<int*>,
+                                       types::random_access_iterator_list<int*>>{},
+                  TestIteratorWithPolicies<Test>{});
+
+  return 0;
+}
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/pstl.is_sorted_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/pstl.is_sorted_comp.pass.cpp
new file mode 100644
index 0000000000000..aa57678a5ec2a
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.sort/is.sorted/pstl.is_sorted_comp.pass.cpp
@@ -0,0 +1,189 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// template<class ExecutionPolicy, class ForwardIterator, class Comp>
+//   bool is_sorted(ExecutionPolicy&& exec,
+//                  ForwardIterator first, ForwardIterator last,
+//                  Comp comp);
+
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <numeric>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+
+template <class Iter>
+struct Test {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    {
+      int a[]     = {0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a)));
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {0, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {0, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {1, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {1, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+
+    {
+      int a[]     = {0, 0, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {0, 0, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {0, 1, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {0, 1, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {1, 0, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {1, 0, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {1, 1, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {1, 1, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+
+    {
+      int a[]     = {0, 0, 0, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {0, 0, 0, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {0, 0, 1, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {0, 0, 1, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {0, 1, 0, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {0, 1, 0, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {0, 1, 1, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {0, 1, 1, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {1, 0, 0, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {1, 0, 0, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {1, 0, 1, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {1, 0, 1, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {1, 1, 0, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {1, 1, 0, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(!std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {1, 1, 1, 0};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+    {
+      int a[]     = {1, 1, 1, 1};
+      unsigned sa = sizeof(a) / sizeof(a[0]);
+      assert(std::is_sorted(policy, Iter(a), Iter(a + sa), std::greater<int>()));
+    }
+  }
+};
+
+int main(int, char**) {
+  types::for_each(types::concatenate_t<types::forward_iterator_list<int*>,
+                                       types::bidirectional_iterator_list<int*>,
+                                       types::random_access_iterator_list<int*>>{},
+                  TestIteratorWithPolicies<Test>{});
+
+  return 0;
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/176129


More information about the libcxx-commits mailing list