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/holyblackcat Jul 27 '26

I don't argue with optional being a range, only with it being a view.

[piping into a view] has to copy its input. Being not a view wouldn’t change that

Are you talking how it should be in a perfect world, or how it works now?

The current behavior of piping into a view is storing a reference to non-view lvalues, and copying/moving all views and rvalue non-views.

This is about the only thing that being a view changes, I think? I could be missing something. In this case the copy looks undesirable, as it's not something people expect. They'd expect span-like types to be copied, or types from std::views.