Reputation: 510
The viewable_range concept specifies the requirements of a range type that can be converted to a view safely.
It's mandatory implementation roughly states that a range
further satisfies viewable_range
if either
std::string_view
, orstd::vector<int>&
, orstd::vector<int>
My questions are:
viewable_range
to constrain universal reference? (i.e. the only chance T
to be deduced to lvalue reference type.) This is the case for standard range adaptor (closure) objects.range
as first parameter in C++23. Is there other usage for viewable_range
concept since then?viewable_range
instead of view
or range
?Upvotes: 5
Views: 803
Reputation: 302748
What idea does this concept capture? Specifically, how could its instance "be converted to a view safely" and why do I want such conversion? What does "safety" even mean here?
Any range can be converted to a view, simply by doing this:
template <input_range R>
auto into_view(R&& r) {
return ref_view(r);
}
But this isn't really a great idea. If we had an rvalue range (whether it's a view or not), now we're taking a reference to it, so this could dangle if we hold onto the resulting view too long.
In general, we don't want to hold onto references to view
s - the point of a view
is that range adaptors hold them by value, not by reference. But also in general, we don't want to hold non-view ranges by value, since those are expensive to copy.
What viewable_range
does is restrict the set of ranges to those where we can covert to a view without added concern for dangling:
view
s should always be by value - so an lvalue view
is only a viewable_range
if it is copyable. An rvalue view
is always a viewable_range
(because view
s have to be movable).view
range is always a viewable_range
because we take a ref_view
in that case. This of course has potential for dangling, but we're taking an lvalue, so it's the safer case.view
range was originally rejected (because our only option was ref_view
and we don't want to refer in this case), but will start to be captured as owning_view
(as of P2415).So basically, the only thing that isn't a viewable range is an lvalue non-copyable view, because of the desire to avoid taking references to views.
Do you always use
viewable_range
to constrainuniversalforwarding reference? (i.e. the only chance T to be deduced to lvalue reference type.) This is the case for standard range adaptor (closure) objects.
No. Only if what you want to do with the forwarding reference is convert it to a view and store the resulting view. Range adaptors do this, but algorithms don't need to - so they shouldn't use that constraint (none of the standard library algorithms do).
Range adaptor (closure) objects are modified to take a range as first parameter in C++23. Is there other usage for viewable_range concept since then?
The term range adaptor closure object is relaxed because now that we can have user-defined range adaptor closure objects (P2387), we can't really enforce what it is that they actually do.
But the standard library range adaptor closure objects still do require viewable_range
(by way of all_t
).
For application development, when to use
viewable_range
instead ofview
orrange
?
This is really the same question as (2). If what you want is to take any range and convert it to a view to be stored, you use viewable_range
- so when you're writing a range adaptor.
Upvotes: 7