[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