在C ++ 14中,广义lambda捕获让我们做:
template<class T>
auto pack(T t)
{
return [t=std::move(t)](auto&& f){f(t);};
};
但它没有玩param-pack:
template<class... T>
auto pack(T... t)
{
return [t=std::move(t)...](auto&& f){f(t...);};
};
是否有任何特殊语法或进一步的标准提案可以解决这个问题?
答案 0 :(得分:18)
我的C ++ 14草案说([expr.prim.lambda] / 24):
simple-capture 后跟省略号是包扩展(14.5.3)。 init-capture 后跟省略号格式不正确。
所以看起来没有办法进行可变广义捕获。一种可能的解决方法是仅捕获元组中的参数,然后使用此处建议的解决方案之一:"unpacking" a tuple to call a matching function pointer
auto pack(T... t)
{
return [args=make_tuple(std::move(t)...)](auto&& f){
// find a way to call f with args
};
};
修改强>
它现在被投票到C ++ 20,由proposal制作。虽然语法有点不同:
template<class... T>
auto pack(T... t)
{
return [...t=std::move(t)](auto&& f){f(t...);};
};
请注意...
在init-capture之前。
答案 1 :(得分:3)
作为后续行动,我来到了这个解决方法:
template<class T>
struct mover
{
mover(T const& val) : val(val) {}
mover(T&& val) : val(std::move(val)) {}
mover(mover const& other) = default;
mover(mover&& other) = default;
mover(mover& other) : val(std::move(other.val)) {}
operator T const&() const
{
return val;
}
T val;
};
template<class T>
using wrap_t = typename std::conditional
<
std::is_move_constructible<T>::value
&& !std::is_trivially_copy_constructible<T>::value
, mover<T>
, T
>::type;
template<class... Ts>
auto pack_impl(wrap_t<Ts>... ts)
{
return [=](auto&& f)->decltype(auto)
{
return f(static_cast<Ts const&>(ts)...);
};
}
auto pack = [](auto&&... ts)
{
return pack_impl<std::decay_t<decltype(ts)>...>(static_cast<decltype(ts)>(ts)...);
};
它利用mover
作为代理,允许lambda通过移动捕获它(它有点hacky)。 wrap_t
决定何时需要或有益于mover
。
现在我们可以测试一下:
struct A
{
A() = default;
A(A&&)
{
std::cout << "move\n";
}
A(A const&)
{
std::cout << "copy\n";
}
};
A a;
std::cout <<"p1------------\n";
auto p1 = pack(std::move(a));
std::cout <<"p2------------\n";
auto p2 = std::move(p1);
std::cout <<"p3------------\n";
auto p3 = p2;
将打印:
p1------------
move
move
p2------------
move
p3------------
copy
答案 2 :(得分:3)
这扩展了我对上面Brian回答的评论。在带有库基础知识TS的C ++ 14中,您可以:
CREATE TRIGGER [TriggerName]
ON [Scope (Server|Database)]
FOR [EventName...],
AS
-- code for your trigger response here
假设您希望通过移动一般性地捕获参数包并在lambda中使用它,您可以在lambda中的lambda中编写代码,然后在其上应用参数:
template<class... T>
auto pack(T... t)
{
return [ts = std::make_tuple(std::move(t)...)](auto&& f){
std::experimental::apply(f, ts);
};
};