假设我们有这样的代码:
std::vector<std::function<void()>> tasks;
我们添加如下任务:
tasks.push_back([]()
{
// ...
}
这有效.但现在我们要添加该任务:
std::unique_ptr<int> v(new int(10));
tasks.push_back([v = std::move(v)]()
{
// ...
}
并且此代码未编译.
为了更清晰:
std::unique_ptr<int> v(new int(10));
std::function<void()> test = [v = std::move(v)]()
{
};
有编译错误.因为lambda的类型不是std :: function< void()>.
但是什么类型的?
最佳答案 没有lambda是std :: function. std :: function是一个类型橡皮擦 – 它采用任何可破坏,可复制和可签名的方式,并删除其余的类型.
由于您的lambda无法复制,因此无法存储在std :: function中.
您可以将其设置为可复制(例如,通过将其状态存储在std :: shared_ptr中),或者编写一个仅移动的std :: function.
#include <utility>
#include <memory>
template<class Sig>class func;
namespace details{
template<class Sig>struct inner;
template<class R,class...Args>
struct inner<R(Args...)>{
virtual ~inner() {};
virtual R invoke(Args&&...args) =0;
};
template<class F,class Sig>struct impl;
template<class F,class R,class...Args>
struct impl<F,R(Args...)>:inner<R(Args...)>{
F f;
template<class... Ts>
impl(Ts&&...ts):f(std::forward<Ts>(ts)...){}
R invoke(Args&&...args)override{
return f(std::forward<Args>(args)...);
}
};
}
template<class T>struct emplace_as{};
template<class R,class...Args>
class func<R(Args...)>{
std::unique_ptr<details::inner<R(Args...)>> pImpl;
public:
R operator()(Args...args){
return pImpl->invoke(std::forward<Args>(args)...);
}
explicit operator bool()const{return pImpl;}
func(func&&)=default;
template<class F,class...Ts,class=typename std::enable_if<
std::is_convertible<decltype(std::declval<F>()(std::declval<Args>()...)),R>::value
>::type>
func(emplace_as<F>,Ts&&...ts):
pImpl( new details::impl<F, R(Args...)>{std::forward<Ts>(ts)...} )
{}
template<class F,class=typename std::enable_if<
std::is_convertible<decltype(std::declval<F>()(std::declval<Args>()...)),R>::value
>::type>
func(F&&f):
func(
emplace_as<typename std::decay<F>::type>(),
std::forward<F>(f)
)
{}
};
(需要添加的功能:对()重载的rvalue引用,可能是swap,也许是赋值和emplace,也许是result_type等的typedef,也许是target和target_type)