[libcxx-commits] [libcxx] [libc++] Optimize ranges::{for_each, for_each_n} for segmented iterators (PR #132896)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Thu Mar 27 06:40:46 PDT 2025


================

----------------
ldionne wrote:

For `std::for_each_n`, is there a reason you don't simply do the following?

```c++
template <class _InputIterator,
           class _Size,
           class _Function,
           __enable_if_t<!__is_random_access_iterator<_InputIterator>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _InputIterator
for_each_n(_InputIterator __first, _Size __orig_n, _Function __f) {
  // existing loop with counter
}

template <class _RandomAccessIterator,
          class _Size,
          class _Function,
          __enable_if_t<__is_random_access_iterator<_RandomAccessIterator>::value, int> = 0>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator
for_each_n(_RandomAccessIterator __first, _Size __orig_n, _Function __f) {
  typedef decltype(std::__convert_to_integral(__orig_n)) _IntegralSize;
  _IntegralSize __n     = __orig_n;
  return std::for_each(__first, __first + __n, std::move(__f));
}
```

That way we dispatch to `std::for_each` in more cases, which covers the segmented iterator optimization you're introducing now but also potentially future optimizations.

Note that this formulation does mean that we lose the optimization for a non random-access segmented sequence, like `join_view`. However, today this optimization is happening at the cost of an additional traversal of the whole sequence, which is not clear to me is worth it. If you have a benchmark on a `join_view`, I'd be curious to see it.

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


More information about the libcxx-commits mailing list