Understanding Views from the Ranges Library
Learn about lazy evaluation with Views in the Ranges Library and its importance in manipulating data.
Lazy evaluation with views in the Ranges library
Views in the Ranges library are lazy evaluated iterations over a range. Technically, they are only iterators with built-in logic, but syntactically, they provide a very pleasant syntax for many common operations.
The following is an example of how to use a view to square each number in a vector (via iteration):
auto numbers = std::vector{1, 2, 3, 4};auto square = [](auto v) { return v * v; };auto squared_view = std::views::transform(numbers, square);for (auto s : squared_view) { // The square lambda is invoked herestd::cout << s << " ";}std::cout << '\n';// Output: 1 4 9 16
The variable squared_view
is not a copy of the numbers vector with the values squared; it is a proxy object for numbers with one slight difference—every time you access an element, the std::transform()
function is invoked. This is why we say that a view is lazy evaluated.
From the outside, you can still iterate over squared_view
in the same way as any regular container and, therefore, you can perform regular algorithms such as find()
or count()
, but, internally, you haven’t created another container.
If you want to store the range, the view can be materialized to a container using std::ranges::copy()
. Once the view has been copied back to a container, there ...