[libcxx-commits] [libcxx] [libc++][pstl] Implementation of parallel std::search() based on __parallel_find() (PR #215119)
Michael G. Kazakov via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Aug 13 04:19:53 PDT 2026
https://github.com/mikekazakov updated https://github.com/llvm/llvm-project/pull/215119
>From fac39056f79ffea7fb8a94f0503a53eabebc0fff Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Sun, 9 Aug 2026 18:32:40 +0100
Subject: [PATCH 1/2] Implementation of parallel std::search()
---
libcxx/include/CMakeLists.txt | 1 +
libcxx/include/__algorithm/pstl.h | 48 ++++
libcxx/include/__pstl/backend_fwd.h | 7 +
libcxx/include/__pstl/backends/default.h | 4 +
libcxx/include/__pstl/backends/libdispatch.h | 5 +
libcxx/include/__pstl/backends/serial.h | 16 ++
libcxx/include/__pstl/backends/std_thread.h | 5 +
libcxx/include/__pstl/cpu_algos/search.h | 102 +++++++
libcxx/include/module.modulemap.in | 3 +
.../pstl.iterator-requirements.verify.cpp | 8 +
.../algorithms/pstl.nodiscard.verify.cpp | 4 +
.../alg.search/pstl.search.pass.cpp | 262 +++++++++++++++++
.../alg.search/pstl.search_pred.pass.cpp | 269 ++++++++++++++++++
.../pstl.exception_handling.pass.cpp | 14 +
14 files changed, 748 insertions(+)
create mode 100644 libcxx/include/__pstl/cpu_algos/search.h
create mode 100644 libcxx/test/std/algorithms/alg.nonmodifying/alg.search/pstl.search.pass.cpp
create mode 100644 libcxx/test/std/algorithms/alg.nonmodifying/alg.search/pstl.search_pred.pass.cpp
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index d24ae7a73a825..07513bc317a60 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -699,6 +699,7 @@ set(files
__pstl/cpu_algos/merge.h
__pstl/cpu_algos/mismatch.h
__pstl/cpu_algos/reverse.h
+ __pstl/cpu_algos/search.h
__pstl/cpu_algos/stable_sort.h
__pstl/cpu_algos/transform.h
__pstl/cpu_algos/transform_reduce.h
diff --git a/libcxx/include/__algorithm/pstl.h b/libcxx/include/__algorithm/pstl.h
index d27044ecdc8b9..15344bc60a59b 100644
--- a/libcxx/include/__algorithm/pstl.h
+++ b/libcxx/include/__algorithm/pstl.h
@@ -792,6 +792,54 @@ _LIBCPP_HIDE_FROM_ABI _ForwardOutIterator rotate_copy(
std::move(__result));
}
+template <class _ExecutionPolicy,
+ class _ForwardIterator1,
+ class _ForwardIterator2,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _ForwardIterator1
+search(_ExecutionPolicy&& __policy,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2) {
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "search requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "search requires ForwardIterators");
+ using _Implementation = __pstl::__dispatch<__pstl::__search, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy),
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ equal_to<>{});
+}
+
+template <class _ExecutionPolicy,
+ class _ForwardIterator1,
+ class _ForwardIterator2,
+ class _BinaryPredicate,
+ class _RawPolicy = __remove_cvref_t<_ExecutionPolicy>,
+ enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _ForwardIterator1
+search(_ExecutionPolicy&& __policy,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _BinaryPredicate __pred) {
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator1, "search requires ForwardIterators");
+ _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator2, "search requires ForwardIterators");
+ using _Implementation = __pstl::__dispatch<__pstl::__search, __pstl::__current_configuration, _RawPolicy>;
+ return __pstl::__handle_exception<_Implementation>(
+ std::forward<_ExecutionPolicy>(__policy),
+ std::move(__first1),
+ std::move(__last1),
+ std::move(__first2),
+ std::move(__last2),
+ std::move(__pred));
+}
+
template <class _ExecutionPolicy,
class _RandomAccessIterator,
class _Comp,
diff --git a/libcxx/include/__pstl/backend_fwd.h b/libcxx/include/__pstl/backend_fwd.h
index c5a219fb59db2..a2fb13a8f0c01 100644
--- a/libcxx/include/__pstl/backend_fwd.h
+++ b/libcxx/include/__pstl/backend_fwd.h
@@ -140,6 +140,13 @@ struct __fill_n;
// optional<__empty>
// operator()(_Policy&&, _ForwardIterator __first, _Size __n, _Tp const& __value) const noexcept;
+template <class _Backend, class _ExecutionPolicy>
+struct __search;
+// template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
+// optional<_ForwardIterator1>
+// operator()(_Policy&&, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
+// _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __pred) const noexcept;
+
template <class _Backend, class _ExecutionPolicy>
struct __replace;
// template <class _Policy, class _ForwardIterator, class _Tp>
diff --git a/libcxx/include/__pstl/backends/default.h b/libcxx/include/__pstl/backends/default.h
index 43bac357efd95..093ca2cd56b70 100644
--- a/libcxx/include/__pstl/backends/default.h
+++ b/libcxx/include/__pstl/backends/default.h
@@ -98,6 +98,10 @@ namespace __pstl {
// ------------
// No other algorithms based on reverse
//
+// search family
+// ------------
+// No other algorithms based on search
+//
// stable_sort family
// ------------------
// - sort
diff --git a/libcxx/include/__pstl/backends/libdispatch.h b/libcxx/include/__pstl/backends/libdispatch.h
index ee698742152f3..2e4eef5de033a 100644
--- a/libcxx/include/__pstl/backends/libdispatch.h
+++ b/libcxx/include/__pstl/backends/libdispatch.h
@@ -42,6 +42,7 @@
#include <__pstl/cpu_algos/merge.h>
#include <__pstl/cpu_algos/mismatch.h>
#include <__pstl/cpu_algos/reverse.h>
+#include <__pstl/cpu_algos/search.h>
#include <__pstl/cpu_algos/stable_sort.h>
#include <__pstl/cpu_algos/transform.h>
#include <__pstl/cpu_algos/transform_reduce.h>
@@ -380,6 +381,10 @@ template <class _ExecutionPolicy>
struct __reverse<__libdispatch_backend_tag, _ExecutionPolicy>
: __cpu_parallel_reverse<__libdispatch_backend_tag, _ExecutionPolicy> {};
+template <class _ExecutionPolicy>
+struct __search<__libdispatch_backend_tag, _ExecutionPolicy>
+ : __cpu_parallel_search<__libdispatch_backend_tag, _ExecutionPolicy> {};
+
template <class _ExecutionPolicy>
struct __stable_sort<__libdispatch_backend_tag, _ExecutionPolicy>
: __cpu_parallel_stable_sort<__libdispatch_backend_tag, _ExecutionPolicy> {};
diff --git a/libcxx/include/__pstl/backends/serial.h b/libcxx/include/__pstl/backends/serial.h
index 13c515b356608..4025d3d7d598e 100644
--- a/libcxx/include/__pstl/backends/serial.h
+++ b/libcxx/include/__pstl/backends/serial.h
@@ -15,6 +15,7 @@
#include <__algorithm/merge.h>
#include <__algorithm/mismatch.h>
#include <__algorithm/reverse.h>
+#include <__algorithm/search.h>
#include <__algorithm/stable_sort.h>
#include <__algorithm/transform.h>
#include <__config>
@@ -117,6 +118,21 @@ struct __reverse<__serial_backend_tag, _ExecutionPolicy> {
}
};
+template <class _ExecutionPolicy>
+struct __search<__serial_backend_tag, _ExecutionPolicy> {
+ template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
+ _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator1>
+ operator()(_Policy&&,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _BinaryPredicate __pred) const noexcept {
+ return std::search(
+ std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::move(__pred));
+ }
+};
+
template <class _ExecutionPolicy>
struct __stable_sort<__serial_backend_tag, _ExecutionPolicy> {
template <class _Policy, class _RandomAccessIterator, class _Comp>
diff --git a/libcxx/include/__pstl/backends/std_thread.h b/libcxx/include/__pstl/backends/std_thread.h
index d0b15c8ed1f00..2e8b64fd344be 100644
--- a/libcxx/include/__pstl/backends/std_thread.h
+++ b/libcxx/include/__pstl/backends/std_thread.h
@@ -21,6 +21,7 @@
#include <__pstl/cpu_algos/merge.h>
#include <__pstl/cpu_algos/mismatch.h>
#include <__pstl/cpu_algos/reverse.h>
+#include <__pstl/cpu_algos/search.h>
#include <__pstl/cpu_algos/stable_sort.h>
#include <__pstl/cpu_algos/transform.h>
#include <__pstl/cpu_algos/transform_reduce.h>
@@ -111,6 +112,10 @@ template <class _ExecutionPolicy>
struct __reverse<__std_thread_backend_tag, _ExecutionPolicy>
: __cpu_parallel_reverse<__std_thread_backend_tag, _ExecutionPolicy> {};
+template <class _ExecutionPolicy>
+struct __search<__std_thread_backend_tag, _ExecutionPolicy>
+ : __cpu_parallel_search<__std_thread_backend_tag, _ExecutionPolicy> {};
+
template <class _ExecutionPolicy>
struct __stable_sort<__std_thread_backend_tag, _ExecutionPolicy>
: __cpu_parallel_stable_sort<__std_thread_backend_tag, _ExecutionPolicy> {};
diff --git a/libcxx/include/__pstl/cpu_algos/search.h b/libcxx/include/__pstl/cpu_algos/search.h
new file mode 100644
index 0000000000000..e74f9bebbe3ad
--- /dev/null
+++ b/libcxx/include/__pstl/cpu_algos/search.h
@@ -0,0 +1,102 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___PSTL_CPU_ALGOS_SEARCH_H
+#define _LIBCPP___PSTL_CPU_ALGOS_SEARCH_H
+
+#include <__algorithm/search.h>
+#include <__config>
+#include <__functional/operations.h>
+#include <__iterator/concepts.h>
+#include <__iterator/iterator_traits.h>
+#include <__optional/nullopt_t.h>
+#include <__optional/optional.h>
+#include <__pstl/backend_fwd.h>
+#include <__pstl/cpu_algos/cpu_traits.h>
+#include <__pstl/cpu_algos/find_if.h>
+#include <__type_traits/is_execution_policy.h>
+#include <__utility/convert_to_integral.h>
+#include <__utility/move.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#if _LIBCPP_STD_VER >= 17
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+namespace __pstl {
+
+template <class _Backend, class _RawExecutionPolicy>
+struct __cpu_parallel_search {
+ template <class _Policy, class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
+ _LIBCPP_HIDE_FROM_ABI optional<_ForwardIterator1>
+ operator()(_Policy&&,
+ _ForwardIterator1 __first1,
+ _ForwardIterator1 __last1,
+ _ForwardIterator2 __first2,
+ _ForwardIterator2 __last2,
+ _BinaryPredicate __pred) const noexcept {
+ if constexpr (__is_parallel_execution_policy_v<_RawExecutionPolicy> &&
+ __has_random_access_iterator_category_or_concept<_ForwardIterator1>::value &&
+ __has_random_access_iterator_category_or_concept<_ForwardIterator2>::value) {
+ typedef typename std::iterator_traits<_ForwardIterator1>::difference_type _DifferenceType;
+ _DifferenceType __size2 = __last2 - __first2; // The length of the needle to search for.
+ if (__size2 == 0) {
+ return __first1; // If the needle length is zero, the first iterator is returned.
+ }
+ _DifferenceType __size1 = __last1 - __first1;
+ if (__size1 < __size2) {
+ return __last1; // The range is too small to contain the requested number of consecutive elements.
+ }
+ // Calculate the length of the tail where a potential match cannot start by definition.
+ _DifferenceType __crop = __size2 - 1;
+ // We're only interested in the range where a potential match can start: [first, last - crop)
+ _ForwardIterator1 __last1_cropped = __last1 - __crop;
+ // Run a parallel chunked find_if, covering the range where a potential match can start.
+ auto __res = __pstl::__parallel_find<_Backend>(
+ __first1,
+ __last1_cropped,
+ [__first2, __last2, __crop, &__pred](_ForwardIterator1 __brick_first, _ForwardIterator1 __brick_last) {
+ // Uncrop the range to allow std::search to find a full match, which can go beyond __brick_last.
+ _ForwardIterator1 __brick_last_uncropped = __brick_last + __crop;
+ // Run a serial std::search inside each of the chunks in parallel.
+ _ForwardIterator1 __ret = std::search(__brick_first, __brick_last_uncropped, __first2, __last2, __pred);
+ // The returned iterator is either a match inside [__brick_first, __brick_last) or a miss encoded as
+ // __brick_last_uncropped. Return the miss as __brick_last to conform to expectations of __parallel_find().
+ return __ret == __brick_last_uncropped ? __brick_last : __ret;
+ },
+ less<>{}, // `less` here means the lowest index among the matches
+ true // `true` here means we want the first match, not the last
+ );
+ if (!__res) {
+ return std::nullopt; // Failed to run the algorithm, propagate the error.
+ }
+ if (*__res == __last1_cropped) {
+ return __last1; // No match was found in the range.
+ }
+ return *__res; // Return the successful match.
+ } else {
+ // Non-random access iterators cannot be processed in parallel, fall back to the sequential implementation.
+ return std::search(
+ std::move(__first1), std::move(__last1), std::move(__first2), std::move(__last2), std::move(__pred));
+ }
+ }
+};
+
+} // namespace __pstl
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER >= 17
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___PSTL_CPU_ALGOS_SEARCH_H
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index a5eac9fc149f0..d774df7458898 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -2437,6 +2437,9 @@ module std {
module reverse {
header "__pstl/cpu_algos/reverse.h"
}
+ module search {
+ header "__pstl/cpu_algos/search.h"
+ }
module stable_sort {
header "__pstl/cpu_algos/stable_sort.h"
export std_core.utility_core.empty
diff --git a/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp b/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
index 2d510be58e164..f8cae6ee6d656 100644
--- a/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
+++ b/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
@@ -223,6 +223,14 @@ void f(non_forward_iterator non_fwd,
(void)std::rotate_copy(pol, it, it, it, non_output); // expected-error@*:* {{static assertion failed: rotate_copy}}
}
+ {
+ (void)std::search(pol, non_fwd, non_fwd, it, it); // expected-error@*:* {{static assertion failed: search}}
+ (void)std::search(pol, it, it, non_fwd, non_fwd); // expected-error@*:* {{static assertion failed: search}}
+
+ (void)std::search(pol, non_fwd, non_fwd, it, it, pred); // expected-error@*:* {{static assertion failed: search}}
+ (void)std::search(pol, it, it, non_fwd, non_fwd, pred); // expected-error@*:* {{static assertion failed: search}}
+ }
+
{
(void)std::sort(pol, non_fwd, non_fwd); // expected-error@*:* {{static assertion failed: sort}}
(void)std::sort(pol, non_fwd, non_fwd, pred); // expected-error@*:* {{static assertion failed: sort}}
diff --git a/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp b/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp
index 37e843eb90fe1..766df3cc8bc4e 100644
--- a/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp
@@ -83,4 +83,8 @@ void test() {
std::lexicographical_compare(std::execution::par, std::begin(a), std::end(a), std::begin(b), std::end(b));
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::lexicographical_compare(std::execution::par, std::begin(a), std::end(a), std::begin(b), std::end(b), pred2);
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::search(std::execution::par, std::begin(a), std::end(a), std::begin(b), std::end(b));
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::search(std::execution::par, std::begin(a), std::end(a), std::begin(b), std::end(b), pred2);
}
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/pstl.search.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/pstl.search.pass.cpp
new file mode 100644
index 0000000000000..cc4abf51d23c4
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/pstl.search.pass.cpp
@@ -0,0 +1,262 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// <algorithm>
+
+// template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2>
+// ForwardIterator1
+// search(ExecutionPolicy&& exec,
+// ForwardIterator1 first1, ForwardIterator1 last1,
+// ForwardIterator2 first2, ForwardIterator2 last2);
+
+#include <cstddef>
+#include <algorithm>
+#include <cassert>
+#include <iterator>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "runway_sample.h"
+
+EXECUTION_POLICY_SFINAE_TEST(search);
+
+static_assert(sfinae_test_search<int, int*, int*, int*, int*>);
+static_assert(!sfinae_test_search<std::execution::parallel_policy, int*, int*, int*, int*>);
+
+template <class Iter1, class Iter2>
+struct Test {
+ template <class ExecutionPolicy>
+ void operator()(ExecutionPolicy&& policy) {
+ { // Check the return type
+ int a[] = {0};
+ int b[] = {0};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ static_assert(std::is_same_v<decltype(res), Iter1>);
+ }
+ { // Empty haystack, empty needle
+ int a[] = {0};
+ int b[] = {0};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::begin(a)), Iter2(std::begin(b)), Iter2(std::begin(b)));
+ assert(res == Iter1(std::begin(a)));
+ }
+ { // Empty haystack, non-empty needle
+ int a[] = {0};
+ int b[] = {0};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::begin(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::begin(a)));
+ }
+ { // Non-empty haystack, empty needle
+ int a[] = {0};
+ int b[] = {0};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::begin(b)));
+ assert(res == Iter1(std::begin(a)));
+ }
+ { // Both single element, same
+ int a[] = {0};
+ int b[] = {0};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::begin(a)));
+ }
+ { // Both single element, different
+ int a[] = {0};
+ int b[] = {1};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::end(a)));
+ }
+ { // Needle found at beginning
+ int a[] = {0, 1, 2, 3, 4, 5};
+ int b[] = {0};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::begin(a)));
+ }
+ { // Needle found in middle
+ int a[] = {0, 1, 2, 3, 4, 5};
+ int b[] = {1};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::begin(a) + 1));
+ }
+ { // Needle found at end
+ int a[] = {0, 1, 2, 3, 4, 5};
+ int b[] = {5};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::end(a) - 1));
+ }
+ { // Multiple element needle found at beginning
+ int a[] = {0, 1, 2, 3, 4, 5};
+ int b[] = {0, 1, 2, 3, 4, 5};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::begin(a)));
+ }
+ { // Multiple element needle found in middle
+ int a[] = {0, 1, 2, 3, 4, 5};
+ int b[] = {2};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::begin(a) + 2));
+ }
+ { // Multiple element needle found at end
+ int a[] = {0, 1, 2, 3, 4, 5};
+ int b[] = {3, 4, 5};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::begin(a) + 3));
+ }
+ { // Needle too long for haystack
+ int a[] = {0, 1, 2, 3, 4};
+ int b[] = {0, 1, 2, 3, 4, 5};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::end(a)));
+ }
+ { // Needle much longer than haystack
+ int a[] = {0};
+ int b[] = {0, 1, 2, 3, 4, 5};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::end(a)));
+ }
+ { // Multiple needles with size=1, the first one is found
+ int a[] = {0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4};
+ int b[] = {1};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::begin(a) + 1));
+ }
+ { // Multiple needles with size=2, the first one is found
+ int a[] = {0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4};
+ int b[] = {1, 2};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::begin(a) + 1));
+ }
+ { // Multiple needles with size=3, the first one is found
+ int a[] = {0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4};
+ int b[] = {1, 2, 3};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::begin(a) + 4));
+ }
+ { // Single needle with size=4, found at end
+ int a[] = {0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4};
+ int b[] = {1, 2, 3, 4};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::begin(a) + 8));
+ }
+ { // Needle with repeated elements in the prefix
+ int a[] = {0, 1, 1, 1, 1, 2, 3, 0, 1, 2, 3, 4};
+ int b[] = {1, 1, 2};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::begin(a) + 3));
+ }
+ { // Long needle, found at the end
+ int a[] = {0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0};
+ int b[] = {0, 0, 0, 0, 1, 1, 1, 1, 0, 0};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::begin(a) + 6));
+ }
+ { // Needle not found - no match exists
+ int a[] = {0, 1, 2, 3, 4, 5};
+ int b[] = {6};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::end(a)));
+ }
+ { // Needle not found, size=3
+ int a[] = {0, 1, 2, 3, 4, 5};
+ int b[] = {4, 5, 6};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::end(a)));
+ }
+ { // Partial match, fails at last element
+ int a[] = {0, 1, 2, 3, 4, 5, 6};
+ int b[] = {3, 4, 6};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::end(a)));
+ }
+ { // Partial match, fails in middle
+ int a[] = {0, 1, 2, 4, 5};
+ int b[] = {1, 3, 4};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::end(a)));
+ }
+ { // All elements identical in haystack
+ int a[] = {7, 7, 7, 7, 7, 7};
+ int b[] = {7, 7};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::begin(a)));
+ }
+ { // Multiple partial matches before real match
+ int a[] = {1, 2, 1, 2, 1, 2, 3};
+ int b[] = {1, 2, 3};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::begin(a) + 4));
+ }
+ { // Alternating pattern
+ int a[] = {0, 1, 0, 1, 0, 1, 0, 1};
+ int b[] = {1, 0, 1, 0};
+ auto res =
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)));
+ assert(res == Iter1(std::begin(a) + 1));
+ }
+ { // Many elements, needles found at various sampled positions
+ int a[1073];
+ std::fill(std::begin(a), std::end(a), 0);
+ int b[] = {1};
+ int c[] = {1, 0, 0};
+ int d[] = {1, 0, 0, 0, 0};
+ runway_sample(std::size(a) - std::size(d) + 1, [&](std::size_t i) {
+ a[i] = 1;
+ assert(
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b))) ==
+ Iter1(std::begin(a) + i));
+ assert(
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(c)), Iter2(std::end(c))) ==
+ Iter1(std::begin(a) + i));
+ assert(
+ std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(d)), Iter2(std::end(d))) ==
+ Iter1(std::begin(a) + i));
+ a[i] = 0;
+ });
+ }
+ }
+};
+
+int main(int, char**) {
+ types::for_each(types::forward_iterator_list<int*>{}, types::apply_type_identity{[](auto v) {
+ using Iter = typename decltype(v)::type;
+ types::for_each(
+ types::forward_iterator_list<int*>{},
+ TestIteratorWithPolicies< types::partial_instantiation<Test, Iter>::template apply>{});
+ }});
+
+ return 0;
+}
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/pstl.search_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/pstl.search_pred.pass.cpp
new file mode 100644
index 0000000000000..a45c484b8245f
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/pstl.search_pred.pass.cpp
@@ -0,0 +1,269 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++17
+
+// UNSUPPORTED: libcpp-has-no-incomplete-pstl
+
+// <algorithm>
+
+// template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>
+// ForwardIterator1
+// search(ExecutionPolicy&& exec,
+// ForwardIterator1 first1, ForwardIterator1 last1,
+// ForwardIterator2 first2, ForwardIterator2 last2,
+// BinaryPredicate p);
+
+#include <cstddef>
+#include <algorithm>
+#include <cassert>
+#include <iterator>
+
+#include "test_execution_policies.h"
+#include "test_iterators.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+#include "runway_sample.h"
+
+EXECUTION_POLICY_SFINAE_TEST(search);
+
+static_assert(sfinae_test_search<int, int*, int*, int*, int*>);
+static_assert(!sfinae_test_search<std::execution::parallel_policy, int*, int*, int*, int*>);
+
+struct Pred {
+ bool operator()(int lhs, int rhs) const { return lhs * 2 == rhs; }
+};
+
+template <class Iter1, class Iter2>
+struct Test {
+ template <class ExecutionPolicy>
+ void operator()(ExecutionPolicy&& policy) {
+ { // Check the return type
+ int a[] = {1};
+ int b[] = {1};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ static_assert(std::is_same_v<decltype(res), Iter1>);
+ }
+ { // Empty haystack, empty needle
+ int a[] = {1};
+ int b[] = {1};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::begin(a)), Iter2(std::begin(b)), Iter2(std::begin(b)), Pred{});
+ assert(res == Iter1(std::begin(a)));
+ }
+ { // Empty haystack, non-empty needle
+ int a[] = {1};
+ int b[] = {1};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::begin(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::begin(a)));
+ }
+ { // Non-empty haystack, empty needle
+ int a[] = {1};
+ int b[] = {1};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::begin(b)), Pred{});
+ assert(res == Iter1(std::begin(a)));
+ }
+ { // Both single element, same
+ int a[] = {1};
+ int b[] = {2};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::begin(a)));
+ }
+ { // Both single element, different
+ int a[] = {1};
+ int b[] = {1};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::end(a)));
+ }
+ { // Needle found at beginning
+ int a[] = {1, 2, 3, 4, 5, 6};
+ int b[] = {2};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::begin(a)));
+ }
+ { // Needle found in middle
+ int a[] = {1, 2, 3, 4, 5, 6};
+ int b[] = {4};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::begin(a) + 1));
+ }
+ { // Needle found at end
+ int a[] = {1, 2, 3, 4, 5, 6};
+ int b[] = {12};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::end(a) - 1));
+ }
+ { // Multiple element needle found at beginning
+ int a[] = {1, 2, 3, 4, 5, 6};
+ int b[] = {2, 4, 6, 8, 10, 12};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::begin(a)));
+ }
+ { // Multiple element needle found in middle
+ int a[] = {1, 2, 3, 4, 5, 6};
+ int b[] = {6};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::begin(a) + 2));
+ }
+ { // Multiple element needle found at end
+ int a[] = {1, 2, 3, 4, 5, 6};
+ int b[] = {8, 10, 12};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::begin(a) + 3));
+ }
+ { // Needle too long for haystack
+ int a[] = {1, 2, 3, 4, 5};
+ int b[] = {2, 4, 6, 8, 10, 12};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::end(a)));
+ }
+ { // Needle much longer than haystack
+ int a[] = {0};
+ int b[] = {0, 1, 2, 3, 4, 5};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::end(a)));
+ }
+ { // Multiple needles with size=1, the first one is found
+ int a[] = {0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4};
+ int b[] = {2};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::begin(a) + 1));
+ }
+ { // Multiple needles with size=2, the first one is found
+ int a[] = {0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4};
+ int b[] = {2, 4};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::begin(a) + 1));
+ }
+ { // Multiple needles with size=3, the first one is found
+ int a[] = {0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4};
+ int b[] = {2, 4, 6};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::begin(a) + 4));
+ }
+ { // Single needle with size=4, found at end
+ int a[] = {0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4};
+ int b[] = {2, 4, 6, 8};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::begin(a) + 8));
+ }
+ { // Needle with repeated elements in the prefix
+ int a[] = {0, 1, 1, 1, 1, 2, 3, 0, 1, 2, 3, 4};
+ int b[] = {2, 2, 4};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::begin(a) + 3));
+ }
+ { // Long needle, found at the end
+ int a[] = {0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0};
+ int b[] = {0, 0, 0, 0, 2, 2, 2, 2, 0, 0};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::begin(a) + 6));
+ }
+ { // Needle not found - no match exists
+ int a[] = {0, 1, 2, 3, 4, 5};
+ int b[] = {12};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::end(a)));
+ }
+ { // Needle not found, size=3
+ int a[] = {0, 1, 2, 3, 4, 5};
+ int b[] = {8, 10, 12};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::end(a)));
+ }
+ { // Partial match, fails at last element
+ int a[] = {0, 1, 2, 3, 4, 5, 6};
+ int b[] = {6, 8, 12};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::end(a)));
+ }
+ { // Partial match, fails in middle
+ int a[] = {0, 1, 2, 4, 5};
+ int b[] = {2, 6, 8};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::end(a)));
+ }
+ { // All elements identical in haystack
+ int a[] = {7, 7, 7, 7, 7, 7};
+ int b[] = {14, 14};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::begin(a)));
+ }
+ { // Multiple partial matches before real match
+ int a[] = {1, 2, 1, 2, 1, 2, 3};
+ int b[] = {2, 4, 6};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::begin(a) + 4));
+ }
+ { // Alternating pattern
+ int a[] = {0, 1, 0, 1, 0, 1, 0, 1};
+ int b[] = {2, 0, 2, 0};
+ auto res = std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{});
+ assert(res == Iter1(std::begin(a) + 1));
+ }
+ { // Many elements, needles found at various sampled positions
+ int a[1073];
+ std::fill(std::begin(a), std::end(a), 0);
+ int b[] = {2};
+ int c[] = {2, 0, 0};
+ int d[] = {2, 0, 0, 0, 0};
+ runway_sample(std::size(a) - std::size(d) + 1, [&](std::size_t i) {
+ a[i] = 1;
+ assert(
+ std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{}) ==
+ Iter1(std::begin(a) + i));
+ assert(
+ std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(c)), Iter2(std::end(c)), Pred{}) ==
+ Iter1(std::begin(a) + i));
+ assert(
+ std::search(
+ policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(d)), Iter2(std::end(d)), Pred{}) ==
+ Iter1(std::begin(a) + i));
+ a[i] = 0;
+ });
+ }
+ }
+};
+
+int main(int, char**) {
+ types::for_each(types::forward_iterator_list<int*>{}, types::apply_type_identity{[](auto v) {
+ using Iter = typename decltype(v)::type;
+ types::for_each(
+ types::forward_iterator_list<int*>{},
+ TestIteratorWithPolicies< types::partial_instantiation<Test, Iter>::template apply>{});
+ }});
+ return 0;
+}
diff --git a/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp b/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
index 4998b02fd0650..ef2d4c000dabb 100644
--- a/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
+++ b/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
@@ -355,6 +355,20 @@ int main(int, char**) {
});
}
+ {
+ auto compare = maybe_throw(tokens[5], [](int x, int y) -> bool { return x == y; });
+
+ // search(first1, last1, first2, last2)
+ assert_non_throwing([=, &policy] {
+ (void)std::search(policy, std::move(first1), std::move(last1), std::move(first2), std::move(last2));
+ });
+
+ // search(first1, last1, first2, last2, pred)
+ assert_non_throwing([=, &policy] {
+ (void)std::search(policy, std::move(first1), std::move(last1), std::move(first2), std::move(last2), compare);
+ });
+ }
+
{
auto compare = maybe_throw(tokens[5], [](int x, int y) -> bool { return x < y; });
>From 43782b3df713bd67f4ceae989aae4cdc16c6879c Mon Sep 17 00:00:00 2001
From: Michael Kazakov <mike.kazakov at gmail.com>
Date: Thu, 13 Aug 2026 09:10:18 +0100
Subject: [PATCH 2/2] Updated a few variable names to improve readability
---
.../alg.search/pstl.search.pass.cpp | 32 +++++++++-------
.../alg.search/pstl.search_pred.pass.cpp | 38 +++++++++++--------
2 files changed, 41 insertions(+), 29 deletions(-)
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/pstl.search.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/pstl.search.pass.cpp
index cc4abf51d23c4..5943e1eff12da 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/pstl.search.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/pstl.search.pass.cpp
@@ -230,20 +230,26 @@ struct Test {
{ // Many elements, needles found at various sampled positions
int a[1073];
std::fill(std::begin(a), std::end(a), 0);
- int b[] = {1};
- int c[] = {1, 0, 0};
- int d[] = {1, 0, 0, 0, 0};
- runway_sample(std::size(a) - std::size(d) + 1, [&](std::size_t i) {
+ int needle1[] = {1};
+ int needle2[] = {1, 0, 0};
+ int needle3[] = {1, 0, 0, 0, 0};
+ runway_sample(std::size(a) - std::size(needle3) + 1, [&](std::size_t i) {
a[i] = 1;
- assert(
- std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b))) ==
- Iter1(std::begin(a) + i));
- assert(
- std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(c)), Iter2(std::end(c))) ==
- Iter1(std::begin(a) + i));
- assert(
- std::search(policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(d)), Iter2(std::end(d))) ==
- Iter1(std::begin(a) + i));
+ assert(std::search(policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(needle1)),
+ Iter2(std::end(needle1))) == Iter1(std::begin(a) + i));
+ assert(std::search(policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(needle2)),
+ Iter2(std::end(needle2))) == Iter1(std::begin(a) + i));
+ assert(std::search(policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(needle3)),
+ Iter2(std::end(needle3))) == Iter1(std::begin(a) + i));
a[i] = 0;
});
}
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/pstl.search_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/pstl.search_pred.pass.cpp
index a45c484b8245f..3ff3be5b3c132 100644
--- a/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/pstl.search_pred.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.search/pstl.search_pred.pass.cpp
@@ -235,23 +235,29 @@ struct Test {
{ // Many elements, needles found at various sampled positions
int a[1073];
std::fill(std::begin(a), std::end(a), 0);
- int b[] = {2};
- int c[] = {2, 0, 0};
- int d[] = {2, 0, 0, 0, 0};
- runway_sample(std::size(a) - std::size(d) + 1, [&](std::size_t i) {
+ int needle1[] = {2};
+ int needle2[] = {2, 0, 0};
+ int needle3[] = {2, 0, 0, 0, 0};
+ runway_sample(std::size(a) - std::size(needle3) + 1, [&](std::size_t i) {
a[i] = 1;
- assert(
- std::search(
- policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(b)), Iter2(std::end(b)), Pred{}) ==
- Iter1(std::begin(a) + i));
- assert(
- std::search(
- policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(c)), Iter2(std::end(c)), Pred{}) ==
- Iter1(std::begin(a) + i));
- assert(
- std::search(
- policy, Iter1(std::begin(a)), Iter1(std::end(a)), Iter2(std::begin(d)), Iter2(std::end(d)), Pred{}) ==
- Iter1(std::begin(a) + i));
+ assert(std::search(policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(needle1)),
+ Iter2(std::end(needle1)),
+ Pred{}) == Iter1(std::begin(a) + i));
+ assert(std::search(policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(needle2)),
+ Iter2(std::end(needle2)),
+ Pred{}) == Iter1(std::begin(a) + i));
+ assert(std::search(policy,
+ Iter1(std::begin(a)),
+ Iter1(std::end(a)),
+ Iter2(std::begin(needle3)),
+ Iter2(std::end(needle3)),
+ Pred{}) == Iter1(std::begin(a) + i));
a[i] = 0;
});
}
More information about the libcxx-commits
mailing list