移动lambda:一旦你移动捕获了一个只移动的类型,lambda如何被使用?

Kyl*_*and 19 c++ lambda move c++14

这个答案解释了如何在C++ 14中移动捕获lambda中的变量.

但是,一旦你std::unique_ptr在lambda中移动捕获了一个不可复制的对象(例如a ),就无法复制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();
}
Run Code Online (Sandbox Code Playgroud)

这会产生以下错误g++(我试图只复制相关的行):

error: use of deleted function ‘main()::<lambda()>::<lambda>(const main()::<lambda()>&’
Run Code Online (Sandbox Code Playgroud)

......我想,我暗示我移动lambda的尝试失败了.

clang++ 给出了类似的错误.

我试着明确地move使用lambda(即使它是一个临时值),但这没有帮助.

编辑:下面的答案充分解决了上述代码产生的编译错误.对于另一种方法,简单地release将唯一的指针的目标值成std::shared_ptr,它可以被复制.(我不是写这个作为答案,因为这会假设这是一个XY问题,但是为什么unique_ptr不能在被转换为a的lambda中使用的根本原因std::function很重要.)

编辑2:非常滑稽,auto_ptr据我所知,我只是意识到这里实际上会做正确的事情(!).它的作用基本上类似unique_ptr,但允许复制构造代替移动构造.

Bar*_*rry 17

你可以移动lambda,没关系.这不是你的问题,你试图用不可std::function复制的lambda 实例化一个.而且:

template< class F > 
function( F f );
Run Code Online (Sandbox Code Playgroud)

构造函数function:

5)初始化与目标副本f.

这是因为std::function:

满足CopyConstructible和CopyAssignable的要求.

由于function必须是可复制的,因此您放入其中的所有内容也必须是可复制的.并且只有移动的lambda不符合该要求.


Pra*_*ian 13

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));
}
Run Code Online (Sandbox Code Playgroud)

现场演示