Search code examples
c++filterstd-ranges

Cannot iterate over const view


I have written the following code:

int main()
{
    const std::vector v {1,2,3};
    const auto squared=v|std::ranges::views::filter(
        [](auto i){
            return i%2==0;
        }) | std::ranges::views::transform(
            [](auto i){
                return i*i;
            }
        );
    for (const auto s:squared){
        std::cout << s<<std::endl;
    }
}

(see https://godbolt.org/z/3345s3Yv5).

However, it does not compile since the iteration apparently discards qualifiers. Sure enough, making squared non-const allows it to build successfully. In addition, removing the filter also fixes the issue.

I want to understand why this is the case:

  1. why does it need to be non-const? I imagine begin is a non-const function, but why? I feel it should be permitted to look over the elements of the range so long as I do not edit them
  2. why does removing the filter fix this? I don't understand how it is different to the transform

Solution

  • Filter views are not const iterable when the underlying view models forward_range.

    From cppreference

    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.