简体   繁体   English

C++ `std::move` 自定义类型转换为 lambda 捕获

[英]C++ `std::move` custom type into a lambda capture

I have a class in which I deleted the copy assignment operator and copy constructor, leaving only a move assignment operator and move constructor.我有一个 class ,其中我删除了复制赋值运算符和复制构造函数,只留下了移动赋值运算符和移动构造函数。 For example:例如:

struct Number {
  public:
  int *pNum;

  Number &operator=(const Number &rhs) = delete;
  Number(const Number &rhs) = delete;

  Number &operator=(Number &&rhs) {
    if (&rhs == this) {
      return *this;
    }

    pNum = rhs.pNum;
    rhs.pNum = nullptr;
    return *this;
  }

  Number() = default;

  Number(Number &&rhs) {
    *this = std::move(rhs);
  }

  ~Number() {
    delete pNum;
  }
};

Now, I want to use std::move to capture this class into a lambda.现在,我想使用std::move将此 class 捕获到 lambda 中。 For example:例如:

int main() {
  std::function<int(int)> add;


  int a = 3;

  {

    Number n{};
    n.pNum = new int;
    *n.pNum = 5;

    add = [&, capA{std::move(n)}](int) mutable -> int {
      int b = *capA.pNum; // 5
      return a + b; // 8
    };
  }

  std::cout << add(3);
}

However, it seems that n would be const so that c++ would try to use the deleted copy constructor.但是,似乎n将是const以便 c++ 会尝试使用已删除的复制构造函数。 How would I fix this?我将如何解决这个问题? (REPL: https://repl.it/@25GrantY/WeirdLambda ) (REPL: https://repl.it/@25GrantY/WeirdLambda

The problem isn't with the lambda.问题不在于 lambda。 Eg this works:例如,这有效:

auto l = [&, capA{std::move(n)}](int) mutable -> int {
      int b = *capA.pNum; // 5
      return a + b; // 8
    };

The problem is with std::function and this lambda.问题出在std::function和这个 lambda 上。 Because you capture a non-copyable object then the lambda is non-copyable.因为您捕获了不可复制的 object,所以 lambda 是不可复制的。 std::function requires its stored object to be copyable so that's why it doesn't work. std::function要求其存储的 object 是可复制的,这就是它不起作用的原因。

You can read more here: Move-only version of std::function您可以在此处阅读更多信息: std::function 的仅移动版本

the problem here is coming from std::function.这里的问题来自 std::function。 This class must satisfy CopyConstructible and CopyAssignable requirements, according to documentation.根据文档,此 class 必须满足 CopyConstructible 和 CopyAssignable 要求。 https://en.cppreference.com/w/cpp/utility/functional/function https://en.cppreference.com/w/cpp/utility/functional/function

std::function satisfies the requirements of CopyConstructible and CopyAssignable. std::function 满足 CopyConstructible 和 CopyAssignable 的要求。

When you attempt to initialize std::function with a lambda that captured move-only type by value, such assignment (if successful) would violate the both of the requirements above.当您尝试使用按值捕获仅移动类型的 lambda 来初始化 std::function 时,此类分配(如果成功)将违反上述两个要求。

This is why compilation fails with an error.这就是编译失败并出现错误的原因。

How to fix this?如何解决这个问题?

Either do not use std::function, or make your lambda copyable.要么不要使用 std::function,要么让你的 lambda 可复制。

You can use std::shared_ptr as a copyable wrapper for move-only type.您可以使用 std::shared_ptr 作为仅移动类型的可复制包装器。

auto shared_number = std::make_shared<Number>{};

Now, you can pass shared_number to lambda, and assign to std::function.现在,您可以将 shared_number 传递给 lambda,并分配给 std::function。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM