[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:47 PDT 2025
================
@@ -40,11 +43,18 @@ struct __for_each_n {
template <input_iterator _Iter, class _Proj = identity, indirectly_unary_invocable<projected<_Iter, _Proj>> _Func>
_LIBCPP_HIDE_FROM_ABI constexpr for_each_n_result<_Iter, _Func>
operator()(_Iter __first, iter_difference_t<_Iter> __count, _Func __func, _Proj __proj = {}) const {
- while (__count-- > 0) {
- std::invoke(__func, std::invoke(__proj, *__first));
- ++__first;
+ if constexpr (forward_iterator<_Iter>) {
+ auto __last = std::ranges::next(__first, __count);
----------------
ldionne wrote:
This is bad if we have a non random-access iterator. For example for a linked list, we have `forward_iterator`s but we'd end up walking the list once to get the `__last`, and then we'd walk it again inside `__for_each`. Did that not show up in the benchmarks? I'd be curious to understand why.
Instead I think what you want here is:
```
if constexpr (random_access_iterator<_Iter>) {
std::__for_each(__first, __first + __count, __func, __proj);
} else {
// the loop
}
```
https://github.com/llvm/llvm-project/pull/132896
More information about the libcxx-commits
mailing list