All the views in std::range
library are lazy by design. What it means in practice? It means that under the hood they usually do much more on begin
, end
and iterator operations than regular containers. Usually to be able to maintain this laziness some internal state is required. For example filtred view can store iterator to the last matching element or something along these lines. In this case begin()
changes this internal field. Even the cppreference says this about begin:
Returns the iterator initialized with {*this, ranges::find_if(base_, std::ref(*pred_))}. In order to provide the amortized constant time complexity required by the range concept, this function caches the result within the filter_view object for use on subsequent calls.
So it makes perfect sense - since there CAN (and most probably is) an internal state which begin()
and/or end()
can modify they cannot be made const
.