简体   繁体   English

如果我们有 ranges::zip 和 views::transform,为什么我们需要 ranges::zip_transform?

[英]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).在 C++23 中,范围(子)库获得了std::ranges::zip ,它将多个范围压缩为单个范围的std::tuple的(或对)。 This is nice, and precludes requiring implementing this ourselves, using boost::zip_iterator or resorting to this kind of a hack * .这很好,并且不需要我们自己实现它,使用boost::zip_iterator或求助于这种 hack *

However, we also get std::ranges::zip_transform .然而,我们也得到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?毕竟,我们可以将ranges::views::transform应用于压缩范围,不是吗? So, isn't zip_transform redundant?那么, zip_transform不是多余的吗?


* - that hack works well in C++11, and doesn't require tens of thousands of lines of code with concepts... * - 该 hack 在 C++11 中运行良好,并且不需要数万行带有概念的代码...

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.如果在 C++ 中,“函数的有序参数”和“元组”的概念相同或可以轻松互换,那么您是对的。

... 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!区别在于std::ranges::zip_transform了中间人:不是用每个迭代器 advance 构造一个std::tuple并将其传递给转换 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除了@einpoklum 对zip_transform的解释zip_transform ,还值得注意的是zip_transform总是将压缩结果中的每个元素转发到 function。这意味着它不能用作zip | transform 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.第二个将不起作用,因为它必须接收带有 2 个参数的 function。


Sidenote, there are also views::adjacent / views::adjacent_transform , and their pairwise specializations that behaves similar to zip / zip_transform .旁注,还有views::adjacent / views::adjacent_transform ,以及它们的行为类似于zip / zip_transformpairwise特化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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