[libcxx-commits] [libcxx] [libc++] Optimize std::for_each_n for segmented iterators (PR #135468)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Wed May 14 09:33:52 PDT 2025


================
@@ -10,32 +10,88 @@
 #ifndef _LIBCPP___ALGORITHM_FOR_EACH_N_H
 #define _LIBCPP___ALGORITHM_FOR_EACH_N_H
 
+#include <__algorithm/for_each.h>
+#include <__algorithm/for_each_n_segment.h>
 #include <__config>
+#include <__iterator/iterator_traits.h>
+#include <__iterator/segmented_iterator.h>
+#include <__type_traits/enable_if.h>
 #include <__utility/convert_to_integral.h>
+#include <__utility/move.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
 #endif
 
-_LIBCPP_BEGIN_NAMESPACE_STD
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
 
-#if _LIBCPP_STD_VER >= 17
+_LIBCPP_BEGIN_NAMESPACE_STD
 
-template <class _InputIterator, class _Size, class _Function>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
-for_each_n(_InputIterator __first, _Size __orig_n, _Function __f) {
+template <class _InputIterator,
+          class _Size,
+          class _Func,
+          __enable_if_t<!__has_random_access_iterator_category<_InputIterator>::value &&
+                            (!__is_segmented_iterator<_InputIterator>::value
+                             //   || !__has_random_access_iterator_category<
+                             //      typename __segmented_iterator_traits<_InputIterator>::__local_iterator>::value
+                             ), // TODO: __segmented_iterator_traits<_InputIterator> results in template instantiation
+                                // during SFINAE, which is a hard error to be fixed. Once fixed, we should uncomment.
+                        int> = 0>
----------------
ldionne wrote:

Instead, I would suggest this:

```
template <class _SegmentedIterator>
struct __has_random_access_local_iterator
  : __has_random_access_iterator_category<
    typename __segmented_iterator_traits< _SegmentedIterator >::__local_iterator
  >
{ };

// Then, use:
 __enable_if_t<
  !__has_random_access_iterator_category<_InputIterator>::value &&
  _Or<
    _Not<__is_segmented_iterator<_InputIterator> >,
    _Not<__has_random_access_local_iterator<_InputIterator> >
  >::value
>
```

The difference here is that `_Or` is performing lazy evaluation of its operands, so `__has_random_access_local_iterator` never gets instantiated if we don't have a segmented iterator.

IMO this also removes the need for https://github.com/llvm/llvm-project/pull/134304.

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


More information about the libcxx-commits mailing list