将所有参数移至 lambda
Move all arguments to lambda
我想创建接受任意数量参数的 lambda,例如:
template <typename... Args>
void f(Args... args) {
auto l = [args...]() {
g(args...);
}
// use l
}
这里的问题是它不适用于只能移动的类型。如果它只有 1 个参数,我会像
void f(Arg arg) {
auto l = [arg = std::move(arg)]() {
g(move(arg));
}
}
如何将所有参数移动到 lambda?
template <class... Args>
void f(Args... args) {
auto l = [tup=std::make_tuple(std::move(args)...)] {
std::apply([](auto&&...args){
g(decltype(args)(args)...);
}, tup );
};
}
有点恶心。
将它们打包成一个元组,然后用 std::apply
解包元组。如果你缺少 std::apply
给自己写一个等价的。
如果你想用右值调用 g
,使外部 lambda 可变,并将 move
元组放入内部 lambda。
内部 lambda 可以默认捕获 &
如果你想访问外部或类似的参数。
我们甚至可以稍微抽象一下这个模式:
template<class F, class...Args>
auto forward_capture( F&& f, Args&&...args ) {
return [
f=std::forward<F>(f),
tup=std::make_tuple(std::forward<Args>(args)...)
]{
return std::apply( f, tup );
};
}
使用:
template <typename... Args>
void f(Args... args) {
auto l = forward_capture(
[](auto&&...args) {
g(args...);
},
std::move(args)...
);
// use l
}
如果您想先获取捕获列表,我们可以做到:
template<class...Args>
auto forward_capture( Args&&...args ) {
return [
tup=std::make_tuple(std::forward<Args>(args)...)
](auto&& f)mutable{
return [
f=decltype(f)(f),
tup=std::move(tup)
]{
return std::apply( f, tup );
};
};
}
使用:
template <typename... Args>
void f(Args... args) {
auto l = forward_capture(std::move(args)...)(
[](auto&&...args) {
g(args...);
}
);
// use l
}
其中 "advantage" 我们有 3 个嵌套的 lambda。
或者更好玩:
template<class...Args>
struct arrow_star {
std::tuple<Args...> args;
template<class F>
auto operator->*(F&& f)&& {
return [f=std::forward<F>(f),args=std::move(args)]()mutable{
return std::experimental::apply( std::move(f), std::move(args) );
};
}
};
template<class...Args>
arrow_star<std::decay_t<Args>...> forward_capture( Args&&...args ) {
return {std::make_tuple(std::forward<Args>(args)...)};
}
template<class...Args>
auto f(Args... args)
{
return
forward_capture( std::move(args)... )
->*
[](auto&&...args){
g(decltype(args)(args)...);
};
}
我想创建接受任意数量参数的 lambda,例如:
template <typename... Args>
void f(Args... args) {
auto l = [args...]() {
g(args...);
}
// use l
}
这里的问题是它不适用于只能移动的类型。如果它只有 1 个参数,我会像
void f(Arg arg) {
auto l = [arg = std::move(arg)]() {
g(move(arg));
}
}
如何将所有参数移动到 lambda?
template <class... Args>
void f(Args... args) {
auto l = [tup=std::make_tuple(std::move(args)...)] {
std::apply([](auto&&...args){
g(decltype(args)(args)...);
}, tup );
};
}
有点恶心。
将它们打包成一个元组,然后用 std::apply
解包元组。如果你缺少 std::apply
给自己写一个等价的。
如果你想用右值调用 g
,使外部 lambda 可变,并将 move
元组放入内部 lambda。
内部 lambda 可以默认捕获 &
如果你想访问外部或类似的参数。
我们甚至可以稍微抽象一下这个模式:
template<class F, class...Args>
auto forward_capture( F&& f, Args&&...args ) {
return [
f=std::forward<F>(f),
tup=std::make_tuple(std::forward<Args>(args)...)
]{
return std::apply( f, tup );
};
}
使用:
template <typename... Args>
void f(Args... args) {
auto l = forward_capture(
[](auto&&...args) {
g(args...);
},
std::move(args)...
);
// use l
}
如果您想先获取捕获列表,我们可以做到:
template<class...Args>
auto forward_capture( Args&&...args ) {
return [
tup=std::make_tuple(std::forward<Args>(args)...)
](auto&& f)mutable{
return [
f=decltype(f)(f),
tup=std::move(tup)
]{
return std::apply( f, tup );
};
};
}
使用:
template <typename... Args>
void f(Args... args) {
auto l = forward_capture(std::move(args)...)(
[](auto&&...args) {
g(args...);
}
);
// use l
}
其中 "advantage" 我们有 3 个嵌套的 lambda。
或者更好玩:
template<class...Args>
struct arrow_star {
std::tuple<Args...> args;
template<class F>
auto operator->*(F&& f)&& {
return [f=std::forward<F>(f),args=std::move(args)]()mutable{
return std::experimental::apply( std::move(f), std::move(args) );
};
}
};
template<class...Args>
arrow_star<std::decay_t<Args>...> forward_capture( Args&&...args ) {
return {std::make_tuple(std::forward<Args>(args)...)};
}
template<class...Args>
auto f(Args... args)
{
return
forward_capture( std::move(args)... )
->*
[](auto&&...args){
g(decltype(args)(args)...);
};
}