Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Is const broken with std::views?

void foo(const auto& collection)
{
    *collection.begin() = 104;
}

int main()
{
    std::vector<int> ints {1, 2, 3, 4, 5};
    foo(ints); // Error, as it should be
    foo(ints | std::views::all); // Compiles and modifies the vector. Why?
    return 0;
}

Why is constness of lvalue reference completely ignored if an argument of a function is of type std::view?

Edit:
If, as you wrote in the comments, const view reference is similar to const pointer in this context, why does the code not compile if the same function takes a view constructed from an rvalue object as an argument?

std::vector<int> getVec()
{
    return std::vector{1, 2, 3, 4, 5};
}

void foo(const auto& collection)
{
    *collection.begin() = 104; // Error: assignment of read-only location
}

int main()
{
    foo(getVec() | std::views::all); // Nope!
    return 0;
}

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Views, despite the name, need not be non-modifiable. In general, how a class that represents a sequence of contained objects propagates const depends on what class gets used. And that’s where things get weird.

See, the return type of views::all(e) changes depending on exactly what e is. If e is a glvalue (and is not itself a view), then it returns a ref_view of the range denoted by e. ref_view behaves as if it stores a pointer to the range it is given. Of course, if you have an R* member of a class, the const equivalent of that is R * const, not R const*. So ref_view cannot propagate const to the contained range.

However, if e is a prvalue (and again is not a view), then what all returns is an owning_view. This object actually stores a copy of e (well, it moves from it) as a member. This means that when you get a const owning_view, that const is propagated to that member. And since const vector<T> does propagate const, so too will a views::all(e) of a prvalue of vector.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading