[英]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_transform
的pairwise
特化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.