gpt4 book ai didi

c++ - 在嵌套 Lambda 中捕获 Lambda 的静态

转载 作者:IT老高 更新时间:2023-10-28 23:02:27 26 4
gpt4 key购买 nike

this answer我使用此代码:

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 yields :

0 0 0 0 0 0 0 0 0 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 yields :

0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0

Visual Studio 2015 给我一个编译时错误:

An internal error has occurred in the compiler.

如果我将捕获嵌套捕获更改为显式捕获 row 我会收到编译器错误:

identifier in capture must be a variable with automatic storage duration declared in the reaching scope of the lambda

我可以在嵌套的 lambda 中捕获 static 吗?看起来是合法的,但是问题太多了!

编辑:

Fozi pointed out如果我将嵌套 lambda 的参数类型从 const auto& 更改为 const int& 。这似乎完全不相关,但确实有效。

如果我尝试显式捕获 row,这将不起作用。在那种情况下,我仍然会收到编译器错误:

identifier in capture must be a variable with automatic storage duration declared in the reaching scope of the lambda

我在这里报告了一个 Visual Studio 2015 错误:https://connect.microsoft.com/VisualStudio/feedback/details/1930409/capturing-a-lambdas-static-in-a-nested-lambda

最佳答案

内部编译器错误 (ICE) 始终是错误。

我们不需要捕获静态存储持续时间的变量,但我们需要捕获自动变量odr-used .来自草案 C++ 标准部分 5.1.2:

The lambda-expression’s compound-statement yields the function-body (8.4) of the function call operator, but for purposes of name lookup (3.4), determining the type and value of this (9.3.2) and transforming idexpressions referring to non-static class members into class member access expressions using (*this) (9.3.1), the compound-statement is considered in the context of the lambda-expression.

所以 row 应该在内部 lambda 中可见,并且:

[...]If a lambda-expression or an instantiation of the function call operator template of a generic lambda odr-uses (3.2) this or a variable with automatic storage duration from its reaching scope, that entity shall be captured by the lambda-expression.[...]

只有 this 和自动存储持续时间的变量在 odr-used 时才需要捕获,我们可以看到显式捕获仅针对自动变量或 this 定义:

The identifier in a simple-capture is looked up using the usual rules for unqualified name lookup (3.4.1); each such lookup shall find an entity. An entity that is designated by a simple-capture is said to be explicitly captured, and shall be this or a variable with automatic storage duration declared in the reaching scope of the local lambda expression.

为了让 Visual Studio 和 gcc 都匹配 clang 的结果,我可以将 row 移出到全局命名空间 see it live for gcc .正如 Fozi 指出的那样,将 const auto&/*j*/ 更改为 const int&/*j*/ 使其开始工作。

看起来 gcc 接受显式捕获非自动变量作为扩展,甚至显式捕获 row 例如 [&, &row](const auto & )仍然产生全零。

如果我将 row 的定义移动到 main 则进一步了解 gcc,然后我会看到以下错误 ( see it live ):

/tmp/cchzwtQI.s: Assembler messages:
/tmp/cchzwtQI.s:1572: Error: symbol `_ZL3row' is already defined

这对我来说似乎是一个编译器错误。

我没有看到标准的任何部分会使原始程序格式错误。将 auto 更改为 int 也不应该产生影响,并且不会影响 polymorphic lambda proposal 引入的更改。似乎也可以解释这种差异。

关于c++ - 在嵌套 Lambda 中捕获 Lambda 的静态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33285103/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com