[libcxx-commits] [libcxx] [libc++][pstl] Implementation of a parallel std::adjacent_find() based on std::mismatch() (PR #210604)

via libcxx-commits libcxx-commits at lists.llvm.org
Wed Jul 29 08:07:09 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Michael G. Kazakov (mikekazakov)

<details>
<summary>Changes</summary>

This PR implements a parallel `std::adjacent_find()` based on parallel `std::mismatch`.
The implementation reshapes the input range as two ranges offset by 1 element and asks `std::mismatch` to find the first equal pair:
```c++
// Find the first match within two overlapping ranges,
// expressed as a double negation of the predicate:
//   [first, __last - 1)
//   [first + 1, __last)
auto res = Mismatch()(policy, first, last2, first2, last,
    [&](auto &lhs, auto& rhs) { return !predicate(lhs, rhs); });
```

Included tests check that:
- Semantics of the iterator-only version is correct.
- Semantics of the predicated version is correct.
- The functions correctly SFINAE out when the first argument is not an execution policy.
- The `noexcept` policy is followed.
- The `nodiscard` policy is followed.
- `static_assert` verifies iterators' categories.

Part of #<!-- -->99938.

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


8 Files Affected:

- (modified) libcxx/include/__algorithm/pstl.h (+25) 
- (modified) libcxx/include/__pstl/backend_fwd.h (+7) 
- (modified) libcxx/include/__pstl/backends/default.h (+45) 
- (modified) libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp (+6) 
- (modified) libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp (+4) 
- (added) libcxx/test/std/algorithms/alg.nonmodifying/alg.adjacent.find/pstl.adjacent_find.pass.cpp (+126) 
- (added) libcxx/test/std/algorithms/alg.nonmodifying/alg.adjacent.find/pstl.adjacent_find_pred.pass.cpp (+134) 
- (modified) libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp (+12) 


``````````diff
diff --git a/libcxx/include/__algorithm/pstl.h b/libcxx/include/__algorithm/pstl.h
index bc48fd9f48d7f..0447691c3b86b 100644
--- a/libcxx/include/__algorithm/pstl.h
+++ b/libcxx/include/__algorithm/pstl.h
@@ -228,6 +228,31 @@ template <class _ExecutionPolicy,
       equal_to{});
 }
 
+template <class _ExecutionPolicy,
+          class _ForwardIterator,
+          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
+          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _ForwardIterator
+adjacent_find(_ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last) {
+  _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "adjacent_find requires ForwardIterators");
+  using _Implementation = __pstl::__dispatch<__pstl::__adjacent_find, __pstl::__current_configuration, _RawPolicy>;
+  return __pstl::__handle_exception<_Implementation>(
+      std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), equal_to{});
+}
+
+template <class _ExecutionPolicy,
+          class _ForwardIterator,
+          class _BinaryPredicate,
+          class _RawPolicy                                    = __remove_cvref_t<_ExecutionPolicy>,
+          enable_if_t<is_execution_policy_v<_RawPolicy>, int> = 0>
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI _ForwardIterator adjacent_find(
+    _ExecutionPolicy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __predicate) {
+  _LIBCPP_REQUIRE_CPP17_FORWARD_ITERATOR(_ForwardIterator, "adjacent_find requires ForwardIterators");
+  using _Implementation = __pstl::__dispatch<__pstl::__adjacent_find, __pstl::__current_configuration, _RawPolicy>;
+  return __pstl::__handle_exception<_Implementation>(
+      std::forward<_ExecutionPolicy>(__policy), std::move(__first), std::move(__last), std::move(__predicate));
+}
+
 template <class _ExecutionPolicy,
           class _ForwardIterator1,
           class _ForwardIterator2,
diff --git a/libcxx/include/__pstl/backend_fwd.h b/libcxx/include/__pstl/backend_fwd.h
index ecd1f0b9b4049..3c835426ec377 100644
--- a/libcxx/include/__pstl/backend_fwd.h
+++ b/libcxx/include/__pstl/backend_fwd.h
@@ -339,6 +339,13 @@ struct __mismatch_3leg;
 // operator()(_Policy&& __policy, _ForwardIterator1 __first1, _ForwardIterator1 __last1,
 //                                _ForwardIterator2 __first2, _Comp __comp) const noexcept;
 
+template <class _Backend, class _ExecutionPolicy>
+struct __adjacent_find;
+// template <class _Policy, class _ForwardIterator, class _BinaryPredicate>
+// optional<_ForwardIterator>
+// operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last,
+//                                _BinaryPredicate __predicate) 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 776c76f3fdfbd..05700daaf3e84 100644
--- a/libcxx/include/__pstl/backends/default.h
+++ b/libcxx/include/__pstl/backends/default.h
@@ -9,6 +9,7 @@
 #ifndef _LIBCPP___PSTL_BACKENDS_DEFAULT_H
 #define _LIBCPP___PSTL_BACKENDS_DEFAULT_H
 
+#include <__algorithm/adjacent_find.h>
 #include <__algorithm/copy_n.h>
 #include <__algorithm/equal.h>
 #include <__algorithm/fill_n.h>
@@ -24,6 +25,7 @@
 #include <__iterator/concepts.h>
 #include <__iterator/iterator_traits.h>
 #include <__iterator/next.h>
+#include <__iterator/prev.h>
 #include <__iterator/reverse_iterator.h>
 #include <__pstl/backend_fwd.h>
 #include <__pstl/dispatch.h>
@@ -66,6 +68,7 @@ namespace __pstl {
 //
 // mismatch family
 // ---------------
+// - adjacent_find
 // - mismatch_3leg
 //
 // for_each family
@@ -249,6 +252,48 @@ struct __mismatch_3leg<__default_backend_tag, _ExecutionPolicy> {
   }
 };
 
+template <class _ExecutionPolicy>
+struct __adjacent_find<__default_backend_tag, _ExecutionPolicy> {
+  template <class _Policy, class _ForwardIterator, class _BinaryPredicate>
+  optional<_ForwardIterator>
+  operator()(_Policy&& __policy, _ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __predicate)
+      const noexcept {
+    if constexpr (__has_bidirectional_iterator_category<_ForwardIterator>::value) {
+      using _Mismatch = __dispatch<__mismatch, __current_configuration, _ExecutionPolicy>;
+      if (__first == __last) {
+        return __last; // Empty range, return __last.
+      }
+      _ForwardIterator __first2 = std::next(__first);
+      if (__first2 == __last) {
+        return __last; // Single element range, no adjacent elements, return __last.
+      }
+      _ForwardIterator __last2 = std::prev(__last);
+      // Find the first match within two overlapping ranges, expressed as a double negation of the predicate:
+      //   [first, __last - 1)
+      //   [first + 1, __last)
+      auto __res = _Mismatch()(
+          __policy,
+          std::move(__first),
+          std::move(__last2),
+          std::move(__first2),
+          __last,
+          [&](__iterator_reference<_ForwardIterator> __lhs, __iterator_reference<_ForwardIterator> __rhs) {
+            return !__predicate(__lhs, __rhs);
+          });
+      if (!__res) {
+        return nullopt; // Failed to run the algorithm, propagate the error.
+      }
+      if (__res->second == __last) {
+        return __last; // No adjacent elements found, return __last.
+      }
+      return __res->first; // Return the first iterator of the pair of mismatched elements.
+    } else {
+      // Currently anything outside bidirectional iterators has to be processed serially
+      return std::adjacent_find(std::move(__first), std::move(__last), std::move(__predicate));
+    }
+  }
+};
+
 //////////////////////////////////////////////////////////////
 // for_each family
 //////////////////////////////////////////////////////////////
diff --git a/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp b/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
index df11341008bc5..640109ac131fb 100644
--- a/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
+++ b/libcxx/test/libcxx/algorithms/pstl.iterator-requirements.verify.cpp
@@ -151,6 +151,12 @@ void f(non_forward_iterator non_fwd,
         pol, it, it, non_fwd, non_fwd, pred); // expected-error@*:* {{static assertion failed: mismatch}}
   }
 
+  {
+    (void)std::adjacent_find(pol, non_fwd, non_fwd); // expected-error@*:* {{static assertion failed: adjacent_find}}
+    (void)std::adjacent_find(
+        pol, non_fwd, non_fwd, pred); // expected-error@*:* {{static assertion failed: adjacent_find}}
+  }
+
   {
     (void)std::move(pol, non_fwd, non_fwd, out); // expected-error@*:* {{static assertion failed: move}}
     (void)std::move(pol, it, it, non_fwd);       // expected-error@*:* {{static assertion failed: move}}
diff --git a/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp b/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp
index f5eaf1642b687..352f00f1c9baf 100644
--- a/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/algorithms/pstl.nodiscard.verify.cpp
@@ -71,4 +71,8 @@ void test() {
   std::mismatch(std::execution::par, std::begin(a), std::end(a), std::begin(b), pred2);
   // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
   std::mismatch(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::adjacent_find(std::execution::par, std::begin(a), std::end(a));
+  // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+  std::adjacent_find(std::execution::par, std::begin(a), std::end(a), pred2);
 }
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.adjacent.find/pstl.adjacent_find.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.adjacent.find/pstl.adjacent_find.pass.cpp
new file mode 100644
index 0000000000000..db78d29da73d0
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.adjacent.find/pstl.adjacent_find.pass.cpp
@@ -0,0 +1,126 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// template<class ExecutionPolicy, class ForwardIterator>
+// ForwardIterator adjacent_find(ExecutionPolicy&& exec,
+//                               ForwardIterator first, ForwardIterator last);
+
+#include <algorithm>
+#include <cassert>
+#include <iterator>
+#include <numeric>
+#include <limits>
+
+#include "test_execution_policies.h"
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "type_algorithms.h"
+#include "runway_sample.h"
+
+// The type X is provided to test that the adjacent_find algorithm can be used with custom non-movable/non-copyable types.
+struct X {
+  X() = delete;
+  explicit X(int i) : i_(i) {}
+  X(const X&)            = delete;
+  X(X&&)                 = delete;
+  X& operator=(const X&) = delete;
+  X& operator=(X&&)      = delete;
+  bool operator==(const X& other) const { return i_ == other.i_; }
+
+private:
+  int i_;
+};
+
+template <class Iter>
+struct Test {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    { // Check the result type of the algorithm
+      int a[]  = {42};
+      auto res = std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::begin(a)));
+      static_assert(std::is_same_v<decltype(res), Iter>);
+    }
+    { // Empty range
+      int a[] = {42};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::begin(a))) == Iter(std::begin(a)));
+    }
+    { // Single element range
+      int a[] = {42};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a))) == Iter(std::end(a)));
+    }
+    { // Two equal elements
+      int a[] = {42, 42};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a))) == Iter(std::begin(a)));
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::begin(a) + 1)) == Iter(std::begin(a) + 1));
+      assert(std::adjacent_find(policy, Iter(std::begin(a) + 1), Iter(std::end(a))) == Iter(std::end(a)));
+    }
+    { // Three elements, all equal
+      int a[] = {0, 0, 0};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a))) == Iter(std::begin(a)));
+    }
+    { // Three elements, no equal pairs
+      int a[] = {0, 1, 0};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a))) == Iter(std::end(a)));
+    }
+    { // Four elements, one equal pair
+      int a[] = {0, 1, 0, 0};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a))) == Iter(std::begin(a) + 2));
+    }
+    { // Four elements, no equal pairs
+      int a[] = {0, 1, 0, 1};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a))) == Iter(std::end(a)));
+    }
+    { // Four elements, two equal pairs
+      int a[] = {0, 1, 1, 1};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a))) == Iter(std::begin(a) + 1));
+    }
+    { // Eight elements, one equal pair
+      int a[] = {0, 1, 2, 2, 0, 1, 2, 3};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a))) == Iter(std::begin(a) + 2));
+      assert(std::adjacent_find(policy, Iter(std::begin(a) + 2), Iter(std::end(a))) == Iter(std::begin(a) + 2));
+      assert(std::adjacent_find(policy, Iter(std::begin(a) + 3), Iter(std::end(a))) == Iter(std::end(a)));
+    }
+    { // Eight elements, no equal pairs
+      int a[] = {0, 1, 2, 7, 0, 1, 2, 3};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a))) == Iter(std::end(a)));
+    }
+    { // 1073 iotaed elements, look for equal pair at different sample positions
+      int a[1073];
+      std::iota(std::begin(a), std::end(a), 0);
+      runway_sample(std::size(a), [&](std::size_t i) {
+        if (i == 0)
+          return; // skip the first element to avoid out-of-bounds access
+        a[i] = a[i - 1];
+        assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a))) == Iter(std::begin(a) + i - 1));
+        a[i] = i;
+      });
+    }
+  }
+};
+
+template <class Iter>
+struct TestX {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    // Four elements, one equal pair
+    X a[] = {X(0), X(1), X(1), X(2)};
+    assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a))) == Iter(std::begin(a) + 1));
+    assert(std::adjacent_find(policy, Iter(std::begin(a) + 1), Iter(std::end(a))) == Iter(std::begin(a) + 1));
+    assert(std::adjacent_find(policy, Iter(std::begin(a) + 2), Iter(std::end(a))) == Iter(std::end(a)));
+  }
+};
+
+int main(int, char**) {
+  types::for_each(types::forward_iterator_list<const int*>{}, TestIteratorWithPolicies<Test>{});
+  types::for_each(types::forward_iterator_list<const X*>{}, TestIteratorWithPolicies<TestX>{});
+  return 0;
+}
diff --git a/libcxx/test/std/algorithms/alg.nonmodifying/alg.adjacent.find/pstl.adjacent_find_pred.pass.cpp b/libcxx/test/std/algorithms/alg.nonmodifying/alg.adjacent.find/pstl.adjacent_find_pred.pass.cpp
new file mode 100644
index 0000000000000..792e4f75dc17f
--- /dev/null
+++ b/libcxx/test/std/algorithms/alg.nonmodifying/alg.adjacent.find/pstl.adjacent_find_pred.pass.cpp
@@ -0,0 +1,134 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// template<class ExecutionPolicy, class ForwardIterator, class BinaryPredicate>
+// ForwardIterator adjacent_find(ExecutionPolicy&& exec,
+//                               ForwardIterator first, ForwardIterator last,
+//                               BinaryPredicate pred);
+
+#include <algorithm>
+#include <cassert>
+#include <numeric>
+#include <iterator>
+#include <limits>
+
+#include "test_execution_policies.h"
+#include "test_macros.h"
+#include "test_iterators.h"
+#include "type_algorithms.h"
+#include "runway_sample.h"
+
+// The type X is provided to test that the adjacent_find algorithm can be used with custom non-movable/non-copyable types.
+struct X {
+  X() = delete;
+  explicit X(int i) : i_(i) {}
+  X(const X&)            = delete;
+  X(X&&)                 = delete;
+  X& operator=(const X&) = delete;
+  X& operator=(X&&)      = delete;
+  int get_value() const { return i_; }
+
+private:
+  int i_;
+};
+
+struct Pred {
+  bool operator()(const X& a, const X& b) const { return b.get_value() - a.get_value() == 42; }
+  bool operator()(int a, int b) const { return b - a == 42; }
+};
+
+template <class Iter>
+struct Test {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    { // Check the result type of the algorithm
+      int a[]  = {42};
+      auto res = std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::begin(a)), Pred{});
+      static_assert(std::is_same_v<decltype(res), Iter>);
+    }
+    { // Empty range
+      int a[] = {42};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::begin(a)), Pred{}) == Iter(std::begin(a)));
+    }
+    { // Single element range
+      int a[] = {42};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a)), Pred{}) == Iter(std::end(a)));
+    }
+    { // Two equal elements
+      int a[] = {42, 84};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a)), Pred{}) == Iter(std::begin(a)));
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::begin(a) + 1), Pred{}) ==
+             Iter(std::begin(a) + 1));
+      assert(std::adjacent_find(policy, Iter(std::begin(a) + 1), Iter(std::end(a)), Pred{}) == Iter(std::end(a)));
+    }
+    { // Three elements, all equal
+      int a[] = {0, 42, 84};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a)), Pred{}) == Iter(std::begin(a)));
+    }
+    { // Three elements, no equal pairs
+      int a[] = {0, 41, 0};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a)), Pred{}) == Iter(std::end(a)));
+    }
+    { // Four elements, one equal pair
+      int a[] = {0, 1, 0, 42};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a)), Pred{}) == Iter(std::begin(a) + 2));
+    }
+    { // Four elements, no equal pairs
+      int a[] = {0, 41, 0, 41};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a)), Pred{}) == Iter(std::end(a)));
+    }
+    { // Four elements, two equal pairs
+      int a[] = {0, 1, 43, 85};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a)), Pred{}) == Iter(std::begin(a) + 1));
+    }
+    { // Eight elements, one equal pair
+      int a[] = {0, 1, 2, 44, 0, 1, 2, 3};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a)), Pred{}) == Iter(std::begin(a) + 2));
+      assert(std::adjacent_find(policy, Iter(std::begin(a) + 2), Iter(std::end(a)), Pred{}) == Iter(std::begin(a) + 2));
+      assert(std::adjacent_find(policy, Iter(std::begin(a) + 3), Iter(std::end(a)), Pred{}) == Iter(std::end(a)));
+    }
+    { // Eight elements, no equal pairs
+      int a[] = {0, 1, 2, 45, 0, 1, 2, 3};
+      assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a)), Pred{}) == Iter(std::end(a)));
+    }
+    { // 1073 iotaed elements, look for equal pair at different sample positions
+      int a[1073];
+      std::iota(std::begin(a), std::end(a), 0);
+      runway_sample(std::size(a), [&](std::size_t i) {
+        if (i == 0)
+          return; // skip the first element to avoid out-of-bounds access
+        a[i] = a[i - 1] + 42;
+        assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a)), Pred{}) ==
+               Iter(std::begin(a) + i - 1));
+        a[i] = i;
+      });
+    }
+  }
+};
+
+template <class Iter>
+struct TestX {
+  template <class ExecutionPolicy>
+  void operator()(ExecutionPolicy&& policy) {
+    // Four elements, one equal pair
+    X a[] = {X(0), X(40), X(82), X(100)};
+    assert(std::adjacent_find(policy, Iter(std::begin(a)), Iter(std::end(a)), Pred{}) == Iter(std::begin(a) + 1));
+    assert(std::adjacent_find(policy, Iter(std::begin(a) + 1), Iter(std::end(a)), Pred{}) == Iter(std::begin(a) + 1));
+    assert(std::adjacent_find(policy, Iter(std::begin(a) + 2), Iter(std::end(a)), Pred{}) == Iter(std::end(a)));
+  }
+};
+
+int main(int, char**) {
+  types::for_each(types::forward_iterator_list<const int*>{}, TestIteratorWithPolicies<Test>{});
+  types::for_each(types::forward_iterator_list<const X*>{}, TestIteratorWithPolicies<TestX>{});
+  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 cbdb4663f168c..e3e76bc3692d3 100644
--- a/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
+++ b/libcxx/test/std/algorithms/pstl.exception_handling.pass.cpp
@@ -273,6 +273,18 @@ int main(int, char**) {
         });
       }
 
+      {
+        auto pred = maybe_throw(tokens[5], [](int x, int y) -> bool { return x == y; });
+
+        // adjacent_find(first, last)
+        assert_non_throwing([=, &policy] { (void)std::adjacent_find(policy, std::move(first1), std::move(last1)); });
+
+        // adjacent_find(first, last, pred)
+        assert_non_throwing([=, &policy] {
+          (void)std::adjacent_find(policy, std::move(first1), std::move(last1), pred);
+        });
+      }
+
       {
         // move(first, last, dest)
         assert_non_throwing([=, &policy] {

``````````

</details>


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


More information about the libcxx-commits mailing list