I am very new to using ranges in C++. I am using gcc 12.1 with the c++23 standard. As a toy example, I would like to use piping to print the indices of all even values contained in some vector. First we define some useful lambdas...
auto square_number = [idx=int{0}]() mutable { ++idx; return idx*idx; };
auto make_pair = [idx=int{0}](int e) mutable { return pair<int,int> {++idx, e};};
auto has_even_value = [](const pair<int,int>& p){ return p.second % 2 == 0; };
Then we create some numbers, use a range::views::transform
to create the pairs of indices and values, and then explicitly store those pairs in a new vector.
namespace srv = std::ranges::views;
vector<int> squares(20);
generate(squares.begin(), squares.end(), square_number);
auto pair_view = squares | srv::transform(make_pair);
auto all_pairs = vector<pair<int,int>> {pair_view.begin(), pair_view.end()};
Next we create a filter view to generate even squares and print the result.
auto even_pair_view = all_pairs | srv::filter(has_even_value);
for(const auto& p : even_pair_view) cout << p.first << " - " << p.second << endl;
As expected we get the (index - value) pairs 2 - 4
up to 20 - 400
. Great.
However, if I try to pipe the transform and the filter directly, without first storing all_pairs
, like so
auto even_pair_view = squares
| srv::transform(make_pair)
| srv::filter(has_even_value);
the same printing as before gives me 3 - 4
, 6 - 16
up to 30 - 400
. So apparently, the ++idx
in my make_pair
lambda is applied multiple times.
I do not understand, where exactly that index is increased, and therefore I also don't know how to solve this problem using range views and piping. All help would be highly appreciated.