> did it offer a `mutable` opt-in, though?
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.