In a case like this:
auto pow = [](int i) {return i * i; };
auto closure = ranges::views::transform(pow);
closure
seems to be a view_closure
. I do get that last line does not make much sense, since transform is not applied anywhere. Actually, I could may as well pipe a vector x
into closure
and it would both compile and work properly.
But, what is a view closure? Is it a "function like" object that expects to be applied somewhere? What are its semantics?
I found this from Eric Niebler's range-v3
source code but there aren't any docs specifying it elsewhere.
I don't even get whether view_closure
is intended for internal usage or for the users' end.
The view_closure
class template in range-v3 that is an implementation strategy for what in C++20 became the range adaptor closure object concept:
A range adaptor closure object is a unary function object that accepts a
viewable_range
argument and returns aview
. For a range adaptor closure objectC
and an expressionR
such thatdecltype((R))
modelsviewable_range
, the following expressions are equivalent and yield a view:C(R) R | C
Given an additional range adaptor closure object
D
, the expressionC | D
is well-formed and produces another range adaptor closure object such that the following two expressions are equivalent:R | C | D R | (C | D)
The result of transform(f)
is a range adaptor closure object, which you can apply to a viewable_range
either via pipe as r | transform(f)
or via call as transform(f)(r)
, either of which will give you some kind of transform_view
adaptor.
More broadly, transform
itself is a range adaptor object which is defined in a way such that transform(f)
gives you a range adaptor closure object such that transform(r, f)
, r | transform(f)
, and transform(f)(r)
are all equivalent.
view_closure
, the class template, is necessary to ensure that stuff like this works:
auto adaptor = transform(f) | filter(g) | chunks(n);
That is, you can build up a pipeline without having a range, and the result of that is a range adaptor closure object that you can then apply to a range - r | adaptor
would be equivalent to r | transform(f) | filter(g) | chunks(n)
which is equivalent to chunks(filter(transform(r, f), g), n)
.
That class template basically affects what operator|
does, among other things. You only need to use it if you're creating your own range adaptor, it's not something you need to care about as a user of ranges otherwise.
view_closure
is not a type, it is a template. The exact type of that expression is an instantiation of that template with an unnamed closure type (i.e. decltype(pow)
). It is an implementation detail.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With