在两个元组上使用带有 std::apply 的折叠表达式
Using fold expression with std::apply on two tuples
刚开始学习C++17折表达式。我知道可以将折叠表达式应用于元组,如以下示例所示(灵感来自对此 question 的回复):
#include <iostream>
#include <tuple>
int main() {
std::tuple in{1, 2, 3, 4};
std::cout << "in = ";
std::apply([](auto&&... x) { ((std::cout << x << ' '), ...); }, in);
std::cout << std::endl;
std::multiplies<int> op;
auto out = std::apply([&](auto&& ...x) { return std::tuple{op(x, 3)...}; }, in);
std::cout << "out = ";
std::apply([](auto&&... x) { ((std::cout << x << ' '), ...); }, out);
std::cout << std::endl;
}
输出:
in = 1 2 3 4
out = 3 6 9 12
是否可以使用类似的方法将两个元组压缩在一起?参考上面的示例,我想用另一个元组替换常量 3,例如 std::apply:
的假设版本
auto out = std::apply([&](auto&& ...x, auto&& ...y) { return std::tuple{op(x, y)...}; }, inX, inY);
如果折叠表达式不适用于此目的,是否有其他方法可以在 C++20 中实现相同的结果(除了模板递归 and/oriSFINAE)?
你可以apply
两次:
auto out = std::apply([&](auto&&... x){
return std::apply([&](auto&&... y){
return std::make_tuple(op(x, y)...);
}, inY);
}, inX);
或者您可以使用索引序列,在 C++20 中更容易,因为我们有更通用的 lambda 语法,但仍然相当密集:
auto out = [&]<size_t... Is>(std::index_sequence<Is...>){
return std::make_tuple(op(std::get<Is>(inX), std::get<Is>(inY))...);
}(std::make_index_sequence<std::tuple_size_v<decltype(inX)>>());
可能值得添加一个帮手,例如...
auto indices_for = []<typename... Ts>(std::tuple<Ts...> const&){
return = []<size_t... Is>(std::index_sequence<Is...>){
return [](auto f) -> decltype(auto) {
return f(std::integral_constant<size_t, Is>()...);
};
}(std::index_sequence_for<Ts...>());
};
也就是说,indices_for(t)
给你一个函数,它接受一个函数并用一堆整数常量调用它。这是一团糟,但是您必须一次编写并且可以轻松测试。这让你写:
auto out = indices_for(inX)([&](auto... Is){
return std::make_tuple(op(std::get<Is>(inX), std::get<Is>(inY))...);
});
类似的东西。
刚开始学习C++17折表达式。我知道可以将折叠表达式应用于元组,如以下示例所示(灵感来自对此 question 的回复):
#include <iostream>
#include <tuple>
int main() {
std::tuple in{1, 2, 3, 4};
std::cout << "in = ";
std::apply([](auto&&... x) { ((std::cout << x << ' '), ...); }, in);
std::cout << std::endl;
std::multiplies<int> op;
auto out = std::apply([&](auto&& ...x) { return std::tuple{op(x, 3)...}; }, in);
std::cout << "out = ";
std::apply([](auto&&... x) { ((std::cout << x << ' '), ...); }, out);
std::cout << std::endl;
}
输出:
in = 1 2 3 4
out = 3 6 9 12
是否可以使用类似的方法将两个元组压缩在一起?参考上面的示例,我想用另一个元组替换常量 3,例如 std::apply:
的假设版本auto out = std::apply([&](auto&& ...x, auto&& ...y) { return std::tuple{op(x, y)...}; }, inX, inY);
如果折叠表达式不适用于此目的,是否有其他方法可以在 C++20 中实现相同的结果(除了模板递归 and/oriSFINAE)?
你可以apply
两次:
auto out = std::apply([&](auto&&... x){
return std::apply([&](auto&&... y){
return std::make_tuple(op(x, y)...);
}, inY);
}, inX);
或者您可以使用索引序列,在 C++20 中更容易,因为我们有更通用的 lambda 语法,但仍然相当密集:
auto out = [&]<size_t... Is>(std::index_sequence<Is...>){
return std::make_tuple(op(std::get<Is>(inX), std::get<Is>(inY))...);
}(std::make_index_sequence<std::tuple_size_v<decltype(inX)>>());
可能值得添加一个帮手,例如...
auto indices_for = []<typename... Ts>(std::tuple<Ts...> const&){
return = []<size_t... Is>(std::index_sequence<Is...>){
return [](auto f) -> decltype(auto) {
return f(std::integral_constant<size_t, Is>()...);
};
}(std::index_sequence_for<Ts...>());
};
也就是说,indices_for(t)
给你一个函数,它接受一个函数并用一堆整数常量调用它。这是一团糟,但是您必须一次编写并且可以轻松测试。这让你写:
auto out = indices_for(inX)([&](auto... Is){
return std::make_tuple(op(std::get<Is>(inX), std::get<Is>(inY))...);
});
类似的东西。