[英]C++ `std::move` custom type into a lambda capture
我有一个 class ,其中我删除了复制赋值运算符和复制构造函数,只留下了移动赋值运算符和移动构造函数。 例如:
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;
}
};
现在,我想使用std::move
将此 class 捕获到 lambda 中。 例如:
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);
}
但是,似乎n
将是const
以便 c++ 会尝试使用已删除的复制构造函数。 我将如何解决这个问题? (REPL: https://repl.it/@25GrantY/WeirdLambda )
问题不在于 lambda。 例如,这有效:
auto l = [&, capA{std::move(n)}](int) mutable -> int {
int b = *capA.pNum; // 5
return a + b; // 8
};
问题出在std::function
和这个 lambda 上。 因为您捕获了不可复制的 object,所以 lambda 是不可复制的。 std::function
要求其存储的 object 是可复制的,这就是它不起作用的原因。
您可以在此处阅读更多信息: std::function 的仅移动版本
这里的问题来自 std::function。 根据文档,此 class 必须满足 CopyConstructible 和 CopyAssignable 要求。 https://en.cppreference.com/w/cpp/utility/functional/function
std::function 满足 CopyConstructible 和 CopyAssignable 的要求。
当您尝试使用按值捕获仅移动类型的 lambda 来初始化 std::function 时,此类分配(如果成功)将违反上述两个要求。
这就是编译失败并出现错误的原因。
如何解决这个问题?
要么不要使用 std::function,要么让你的 lambda 可复制。
您可以使用 std::shared_ptr 作为仅移动类型的可复制包装器。
auto shared_number = std::make_shared<Number>{};
现在,您可以将 shared_number 传递给 lambda,并分配给 std::function。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.