捕获lambda并可分配移动



我很困惑为什么捕获lambda不可移动赋值,但它的手动定义(作为带运算符((的结构(是。

考虑以下简化代码:

struct Environment {
Environment(std::unique_ptr<int>&& p): ptr(std::move(p)) {}

std::unique_ptr<int> ptr;
};
class LambdaCPPInsights
{
public: 
inline /*constexpr */ void operator()() const
{
}
private: 
std::shared_ptr<Environment> env;
public: 
LambdaCPPInsights(const std::shared_ptr<Environment> & _env)
: env{_env}
{}
};
constexpr const char* btos(bool b)
{
return b ? "true" : "false";
}
int main()
{

auto env =  std::make_shared<Environment>(std::make_unique<int>(4));

std::cout << "True   lambda is move-assignable: " << btos(std::is_move_assignable_v< decltype([env = env]() {}) >) << std::endl;
std::cout << "Manual lambda is move-assignable: " << btos(std::is_move_assignable_v< LambdaCPPInsights >);  
return 0;
}

LambdaCPPInsights类是由cpp insights提供的已翻译(然后重命名(的lambda结构,因此应该与[env = env]() {}定义的lambda相同。然而,在gcc11.2和c++20下的前一个代码的输出是:

True   lambda is move-assignable: false
Manual lambda is move-assignable: true

godbolt的示例如下:https://godbolt.org/z/Yx3n9eGj5

我错过了什么?

带有捕获的lambda有一个已删除的复制赋值运算符,这也意味着它没有隐式的移动赋值运算符。参见[Epr.primλ闭包]/13。

您的LambdaCPPInsights没有正确复制闭包类型。它应该显式默认复制和移动构造函数,并显式删除复制赋值运算符。

最新更新