[libcxx-commits] [libcxx] [WIP][libc++] Implement find_first_of in terms of find_if or find (PR #207276)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Jul 2 13:48:50 PDT 2026
https://github.com/ldionne created https://github.com/llvm/llvm-project/pull/207276
This allows taking advantage of optimizations in find_if and find in that algorithm.
Closes #129319
>From b636d2308702c846194c588d4040e0c0635fbd1d Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 2 Jul 2026 16:47:46 -0400
Subject: [PATCH] [WIP][libc++] Implement find_first_of in terms of find_if or
find
This allows taking advantage of optimizations in find_if and find
in that algorithm.
Closes #129319
---
libcxx/include/__algorithm/find_first_of.h | 36 +++++++++++++++----
.../__algorithm/ranges_find_first_of.h | 1 +
2 files changed, 31 insertions(+), 6 deletions(-)
diff --git a/libcxx/include/__algorithm/find_first_of.h b/libcxx/include/__algorithm/find_first_of.h
index 45ec133154371..c6f4bdb0874a0 100644
--- a/libcxx/include/__algorithm/find_first_of.h
+++ b/libcxx/include/__algorithm/find_first_of.h
@@ -11,7 +11,11 @@
#define _LIBCPP___ALGORITHM_FIND_FIRST_OF_H
#include <__algorithm/comp.h>
+#include <__algorithm/find.h>
+#include <__algorithm/find_if.h>
#include <__config>
+#include <__iterator/iterator_traits.h>
+#include <__type_traits/desugars_to.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -20,16 +24,36 @@
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredicate>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 __find_first_of_ce(
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator1 __find_first_of(
_ForwardIterator1 __first1,
_ForwardIterator1 __last1,
_ForwardIterator2 __first2,
_ForwardIterator2 __last2,
_BinaryPredicate&& __pred) {
- for (; __first1 != __last1; ++__first1)
- for (_ForwardIterator2 __j = __first2; __j != __last2; ++__j)
- if (__pred(*__first1, *__j))
+ for (; __first1 != __last1; ++__first1) {
+#ifndef _LIBCPP_CXX03_LANG
+
+ using _Ref1 = typename iterator_traits<_ForwardIterator1>::reference;
+ using _Ref2 = typename iterator_traits<_ForwardIterator2>::reference;
+
+ if constexpr (__desugars_to<__equal_tag, _BinaryPredicate, _Ref1, _Ref2>) {
+ _ForwardIterator2 __found = std::find(__first2, __last2, *__first1);
+ if (__found != __last2)
return __first1;
+ } else {
+ _ForwardIterator2 __found = std::find_if(__first2, __last2, [&](auto&& __x) { return __pred(*__first1, __x); });
+ if (__found != __last2)
+ return __first1;
+ }
+
+#else
+
+ _ForwardIterator2 __found = std::find_if(__first2, __last2, [&](auto&& __x) { return __pred(*__first1, __x); });
+ if (__found != __last2)
+ return __first1;
+
+#endif
+ }
return __last1;
}
@@ -40,13 +64,13 @@ template <class _ForwardIterator1, class _ForwardIterator2, class _BinaryPredica
_ForwardIterator2 __first2,
_ForwardIterator2 __last2,
_BinaryPredicate __pred) {
- return std::__find_first_of_ce(__first1, __last1, __first2, __last2, __pred);
+ return std::__find_first_of(__first1, __last1, __first2, __last2, __pred);
}
template <class _ForwardIterator1, class _ForwardIterator2>
[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _ForwardIterator1 find_first_of(
_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2) {
- return std::__find_first_of_ce(__first1, __last1, __first2, __last2, __equal_to());
+ return std::__find_first_of(__first1, __last1, __first2, __last2, __equal_to());
}
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__algorithm/ranges_find_first_of.h b/libcxx/include/__algorithm/ranges_find_first_of.h
index 102e16dd7a55b..62e4fbbff6738 100644
--- a/libcxx/include/__algorithm/ranges_find_first_of.h
+++ b/libcxx/include/__algorithm/ranges_find_first_of.h
@@ -42,6 +42,7 @@ struct __find_first_of {
_Pred& __pred,
_Proj1& __proj1,
_Proj2& __proj2) {
+ // TODO: also implement this via __find_first_of (requires projection support?)
for (; __first1 != __last1; ++__first1) {
for (auto __j = __first2; __j != __last2; ++__j) {
if (std::invoke(__pred, std::invoke(__proj1, *__first1), std::invoke(__proj2, *__j)))
More information about the libcxx-commits
mailing list