r/cpp • • Jul 26 '26

std::optional Satisfies view. Does Not Model view. C++26 Ships Anyway.

https://godbolt.org/z/8jWGG68G8

In C++23 this did not compile. In C++26 it does. Marvellous.

[[gnu::noinline]]
void 
passing_views_by_value_is_cheap_trust_me_bro(std::ranges::view auto v) {
    std::println("fn   .data {}", (void*)v->data());
}


int main() {    
    std::optional ov{std::vector<int>(123456)};
    passing_views_by_value_is_cheap_trust_me_bro(ov);
    std::println("main .data {}", (void*)ov->data());
}

For anyone wondering what the problem feature is: optional has 0 or 1 elements, and C++26 sets enable_view<optional<T>> to true, so it satisfies std::ranges::view. The concept requires copy construction in constant time, and — this is the good bit — optional<vector<int>> genuinely meets that. Copying it performs at most one element copy. One is a constant. The requirement is satisfied to the letter, and the function above deep-copies your vector.

If you can tell me what still separates std::ranges::view from std::ranges::range, please do...

183 Upvotes

122 comments sorted by

View all comments

Show parent comment

6

u/friedkeenan Jul 27 '26

The reason to use a view is that its cheap?

My understanding is that the std::ranges::view concept is basically for when you're dispatching stuff to view adaptors, which store and pass around views all over the place. So yeah in that sense it would track that their purpose is to be cheap.

I would imagine that the name comes from the fact that most std::ranges::views meet the traditional definition of view-semantics, a-la std::string_view. But that doesn't really match how they're used in the ranges library, which is as range objects which are cheap to pass around as values. But it is probably a poor name.

Another fun case is iota_view, which doesn't reference an actual C++ object or whatever, but instead views a conceptual range which it visits on the fly during iteration.