![](/img/trans.png)
[英]GCC vs Clang & MSVC Bug while using non type template parameter
[英]MSVC vs GCC & Clang Bug while using lambdas
我正在尝试在CppCon上展示的一个使用lambdas的示例。 令我惊讶的是,该程序没有在 gcc 和 clang 中编译(在 C++14 或 C++17 中),而是在 msvc 中编译。 这可以在这里验证。
作为参考,示例代码如下:
#include <stdio.h>
int g = 10;
auto kitten = [=]() { return g+1; };
auto cat = [g=g]() { return g+1; };
int main() {
g = 20;
printf("%d %d\n", kitten(), cat());
}
这里有什么问题(如果有的话),哪个编译器是正确的?
请注意,该代码是从他们的官方演示幻灯片中精确复制粘贴的。
这是 MSVC 的问题。 clang 和 g++ 是正确的。
来自[expr.prim.lambda.capture]/3
(C++17 草案 N4659)
其最小封闭 scope 是块 scope (6.3.3) 的 lambda 表达式是本地 lambda 表达式; 任何其他 lambda 表达式在其 lambda 引入器中不得有捕获默认或简单捕获。 局部 lambda 表达式的到达 scope 是封闭范围的集合,直到并包括最里面的封闭 function 及其参数。 [注意:达到 scope 包括任何中间的 lambda 表达式。 ——尾注]
由于=
是capture-default
,并且 lambda 不在块范围内,因此代码无效。
这里有什么问题(如果有的话)
让我们问一下拒绝编译的编译器有什么要说的:
error: non-local lambda expression cannot have a capture-default
让我们看看标准是怎么说的:
C++14 草案 N4140
最小封闭 scope 是块 scope ([basic.scope.block]) 的 lambda 表达式是一个局部 lambda 表达式; 任何其他 lambda 表达式在其 lambda 引入器中不得有捕获默认或简单捕获。 局部 lambda 表达式的到达 scope 是封闭范围的集合,直到并包括最里面的封闭 function 及其参数。 [注意:达到 scope 包括任何中间的 lambda 表达式。 ——尾注]
最新草案
lambda 表达式在其 lambda 引入器中不应包含捕获默认值或简单捕获,除非其最内层的封闭 scope 是一个块 scope([basic.scope.block])或者它出现在默认成员初始化器及其最内层的封闭scope对应的是class scope([basic.scope.class])。
C++17 的措辞与 C++14 几乎相同。
程序格式错误,诊断消息正确。 不诊断格式错误的编译器(icc、msvc)不符合标准。
该程序可以简单地通过删除 capture-default 来修复。 无论如何,它无法捕获块 scope 之外的任何内容,这使得它无用,这就是为什么不允许它。 可以在不捕获它们的情况下访问诸如::g
之类的全局变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.