这个答案解释了如何在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的尝试失败了。
CCD_ 3给出了类似的错误。
我尝试过显式地对lambda进行move
处理(尽管它是一个临时值(,但没有帮助。
编辑:下面的答案充分解决了由上述代码产生的编译错误。对于另一种方法,只需将唯一指针的目标值release
复制到std::shared_ptr
中,可以复制。(我写这篇文章不是为了回答问题,因为这会假设这是一个XY问题,但理解unique_ptr
不能用于转换为std::function
的lambda的根本原因很重要。(
第2版:有趣的是,据我所知,我刚刚意识到auto_ptr
实际上会在这里做正确的事情(!(。它的作用本质上类似于unique_ptr
,但允许复制构造来代替移动构造。
您可以移动lambda,这很好。但这并不是您的问题所在,您正试图用不可压缩的lambda实例化std::function
。以及:
template< class F >
function( F f );
function
的构造函数:
5( 使用
f
的副本初始化目标。
这是因为std::function
:
满足CopyConstructable和CopyAssignable的要求。
由于function
必须是可复制的,所以您放入其中的所有内容也必须是可拷贝的。只移动lambda不满足这个要求。
std::function
不是lambda!它是一个包装器,可以由任何类型的可调用函数(包括lambda(构造。std::function
要求可调用的是可复制构造的,这就是您的示例失败的原因。
只能移动的lambda可以再次移动,如下所示。
template<typename F>
void call(F&& f)
{
auto f1 = std::forward<F>(f); // construct a local copy
f1();
}
int main()
{
auto uniq = make_unique<std::string>("Blah blah blah");
auto lambda = [uniq = move(uniq)]() {
std::cout << *uniq << std::endl;
};
// call(lambda); // doesn't compile because the lambda cannot be copied
call(std::move(lambda));
}
实时演示