(that is, without the boilerplate .begin and .end).
Even that is enough to make ranges useful in my mind, but in a codebase which has started to integrate some functional programming techniques, there are also applications for things like views and transforms.
This can make it easier to reason about iteration pipelines in ways you might already be familiar with from POSIX.
That all said, it's C++ so sometimes the error messages get a lot more 'interesting' than they would have with STL-style iterators, especially when mixed with constexpr expressions as you might do with std::format or fmt libs.
`std::accumulate` is defined to have sequential semantics, so the analysis required to make it parallel is probably not that different than starting from the loop version. I guess you could have an alternate `accumulate_associative` that uses the same interface but assumes the reduction is associative and has unspecified evaluation order?
And now you should probably also stop and consider whether adding elements one-by-one as opposed to recursively adding together sums of smaller subarrays has better or worse numerical behaviour in regards to e.g. rounding and stability.
2) the map part is included in the accumulate lambda, so the map part cannot be parallelized either -> you'd have to split it out into a transform step (iirc)
It's been 15 years since I've last touched OpenMP, but the second form is trivially parallelizable as well. Besides, this parallelization can only ever properly work with arrays/vectors or, at the very worst, std::deque as its usually implemented (a vector of fixed-length arrays), not with e.g. linked lists or red-black trees, so why even bother with generic spans and algorithms?