矢量

2014-10-11 78 views
4

假设我们有这样的代码:矢量

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)]() 
{ 
}; 

有编译错误。因为拉姆达的类型不是std::function<void()>。 但是什么类型?

+2

一个lambda具有“不可告人”独特类型由编译器生成。你的问题是'std :: function'要求它的函数对象是'CopyConstructible','unique_ptr'不能被复制。 – 2014-10-11 22:16:04

+0

但在例子中'lambda'是一个右值引用,它调用移动的构造函数。不是吗? – herolover 2014-10-11 22:22:33

+1

没关系。 'std :: function'对于'CopyConstructible'使用的函数对象有很强的要求,而你的lambda不是因为它捕获了'unique_ptr'。故事结局。 – 2014-10-11 22:25:25

回答

2

否lambda是std::functionstd::function是一种类型的橡皮擦 - 它采用任何可破坏,可复制和可调用的签名,并擦除其余类型。

由于您的拉姆达无法复制,因此无法将其存储在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) 
    ) 
    {} 
}; 

something like that

(需要添加特点:右值参照该重载上(),也许swap,也许assignemplace,也许类型定义为result_type等),也许targettarget_type