C++11 如何为lambda构造std::函数

C++11 如何为lambda构造std::函数,c++11,lambda,std-function,C++11,Lambda,Std Function,我对给定lambda下如何构造std::function感到有点困惑。将列出std::function的构造函数。哪一个是用来捕捉羔羊的?它是模板函数(F)?看起来我无法用捕获非复制可构造对象的lambda构造std::function。为什么这对lambda捕获是必要的 // fu is an object of type std::future std::function f = [future=std::move(fu)]() {...} // compile error // fo

我对给定lambda下如何构造
std::function
感到有点困惑。将列出
std::function
的构造函数。哪一个是用来捕捉羔羊的?它是
模板函数(F)?看起来我无法用捕获非复制可构造对象的lambda构造
std::function
。为什么这对lambda捕获是必要的

// fu is an object of type std::future 
std::function f = [future=std::move(fu)]() {...}  // compile error

// foo is an object of type int
std::function f = [foo=std::move(foo)]() {...} // compile ok

通过值捕获仅移动对象的lambda将变为自身仅移动,这是有意义的,因为它包含所述对象


但是必须是和,这意味着它只能包含可复制的对象。

简单的回答是,标准规定只有可复制的函数对象才能存储在
std::function
中。这并不令人满意:为什么

std::function
是一种可复制类型

该标准规定,复制时,也会复制其内容

“但是”,你说,“我从不复制它。为什么需要复制它?”一个
std::function
的实例记录了如何复制它的内容,即使它从未这样做。它通常使用一种称为类型擦除的技术

以下是一个玩具示例:

struct invoke_later {
  struct i_impl {
    virtual ~i_impl() {}
    virtual void invoke() const = 0;
    virtual std::unique_ptr<i_impl> clone() const = 0;
  };
  template<class T>
  struct impl:i_impl {
    T t;
    ~impl() = default;
    void invoke() const override {
      t();
    }
    impl(T&& tin):t(std::move(tin)) {}
    impl(T const& tin):t(tin) {}
    virtual std::unique_ptr<i_impl> clone() const {
      return std::make_unique<impl>(t);
    };
  };
  std::unique_ptr<i_impl> pimpl;

  template<class T,
    // SFINAE suppress using this ctor instead of copy/move ctors:
    std::enable_if_t< !std::is_same<std::decay_t<T>, invoke_later>{}, int>* =0
  >
  invoke_later( T&& t ):
    pimpl( std::make_unique<impl<std::decay_t<T>>( std::forward<T>(t) ) )
  {}

  invoke_later(invoke_later&&)=default;
  invoke_later(invoke_later const&o):
    pimpl(o.pimpl?o.pimpl->clone():std::unique_ptr<i_impl>{})
  {}

  ~invoke_later() = default;

  // assignment goes here

  void operator() const {
    pimpl->invoke();
  }
  explicit operator bool() const { return !!pimpl; }
};
现在:


类似的问题:特别是对于未来的
s,
.share()
可能更便宜。
template<class F>
auto shared_state( F&& f ) {
  return [pf = std::make_shared<std::decay_t<F>>(std::forward<F>(f))]
    (auto&&... args)->decltype(auto) {
      return (*pf)(decltype(args)(args)...);
    };
}
std::function<Sig> f = shared_state([future=std::move(fu)]() {...});
std::function<void()> f = [fu=fu.share()]{ /* code */ };