[libcxx-commits] [libcxx] [libcxx] Modify `std::__for_each{, _n}` to accept r-values in `__f` (PR #179451)

Connector Switch via libcxx-commits libcxx-commits at lists.llvm.org
Tue Feb 3 05:09:37 PST 2026


https://github.com/c8ef updated https://github.com/llvm/llvm-project/pull/179451

>From 0fe2c5063b39ba19a5f39a813ac7dbfea06bfa00 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Tue, 3 Feb 2026 20:32:50 +0800
Subject: [PATCH 1/2] make func accept rval

---
 libcxx/include/__algorithm/for_each.h   | 14 ++++++++++----
 libcxx/include/__algorithm/for_each_n.h |  5 +++--
 libcxx/include/__algorithm/generate_n.h |  7 +++++--
 3 files changed, 18 insertions(+), 8 deletions(-)

diff --git a/libcxx/include/__algorithm/for_each.h b/libcxx/include/__algorithm/for_each.h
index 85fedce3d936d..f46a4d70687e2 100644
--- a/libcxx/include/__algorithm/for_each.h
+++ b/libcxx/include/__algorithm/for_each.h
@@ -17,32 +17,36 @@
 #include <__iterator/segmented_iterator.h>
 #include <__type_traits/invoke.h>
 #include <__type_traits/is_same.h>
+#include <__utility/forward.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
 #endif
 
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _InputIterator, class _Sent, class _Func, class _Proj>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
-__for_each(_InputIterator __first, _Sent __last, _Func& __func, _Proj& __proj) {
+__for_each(_InputIterator __first, _Sent __last, _Func&& __f, _Proj& __proj) {
 #ifndef _LIBCPP_CXX03_LANG
   if constexpr (using _SpecialAlg =
                     __specialized_algorithm<_Algorithm::__for_each, __iterator_pair<_InputIterator, _Sent>>;
                 _SpecialAlg::__has_algorithm) {
-    _SpecialAlg()(__first, __last, __func, __proj);
+    _SpecialAlg()(__first, __last, std::forward<_Func>(__f), __proj);
     return __last;
   } else if constexpr (is_same<_InputIterator, _Sent>::value && __is_segmented_iterator_v<_InputIterator>) {
     using __local_iterator_t = typename __segmented_iterator_traits<_InputIterator>::__local_iterator;
     std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
-      std::__for_each(__lfirst, __llast, __func, __proj);
+      std::__for_each(__lfirst, __llast, __f, __proj);
     });
     return __last;
   }
 #endif
   for (; __first != __last; ++__first)
-    std::__invoke(__func, std::__invoke(__proj, *__first));
+    std::__invoke(__f, std::__invoke(__proj, *__first));
   return __first;
 }
 
@@ -56,4 +60,6 @@ for_each(_InputIterator __first, _InputIterator __last, _Func __f) {
 
 _LIBCPP_END_NAMESPACE_STD
 
+_LIBCPP_POP_MACROS
+
 #endif // _LIBCPP___ALGORITHM_FOR_EACH_H
diff --git a/libcxx/include/__algorithm/for_each_n.h b/libcxx/include/__algorithm/for_each_n.h
index 72c7adb093f95..7ff3f9b157c02 100644
--- a/libcxx/include/__algorithm/for_each_n.h
+++ b/libcxx/include/__algorithm/for_each_n.h
@@ -18,6 +18,7 @@
 #include <__iterator/segmented_iterator.h>
 #include <__type_traits/invoke.h>
 #include <__utility/convert_to_integral.h>
+#include <__utility/forward.h>
 #include <__utility/move.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
@@ -31,7 +32,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _InputIterator, class _Size, class _Func, class _Proj>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
-__for_each_n(_InputIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj) {
+__for_each_n(_InputIterator __first, _Size __orig_n, _Func&& __f, _Proj& __proj) {
   typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize;
   _IntegralSize __n = __orig_n;
 
@@ -43,7 +44,7 @@ __for_each_n(_InputIterator __first, _Size __orig_n, _Func& __f, _Proj& __proj)
         std::__for_each(__lfirst, __llast, __f, __proj);
       });
     } else {
-      return std::__for_each(__first, __first + __n, __f, __proj);
+      return std::__for_each(__first, __first + __n, std::forward<_Func>(__f), __proj);
     }
   } else
 #endif
diff --git a/libcxx/include/__algorithm/generate_n.h b/libcxx/include/__algorithm/generate_n.h
index 23899e49e0b65..ba04eb62e3c3a 100644
--- a/libcxx/include/__algorithm/generate_n.h
+++ b/libcxx/include/__algorithm/generate_n.h
@@ -29,8 +29,11 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
 __generate_n(_OutputIterator __first, _Size __orig_n, _Generator& __gen) {
   using __iter_ref = decltype(*__first);
   __identity __proj;
-  auto __f = [&](__iter_ref __element) { std::forward<__iter_ref>(__element) = __gen(); };
-  return std::__for_each_n(std::move(__first), __orig_n, __f, __proj);
+  return std::__for_each_n(
+      std::move(__first),
+      __orig_n,
+      [&](__iter_ref __element) { std::forward<__iter_ref>(__element) = __gen(); },
+      __proj);
 }
 
 template <class _OutputIterator, class _Size, class _Generator>

>From f2f48734159925124781eb0af891a97894e5b0e2 Mon Sep 17 00:00:00 2001
From: c8ef <c8ef at outlook.com>
Date: Tue, 3 Feb 2026 21:09:22 +0800
Subject: [PATCH 2/2] restore func; remove a forward

---
 libcxx/include/__algorithm/for_each.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libcxx/include/__algorithm/for_each.h b/libcxx/include/__algorithm/for_each.h
index f46a4d70687e2..77eb4cfbcdd4e 100644
--- a/libcxx/include/__algorithm/for_each.h
+++ b/libcxx/include/__algorithm/for_each.h
@@ -30,23 +30,23 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _InputIterator, class _Sent, class _Func, class _Proj>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
-__for_each(_InputIterator __first, _Sent __last, _Func&& __f, _Proj& __proj) {
+__for_each(_InputIterator __first, _Sent __last, _Func&& __func, _Proj& __proj) {
 #ifndef _LIBCPP_CXX03_LANG
   if constexpr (using _SpecialAlg =
                     __specialized_algorithm<_Algorithm::__for_each, __iterator_pair<_InputIterator, _Sent>>;
                 _SpecialAlg::__has_algorithm) {
-    _SpecialAlg()(__first, __last, std::forward<_Func>(__f), __proj);
+    _SpecialAlg()(__first, __last, __func, __proj);
     return __last;
   } else if constexpr (is_same<_InputIterator, _Sent>::value && __is_segmented_iterator_v<_InputIterator>) {
     using __local_iterator_t = typename __segmented_iterator_traits<_InputIterator>::__local_iterator;
     std::__for_each_segment(__first, __last, [&](__local_iterator_t __lfirst, __local_iterator_t __llast) {
-      std::__for_each(__lfirst, __llast, __f, __proj);
+      std::__for_each(__lfirst, __llast, __func, __proj);
     });
     return __last;
   }
 #endif
   for (; __first != __last; ++__first)
-    std::__invoke(__f, std::__invoke(__proj, *__first));
+    std::__invoke(__func, std::__invoke(__proj, *__first));
   return __first;
 }
 



More information about the libcxx-commits mailing list