Disclaimers

The library used in the code examples is not really the C++20 ranges, it’s the ranges-v3 open-source library from Eric Niebler, which is the basis of the proposal to add ranges to the C++. It’s a header-only library compatible with C++11/14/17. The code in the article is purely experimental, doesn’t really care about the cleanness and readability.

Functional Programming in C++

Functional Programming (hereinafter FP) is one of the programming paradigms C++ supports. However, compared to other functional-only languages it isn’t very comfortable. Yet, having such a sharp and powerful tool as C++ you’re free to create your own stuff. That’s exactly what ranges-v3 is. The best part of that library is the Unix pipe syntax it provides. That improves the readability, enables us to have less code, thus fewer errors. That’s just one of the pros of the FP: for more in-depth knowledge I highly recommend this book — Functional Programming in C++.

ranges-v3

Before understanding what this library brings to the table, let’s quickly recap what do we have. We have STL, in it containers, algorithms, a decent level of abstraction with iterators that enable the algorithms to work with those containers, and some functors.

The ranges library brings the following:

range — a wrapper to anything like a range, e.g. containers, initializer lists, lazy range-like objects. algorithms — more or less the same set of algorithms that STL provides, just that these work with the ranges. actions — objects that modify the underlying range, like sort. views — lazy objects that behave like ranges or wrap actual ones, like filter.

Before going to the code, let’s dive into the views deeper. They’re significant for being something really new and lazy, thus highly efficient. Consider this pseudocode:

ContainerT container = { ... };

auto widgets = container

| views::filter(...)

| views::transform(...)

| views::take(10);

Imagine a scenario where you have a big container of user objects and you want to

select those meeting a certain criteria create a widget from each user object take the first 10 widgets only

The straightforward way is to simply do all these steps, which might be very inefficient (considering the container is really big and we only need the first 10 of the result). But when we do the same with the views, their laziness makes it very efficient. In the pseudocode above, nothing has happened yet, we’ve just created a view, a combination of other views. It’s something that behaves like a range, i.e. we can iterate over it. Once we start iterating, the action begins:

for (auto widget: widgets) {

/* ... */

}