繁体   English   中英

在clang和gcc中移动可分配的lambdas

[英]move assignable lambdas in clang and gcc

我有这个程序:

int main()
{
  auto l([](){});

  ::std::cout << ::std::is_move_assignable<decltype(l)>{} << ::std::endl;
}

gcc-6.1.1显示0

clang-3.8.0显示1

这导致我的程序中出现编译错误。 哪个编译器是对的?

错误:

error: object of type '(lambda at t.cpp:5:5)' cannot be assigned because its copy assignment operator is implicitly deleted

但这与我的问题无关。

N4140(大致是C ++ 14)说:

5.1.2 Lambda表达式[expr.prim.lambda]

20与lambda表达式关联的闭包类型具有已删除(8.4.3)的默认构造函数和已删除的复制赋值运算符。 它有一个隐式声明的复制构造函数(12.8),并且可能有一个隐式声明的移动构造函数(12.8)。 [ 注意:复制/移动构造函数的隐式定义方式与隐式定义任何其他隐式声明的复制/移动构造函数的方式相同。 - 结束说明 ]

请注意,这并未提及是否隐式声明了已删除的复制赋值运算符。 编译器将lambda转换为类定义和实例化,但是可以通过隐式声明复制赋值运算符的方式巧妙地定义该类,但该类的某些其他属性会导致隐式复制赋值运算符被删除。

然后:

12.8复制和移动类对象[class.copy]

20如果类X的定义没有显式地声明一个移动赋值运算符,那么当且仅当一个运算符默认时,它将被隐式声明为默认值

(20.1) - X没有用户声明的拷贝构造函数,

(20.2) - X没有用户声明的移动构造函数,

(20.3) - X没有用户声明的复制赋值运算符,和

(20.4) - X没有用户声明的析构函数。

如果隐式声明lambda的复制赋值运算符,则它不会禁止生成移动赋值运算符。 如果显式声明,则禁止移动赋值运算符。

根据标准的字面措辞,这两种行为都是可辩护的。

CWG问题1891部分解决了这个问题 ,该问题将文本改为:

lambda表达式关联的闭包类型没有默认构造函数和已删除的复制赋值运算符。 它有一个默认的复制构造函数和一个默认的移动构造函数(12.8 [class.copy])。 [ 注意:这些特殊成员函数是通常隐式定义的,因此可能被定义为已删除。 - 结束说明 ]

然而,尽管移动分配操作员在该问题中被提出作为一个问题,它并没有改变答案,它继续留下开放的可能性。

具有空捕获列表的 lambda被定义为可分配给函数指针类型,因此如果您的实际代码也具有该类型的lambda函数,则可以使用函数指针。

暂无
暂无

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

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