884 karma · joined July 20, 2014
Home: stl@nuwen.net
Work: stl@microsoft.com (I work for Microsoft, but I don't speak for them.)
(It's easier to recognize a straight line on a log scale, than to distinguish an exponential line on a linear scale from a line that's "merely" quadratic, say.)
Nope.
> would intuitively expect it to be the POLS behavior.
If you give me (the implementation) a modifiable range, and I invisibly add constness before giving you back an element, that's surprising. C++ doesn't add constness by default anywhere (with the novel exception of lambda function call operators). If you give me a modifiable range, the least surprising thing to do is to give you a modifiable element, because that's what all of ptr[idx], * ptr, and * iter would do.
> how realistic (from the impl. POV) would be to have value-semantic range-based `for` with _mandated_ copy elision whenever possible?
If you say "for (auto elem : range) { elem = stuff; }" the write to the elem-copy will be dropped on the floor. Copy elision can't solve that.
> it doesn't say that `it` _itself_ has to be immutable (right?)
Correct.
> How do you think about InputIterators?
The concept is single-pass, read-only, but a given iterator may be stronger. for_each() is kind of special (it's the only algorithm that takes InputIterators, yet allows stronger iterators to be used with modifying functors), but other algorithms are vaguely similar. For example, transform(InIt first, InIt last, OutIt result, UnOp op) permits transform(first, last, first, op) for an in-place transformation - here, first/last's type clearly has to be InIt and OutIt simultaneously, i.e. a mutable FwdIt iterator or stronger.
for_each() does not add constness, and can modify elements in-place. The fact that it is grouped with the "non-modifying algorithms" is a confusing historical artifact (and was actually the subject of the first Library Issue I had a part in filing) - the algorithm itself does not modify things (unlike sort(), say) but the given functor can.
Note that nothing's wrong with "const auto& elem", except that it prohibits modification. On the other hand, "const auto&& elem" will typically not compile (it'll insist on binding to rvalues, which only proxy iterators return).