2

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.

Michael
  • 878
  • 5
  • 17

0 Answers0