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

via libcxx-commits libcxx-commits at lists.llvm.org
Tue Feb 3 04:52:17 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libcxx

Author: Connector Switch (c8ef)

<details>
<summary>Changes</summary>

This is necessary when optimizing algorithms for segmented iterators to reduce boilerplate code.

related:
- https://github.com/llvm/llvm-project/pull/177853#discussion_r2754820322
- https://github.com/llvm/llvm-project/pull/164266#discussion_r2447129525

We also change the `__func` to `__f` here for better consistency with other for_each code names.

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


3 Files Affected:

- (modified) libcxx/include/__algorithm/for_each.h (+10-4) 
- (modified) libcxx/include/__algorithm/for_each_n.h (+3-2) 
- (modified) libcxx/include/__algorithm/generate_n.h (+5-2) 


``````````diff
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>

``````````

</details>


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


More information about the libcxx-commits mailing list