Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is a view_closure in range-v3?

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.

like image 617
gonidelis Avatar asked Oct 18 '25 15:10

gonidelis


2 Answers

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 a view. For a range adaptor closure object C and an expression R such that decltype((R)) models viewable_­range, the following expressions are equivalent and yield a view:

C(R)
R | C

Given an additional range adaptor closure object D, the expression C | 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.

like image 53
Barry Avatar answered Oct 21 '25 05:10

Barry


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.

like image 34
Caleth Avatar answered Oct 21 '25 06:10

Caleth