在嵌套 Lambda 中捕获 Lambda 的静态
Capturing a Lambda's static in a Nested Lambda
在这个答案中,我使用以下代码:
std::vector<std::vector<int>> imat(3, std::vector<int>(10));
std::for_each(imat.begin(), imat.end(), [&](auto& i) {
static auto row = 0;
auto column = 0;
std::transform(i.begin(), i.end(), i.begin(),
[&](const auto& /*j*/) {
return row * column++;
});
++row;
});
但是我注意到在捕获static auto row
时一些错误的行为取决于编译器。
Clang 3.7.0生成:
0 1 2 3 4 5 6 7 8 9
0 2 4 6 8 10 12 14 16 18
gcc 5.1.0 yield:
<<
>
和Visual Studio 2015给了我一个编译时错误:
编译器内部错误。
如果我改变捕获嵌套捕获显式捕获row
,我得到编译器错误:
捕获中的标识符必须是在lambda
的到达范围内声明具有自动存储持续时间的变量。
允许在嵌套lambda中捕获static
吗?这似乎是合法的,但有很多问题!
Fozi指出,如果我将嵌套lambda的参数类型从const auto&
更改为const int&
,则I 可以获得Visual Studio 2015编译并给出与Clang 3.7.0相同的输出。这看起来完全不相关,但却有效。
如果我试图显式捕获row
,这不起作用。在这种情况下,我仍然得到编译器错误:
捕获中的标识符必须是在lambda
的到达范围内声明具有自动存储持续时间的变量。
我报告了VisualStudio 2015的一个bug: https://connect.microsoft.com/VisualStudio/feedback/details/1930409/capturing-a-lambdas-static-in-a-nested-lambda
内部编译错误(ICE)总是一个bug。
我们不需要捕获静态存储持续时间的变量,但我们确实需要捕获经常使用的自动变量。来自c++标准草案5.1.2
:
lambda表达式的复合语句产生函数调用操作符的函数体(8.4),,但用于名称查找(3.4),确定this(9.3.2)的类型和值并转换表达式使用(*this)(9.3.1)在类成员访问表达式中引用非静态类成员,复合语句在lambda表达式的上下文中被考虑。
所以row
应该在内部lambda和:
[…如果是lambda表达式或者泛型lambda odr的函数调用操作符模板的实例化-使用(3.2)this或a具有自动存储期限的变量,从其到达范围开始,该实体应由lambda表达式。[…]
捕获只需要用于this
和自动存储持续时间的变量,如果它们是odr使用的,我们可以看到显式捕获只定义为自动变量或 :
简单捕获中的标识符使用非限定名称查找的常规规则查找(3.4.1);每个这样的查找将找到一个实体。由简单捕获指定的实体称为显式实体捕获的,并且应该是this或在到达范围内声明具有自动存储持续时间的变量
对于Visual Studio和gcc都匹配clang的结果,我可以将row
移到全局命名空间中,参见gcc的现场。此外,Fozi指出,将const auto& /*j*/
更改为const int& /*j*/
可以使其开始工作。
看起来gcc接受显式捕获非自动变量作为扩展,即使显式捕获row
,例如[&, &row](const auto & )
仍然产生全零。
对于gcc,如果我将row
的定义移动到main
,那么我看到以下错误( live):
/tmp/cchzwtQI.s: Assembler messages:
/tmp/cchzwtQI.s:1572: Error: symbol `_ZL3row' is already defined
这对我来说似乎是一个编译错误。
我看不出标准的任何部分会使原始程序格式错误。将auto
更改为int
也不应该产生差异,并且由多态lambda提议引入的更改似乎也不能解释这种差异。
- C++ 模板类型的静态 lambda 成员的构造
- 获取具有静态局部变量的绑定/推断捕获 lambda 的函数指针
- C++ lambda - 捕获静态成员变量
- 是否允许在作为静态数据结构成员的lambda函数中捕获变量
- 无法捕获 lambda 中的静态变量
- 具有静态大小数组作为参数的泛型 lambda
- 类初始化中的静态 lambda
- 使用 lambda 初始化静态数组
- 使用 lambda 函数初始化静态数据成员
- 捕获的静态断言 lambda
- 返回对 std::函数包装的 lambda 中静态变量的引用会导致段错误
- 为什么静态 lambda 成员的封闭类型不完整?
- lambda(或函数)C++中的静态初始化
- lambda 如何捕获局部静态变量?
- 将 lambda 函数分配给静态成员变量 (c++)
- 长镜头 -- 可能有一个静态类成员,该类成员具有访问非静态成员的 lambda
- 静态(可能是constexpr)数据成员lambda
- 在lambda中使用静态方法的错误
- 如何在声明和定义中拆分静态lambda
- 尝试在静态功能(C )中使用lambda函数