Lambda 链的完美转发
Perfect Forwarding for Lambda Chaining
我想 chain/compose 多个 lambda 到一个新的 lambda。当使用参数调用新的 lambda 时,它应该使用这些参数调用原始的 lambda。这个 lambda 链接在刚刚复制参数时工作得很好,但是当我想修改它们时 完美转发 不起作用:
#include <boost/hana.hpp>
#include <cassert>
constexpr auto chain_lambdas = [](auto... lambdas) {
constexpr auto lambdasTpl = boost::hana::make_basic_tuple(lambdas...);
return [lambdas(lambdasTpl)](auto&&... args) {
auto argsTpl = boost::hana::make_basic_tuple(std::forward<decltype(args)>(args)...);
boost::hana::for_each(lambdas, [args(argsTpl)](auto lambda) mutable {
boost::hana::unpack(std::move(args), [lambda(lambda)](auto&&... args) {
lambda(std::forward<decltype(args)>(args)...);
});
});
};
};
auto main() -> int
{
auto lambda1 = [](bool& called){
called = true;
};
auto lambda2 = [](bool& called){
called = true;
};
bool called = false;
chain_lambdas(lambda1, lambda2)(called);
assert(called == true);
return 0;
}
compiler explorer 处的代码。完美转发是否适用于此用例?
auto argsTpl = boost::hana::make_basic_tuple(std::forward<decltype(args)>(args)...);
复制(移动)参数,因此您只需改变副本。
你需要 std::forward_as_tuple
等值的提升:
constexpr auto chain_lambdas = [](auto... lambdas) {
constexpr auto lambdasTpl = boost::hana::make_basic_tuple(lambdas...);
return [lambdas(lambdasTpl)](auto&&... args) {
auto argsTpl = boost::hana::basic_tuple<decltype(args)...>(std::forward<decltype(args)>(args)...);
boost::hana::for_each(lambdas, [args(argsTpl)](auto lambda) mutable {
boost::hana::unpack(args, [lambda(lambda)](auto&&... args) {
lambda(std::forward<decltype(args)>(args)...);
});
});
};
};
在我这边,只有 std (C++17),你可能会这样做:
constexpr auto chain_lambdas = [](auto... lambdas) {
return [=](auto&&... args) {
return std::apply([&](auto... f){ (f(args...), ...); }, std::tie(lambdas...));
};
};
Demo.
我为 args
删除了 std::forward
,因为使用移动的对象调用函数可能不受欢迎,但如果需要,您可以启用它。
我想 chain/compose 多个 lambda 到一个新的 lambda。当使用参数调用新的 lambda 时,它应该使用这些参数调用原始的 lambda。这个 lambda 链接在刚刚复制参数时工作得很好,但是当我想修改它们时 完美转发 不起作用:
#include <boost/hana.hpp>
#include <cassert>
constexpr auto chain_lambdas = [](auto... lambdas) {
constexpr auto lambdasTpl = boost::hana::make_basic_tuple(lambdas...);
return [lambdas(lambdasTpl)](auto&&... args) {
auto argsTpl = boost::hana::make_basic_tuple(std::forward<decltype(args)>(args)...);
boost::hana::for_each(lambdas, [args(argsTpl)](auto lambda) mutable {
boost::hana::unpack(std::move(args), [lambda(lambda)](auto&&... args) {
lambda(std::forward<decltype(args)>(args)...);
});
});
};
};
auto main() -> int
{
auto lambda1 = [](bool& called){
called = true;
};
auto lambda2 = [](bool& called){
called = true;
};
bool called = false;
chain_lambdas(lambda1, lambda2)(called);
assert(called == true);
return 0;
}
compiler explorer 处的代码。完美转发是否适用于此用例?
auto argsTpl = boost::hana::make_basic_tuple(std::forward<decltype(args)>(args)...);
复制(移动)参数,因此您只需改变副本。
你需要 std::forward_as_tuple
等值的提升:
constexpr auto chain_lambdas = [](auto... lambdas) {
constexpr auto lambdasTpl = boost::hana::make_basic_tuple(lambdas...);
return [lambdas(lambdasTpl)](auto&&... args) {
auto argsTpl = boost::hana::basic_tuple<decltype(args)...>(std::forward<decltype(args)>(args)...);
boost::hana::for_each(lambdas, [args(argsTpl)](auto lambda) mutable {
boost::hana::unpack(args, [lambda(lambda)](auto&&... args) {
lambda(std::forward<decltype(args)>(args)...);
});
});
};
};
在我这边,只有 std (C++17),你可能会这样做:
constexpr auto chain_lambdas = [](auto... lambdas) {
return [=](auto&&... args) {
return std::apply([&](auto... f){ (f(args...), ...); }, std::tie(lambdas...));
};
};
Demo.
我为 args
删除了 std::forward
,因为使用移动的对象调用函数可能不受欢迎,但如果需要,您可以启用它。