[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
Wed Feb 4 04:24:18 PST 2026


================
@@ -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);
----------------
c8ef wrote:

```cpp
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) {
  typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize;
  _IntegralSize __n = __orig_n;

#ifndef _LIBCPP_CXX03_LANG
  if constexpr (__is_segmented_iterator_v<_InputIterator>) {
    using __local_iterator = typename __segmented_iterator_traits<_InputIterator>::__local_iterator;
    if constexpr (__has_random_access_iterator_category<__local_iterator>::value) {
      return std::__for_each_n_segment(__first, __orig_n, [&](__local_iterator __lfirst, __local_iterator __llast) {
        std::__for_each(__lfirst, __llast, __f, __proj);
      });
    } else {
      return std::__for_each(__first, __first + __n, __f, __proj);
    }
  } else
#endif
  {
    while (__n > 0) {
      std::__invoke(__f, std::__invoke(__proj, *__first));
      ++__first;
      --__n;
    }
    return std::move(__first);
  }
}
```

`generate_n` calls `__for_each_n`. In the outer it appears to only branch based on whether segmented iterators or not, so I believe set/map will not be affected, too?

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


More information about the libcxx-commits mailing list