在 clang 和 gcc 中移动可分配的 lambda
Posted
技术标签:
【中文标题】在 clang 和 gcc 中移动可分配的 lambda【英文标题】:move assignable lambdas in clang and gcc 【发布时间】:2016-07-23 11:38:46 【问题描述】:我有这个程序:
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
但这与我的问题无关。
【问题讨论】:
显示你得到的错误。 【参考方案1】:N4140(大约 C++14)说:
5.1.2 Lambda 表达式 [expr.prim.lambda]
20 与 lambda-expression 关联的闭包类型具有已删除的 (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 issue 1891 部分解决了此问题,将文本更改为:
与 lambda-expression 关联的闭包类型没有默认构造函数和已删除的复制赋值运算符。它有一个默认的复制构造函数和一个默认的移动构造函数(12.8 [class.copy])。 [注意: 这些特殊的成员函数像往常一样被隐式定义,因此可能被定义为删除。 -- 尾注]
然而,尽管在该问题中提出了移动赋值运算符作为一个问题,但它并没有改变答案,它继续保持开放的可能性。
【讨论】:
【参考方案2】:具有空捕获列表的 lambda 被定义为可分配给函数指针类型,因此如果您的实际代码也具有该类型的 lambda 函数,您可以只使用函数指针。
【讨论】:
随意捕捉示例中的内容。 @user1095108 好吧,您的问题显示了一个没有捕获的 lambda,并询问 that 是否应该是可移动的。您需要为问题准备一个 MVCE(在这种情况下,它就像捕获一个变量一样简单)。以上是关于在 clang 和 gcc 中移动可分配的 lambda的主要内容,如果未能解决你的问题,请参考以下文章
是否有类似 -mcpu= 但用于 gcc 和 clang 中的操作系统选择的东西?还是“选择最匹配的最近目标”?
gcc/clang 在基本结构的后填充中布置派生结构的字段[重复]