我需要将 unique_ptr
移动到 std::function
闭包。我正在使用 generalized lambda captures在 C++14 中。
auto ptr = make_unique<Foo>();
// Works.
auto lambda = [p = move(ptr)] { };
// This does not compile.
std::function<void()> func = [p = move(ptr)] { };
它试图将 lambda 捕获复制而不是移动到 std::function
中。相关错误是:
copy constructor of '' is implicitly deleted because field '' has a deleted copy
constructor
std::function<void()> func = [p = move(ptr)] { };
例子here会让这看起来有效。
请注意 answer here只是重复 isocpp.org 上的示例。
我可以按如下方式移动到 shared_ptr
:
shared_ptr<Foo> s = move(ptr);
但这会产生另一个问题,因为我需要从我的 lambda 中调用一个需要 unique_ptr
的函数,而且我无法将 shared_ptr
转换回unique_ptr
.
是否可以在 std::function
中捕获 unique_ptr
?
最佳答案
std::function 对象都可以复制
std::function
是类型删除对象,支持复制存储的对象。
当您存储 std::unique_ptr
在 lambda 中,该 lambda 不支持被复制。
所以 std::function
很正确地提示。它是一种可以复制的类型,当传入某些东西时,就会计算出如何复制它。 “我无法复制它”不是一个有效的答案;所有std::function
s可以复制。
工业强度解决方案:
有两种常见的方法可以解决这个问题。首先,您存储 std::function
在 std::shared_ptr
中的状态某种。二、你自己写或者找一个非抄袭的std::function
并改用它。
更“现代”std::function
替换库支持许多有用的东西:
- 函数 View ,不拥有它们包装的内容。
- 只移动函数对象,不支持复制。
- 多重重载函数对象,一次支持超过 1 个签名。
- 固定大小的缓冲区,如果没有足够的自动存储而不是堆分配,则无法编译。
- 简单可复制的函数对象
出于各种特殊目的,我个人需要以上每一种。
然后你会使用moveonly_function<void()>
当您不需要复制可调用对象时,您的代码就会编译。
但是,这对于您现在的需求来说可能太重了。
一个快速的解决方案是:
template<class F>
auto make_shared_function( F&& f ) {
return
[pf = std::make_shared<std::decay_t<F>>(std::forward<F>(f))]
(auto&&...args)->decltype(auto)
{
return (*pf)( decltype(args)(args)... );
};
}
现在每当你遇到这个问题时:
// This does not compile.
std::function<void()> func = make_shared_function([p = move(ptr)] { });
并且可调用对象的状态现在存储在共享指针中。
关于c++ - 如何在 std::function 中捕获 unique_ptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56940199/