简体   繁体   English

MSVC vs GCC & Clang 使用 lambda 时的错误

[英]MSVC vs GCC & Clang Bug while using lambdas

I was trying out an example presented at CppCon that uses lambdas .我正在尝试在CppCon上展示的一个使用lambdas的示例。 And to my surprise the program don't compile in gcc and clang(in either C++14 or C++17) but compiles in msvc.令我惊讶的是,该程序没有在 gcc 和 clang 中编译(在 C++14 或 C++17 中),而是在 msvc 中编译。 This can be verified here .这可以在这里验证。

For reference, the example code is as follows:作为参考,示例代码如下:

#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());
}

What is the problem here(if any) and which compiler is right?这里有什么问题(如果有的话),哪个编译器是正确的?

Note that the code is an exact copy-paste from their official presentation slide.请注意,该代码是从他们的官方演示幻灯片中精确复制粘贴的。

This is a problem with MSVC.这是 MSVC 的问题。 clang and g++ are correct. clang 和 g++ 是正确的。

From [expr.prim.lambda.capture]/3 (C++17 draft N4659)来自[expr.prim.lambda.capture]/3 (C++17 草案 N4659)

A lambda-expression whose smallest enclosing scope is a block scope (6.3.3) is a local lambda expression;其最小封闭 scope 是块 scope (6.3.3) 的 lambda 表达式是本地 lambda 表达式; any other lambda-expression shall not have a capture-default or simple-capture in its lambda-introducer.任何其他 lambda 表达式在其 lambda 引入器中不得有捕获默认或简单捕获。 The reaching scope of a local lambda expression is the set of enclosing scopes up to and including the innermost enclosing function and its parameters.局部 lambda 表达式的到达 scope 是封闭范围的集合,直到并包括最里面的封闭 function 及其参数。 [ Note: This reaching scope includes any intervening lambda-expressions. [注意:达到 scope 包括任何中间的 lambda 表达式。 —end note ] ——尾注]

Since = is a capture-default , and the lambda is not within a block-scope, the code is not valid.由于=capture-default ,并且 lambda 不在块范围内,因此代码无效。

What is the problem here(if any)这里有什么问题(如果有的话)

Let's ask what the compilers that refuse to compile have to say:让我们问一下拒绝编译的编译器有什么要说的:

 error: non-local lambda expression cannot have a capture-default

Let's see what the standard has to say:让我们看看标准是怎么说的:

C++14 draft N4140 C++14 草案 N4140

A lambda-expression whose smallest enclosing scope is a block scope ([basic.scope.block]) is a local lambda expression;最小封闭 scope 是块 scope ([basic.scope.block]) 的 lambda 表达式是一个局部 lambda 表达式; any other lambda-expression shall not have a capture-default or simple-capture in its lambda-introducer.任何其他 lambda 表达式在其 lambda 引入器中不得有捕获默认或简单捕获。 The reaching scope of a local lambda expression is the set of enclosing scopes up to and including the innermost enclosing function and its parameters.局部 lambda 表达式的到达 scope 是封闭范围的集合,直到并包括最里面的封闭 function 及其参数。 [ Note: This reaching scope includes any intervening lambda-expressions. [注意:达到 scope 包括任何中间的 lambda 表达式。 — end note ] ——尾注]


latest draft最新草案

A lambda-expression shall not have a capture-default or simple-capture in its lambda-introducer unless its innermost enclosing scope is a block scope ([basic.scope.block]) or it appears within a default member initializer and its innermost enclosing scope is the corresponding class scope ([basic.scope.class]). lambda 表达式在其 lambda 引入器中不应包含捕获默认值或简单捕获,除非其最内层的封闭 scope 是一个块 scope([basic.scope.block])或者它出现在默认成员初始化器及其最内层的封闭scope对应的是class scope([basic.scope.class])。

C++17 wording is nearly identical to C++14. C++17 的措辞与 C++14 几乎相同。

The program is ill-formed and the diagnostic message is correct.程序格式错误,诊断消息正确。 The compilers that don't diagnose the ill-formedness (icc, msvc) don't conform to the standard.不诊断格式错误的编译器(icc、msvc)不符合标准。


The program can be fixed simply by removing the capture-default.该程序可以简单地通过删除 capture-default 来修复。 It cannot capture anything outside of a block scope anyway which makes it useless which is why it isn't allowed.无论如何,它无法捕获块 scope 之外的任何内容,这使得它无用,这就是为什么不允许它。 Globals such as ::g can be accessed without capturing them.可以在不捕获它们的情况下访问诸如::g之类的全局变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 GCC vs Clang & MSVC 使用非类型模板参数时出现错误 - GCC vs Clang & MSVC Bug while using non type template parameter GCC &amp; Clang vs MSVC Bug,同时在函数模板的相同参数子句中扩展模板参数包 - GCC & Clang vs MSVC Bug while expanding template parameter pack in the same parameter clause for function templates C ++ MSVC / GCC / Clang编译器错误 - C++ MSVC/GCC/Clang compilers bug MSVC 与 Clang/GCC 错误在函数模板的重载解决期间,其中一个包含参数包 - MSVC vs Clang/GCC bug during overload resolution of function templates one of which contains a parameter pack c ++:MSVC与GCC + CLANG:处理lambdas捕获类成员变量,正确的方法是什么? - c++: MSVC vs. GCC+CLANG: Handling lambdas capturing class member variables, what is the correct approach? 在clang vs gcc和msvc中按方法指针的模板 - Template by method pointer in clang vs gcc and msvc Clang vs GCC vs MSVC - 使用大括号括起初始化列表创建用户定义类型? - Clang vs GCC vs MSVC - using brace-enclosed initializer list to create user defined type? 在fold表达式中使用lambdas时出现“未初始化的捕获引用”错误 - clang vs gcc - “Uninitialized captured reference” error when using lambdas in fold expression - clang vs gcc 命名空间 scope - gcc 与 clang 与 msvc 中的外部 - extern in namespace scope - gcc vs clang vs msvc 没有GCC或MSVC的Clang - Clang without GCC or MSVC
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM