【发布时间】:2015-12-05 20:09:45
【问题描述】:
This answer 解释了如何在 C++14 中移动捕获 lambda 中的变量。
但是,一旦您在 lambda 中移动捕获了一个不可复制的对象(例如 std::unique_ptr),您就无法复制 lambda 本身。
如果您可以移动 lambda,这会很好,但尝试这样做时会出现编译错误:
using namespace std;
class HasCallback
{
public:
void setCallback(std::function<void(void)>&& f)
{
callback = move(f);
}
std::function<void(void)> callback;
};
int main()
{
auto uniq = make_unique<std::string>("Blah blah blah");
HasCallback hc;
hc.setCallback(
[uniq = move(uniq)](void)
{
std::cout << *uniq << std::endl;
});
hc.callback();
}
这会产生以下g++ 错误(我试图仅复制相关行):
error: use of deleted function ‘main()::<lambda()>::<lambda>(const main()::<lambda()>&’
...我认为,这意味着我移动 lambda 的尝试失败了。
clang++ 给出了类似的错误。
我尝试明确地moveing lambda(即使它是一个临时值),但这并没有帮助。
编辑: 下面的答案充分解决了上述代码产生的编译错误。对于另一种方法,只需将唯一指针的目标值release 转换为std::shared_ptr,可以复制。 (我不是在写这个作为答案,因为那会假设这是一个 XY 问题,但是 unique_ptr 不能在转换为 std::function 的 lambda 中使用的根本原因很重要理解.)
编辑 2: 有趣的是,据我所知,我刚刚意识到 auto_ptr 实际上会在这里做正确的事情(!)。它的行为本质上类似于unique_ptr,但允许复制构造代替移动构造。
【问题讨论】:
-
我认为 setCallback 应该通过值而不是右值引用来获取参数,我错了吗?
-
@Slava 这就是我最初拥有的,但它给出了同样的错误。我认为采用右值引用将允许(/强制)移动构造 lambda,但情况似乎并非如此。