移动clang和gcc中可分配的lambda
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的复制赋值运算符是隐式声明的,则不会禁止生成移动赋值运算符。如果显式声明了移动赋值运算符,则该运算符将被抑制。
根据标准的字面措辞,这两种行为都是可以辩护的。
1891年的CWG问题部分解决了这一问题,将文本改为:
与lambda表达式关联的闭包类型没有默认构造函数和已删除的复制赋值运算符。它有一个默认复制构造函数和一个默认移动构造函数(12.8[class.copy])。[注意:这些特殊成员函数是像往常一样隐式定义的,因此可能被定义为已删除。--end Note]
然而,尽管移动分配操作员被认为是该问题的一个问题,但它并没有改变答案,它仍然保留着可能性。
具有空捕获列表的lambda被定义为可分配给函数指针类型,因此如果实际代码也具有该类型的lambda函数,则可以使用函数指针。
- 可组合的lambda/std::函数与std::可选
- 我可以为unordered_map分配特定的模组值吗?
- 为 lambda 分配名称会影响性能吗?
- 使用领带从元组中分配 2 个 lambda
- 编写可测试的代码 - lambda 函数和unique_ptr中的basic_istream工厂
- 在可拆卸线程完成操作时取消分配内存
- 复制分配C++相同类型的 lambda
- 在线程中使用堆可分配 >100MB 的 RAM
- 哪种类型特征表明该类型是可分配的?(元组,对)
- C++概念相同且可分配
- 在开关语句中分配 lambda
- 如何使具有包含唯一指针的成员变量的类可复制可分配
- GCC C++11 删除移动可分配类的副本分配会阻止 std::sort 编译
- 如何使具有常量属性的类可分配
- 创建可分配的最大字符数组
- 如何使我自己的容器索引和可分配
- 为Fortran可分配程序在C中分配内存
- 移动包含向量<unique_ptr的可分配类<T>>
- 移动clang和gcc中可分配的lambda
- 对左值和右值的可分配引用