简体   繁体   中英

If we have ranges::zip and views::transform, why do we need ranges::zip_transform?

In C++23, the ranges (sub)library has gained std::ranges::zip , which zips multiple ranges into a single range of std::tuple 's (or pairs). This is nice, and precludes requiring implementing this ourselves, using boost::zip_iterator or resorting to this kind of a hack * .

However, we also get std::ranges::zip_transform . Why do we need it? After all, we can apply a ranges::views::transform to a zipped range, can't we? So, isn't zip_transform redundant?


* - that hack works well in C++11, and doesn't require tens of thousands of lines of code with concepts...

If, in C++, the concepts of "the ordered parameters of a function" and "a tuple" were identical or easily interchangeable, then you would be right.

... unfortunately, that is not the case. The difference is that std::ranges::zip_transform cuts out the middle-man: Instead of constructing an std::tuple with each iterator advance and passing it to the transform function, references to the range elements themselves are passed to the function!

So, instead of writing something like:

auto add = [](std::tuple t) { 
    return std::get<0>(t) + std::get<1>(t) + std::get<2>(t); 
};
auto elementwise_sum = 
    std::views::zip(v1, v2, v3) | std::views::transform(add);

we can write, instead:

auto add = [](auto a, auto b, auto c) { return a + b + c; };
auto elementwise_sum = std::views::zip_transform(add, v1, v2, v3);

which I'm sure you'll agree is nicer.

In addition to what @einpoklum has explained about zip_transform , it is also worth noting that zip_transform will always forward each elements in a zipped result to the function. Which means it cannot be used as a drop-in replacement for zip | transform zip | transform :

std::vector<int> v1, v2;
auto func = [](std::tuple<int, int> t){ return double{}; };

views::zip(v1, v2) | views::transform(func); // ok

// views::zip_transform(func, v1, v2); // this will not work

The second one will not work because it must receive a function that takes 2 parameters.


Sidenote, there are also views::adjacent / views::adjacent_transform , and their pairwise specializations that behaves similar to zip / zip_transform .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM