简体   繁体   English

Why visual c++ (latest) and gcc 12.1 accepted hiding this init capture for lambda, while clang 14.0.0 not? (c++20)

[英]Why visual c++ (latest) and gcc 12.1 accepted hiding this init capture for lambda, while clang 14.0.0 not? (c++20)

Case 1情况1

int main() {
    int x = 100;
    auto lamb_var = [y = x](){
                    int y = 10;
                    return y + 1;
    }; 

    assert (lamb_var() == 11);

    return 0; 
}

in https://godbolt.org/z/hPPParjnzhttps://godbolt.org/z/hPPParjnz

Both MSVC and GCC accepted shadowing the init-capture, while Clang accused y redefinition on the compound statement and throwed compiler error. MSVC 和 GCC 都接受了对 init-capture 的遮蔽,而 Clang 指责 y 在复合语句上重新定义并引发编译器错误。

However, if we remove the init-capture and make a simple-capture, all compilers accept Shadowing:但是,如果我们删除 init-capture 并进行 simple-capture,所有编译器都接受 Shadowing:

Case 2案例2

int main() {
    int x = 100;
    auto lamb_var = [x](){
                    int x = 10;
                    return x + 1;
    }; 

    assert (lamb_var() == 11);

    return 0; 
}

in https://godbolt.org/z/Gs4cadf5ehttps://godbolt.org/z/Gs4cadf5e


A simple-capture (case 2) leads to the creation of an attribute in the lambda-associated class, so shadowing should be normal.简单捕获(案例 2)导致在 lambda 关联的 class 中创建属性,因此阴影应该是正常的。

From what I found,the expression "whose declarative region is the body of the lambda expression" of the quote below from cppreference could defend the implementation of CLANG ("redefinition"), but I'm not sure.根据我的发现,cppreference 下面引用的“其声明区域是 lambda 表达式的主体”的表达式可以捍卫 CLANG (“重新定义”)的实现,但我不确定。

A capture with an initializer acts as if it declares and explicitly captures a variable declared with type auto, whose declarative region is the body of the lambda expression (that is, it is not in scope within its initializer), except that: [...] [1]带有初始化程序的捕获就像它声明并显式捕获了一个声明为 auto 类型的变量,其声明区域是 lambda 表达式的主体(也就是说,它不在其初始化程序中的 scope 中),除了: [.. .] [1]

Who is right in implementation (GCC and MSVC or Clang), and how to understand this citation of cppreference?谁在实施中是正确的(GCC 和 MSVC 或 Clang),以及如何理解对 cppreference 的引用?


[1] < https://en.cppreference.com/w/cpp/language/lambda > [1] < https://en.cppreference.com/w/cpp/language/lambda >

I think that clang is correct in rejecting snippet 1 and accepting snippet 2 because in the first case the non-static data member is named y while in the second case the non-static data member is unnamed .我认为clang 拒绝片段 1 并接受片段 2 是正确的,因为在第一种情况下,非静态数据成员被命名为y而在第二种情况下,非静态数据成员被命名为unnamed

Case 1情况1

Here we consider snippet 1:这里我们考虑片段 1:

int main() {
    int x = 100;
    auto lamb_var = [y = x](){  //the data member is "named" y
                    int y = 10; //error because we're defining y for second time 
                    return y + 1;
    }; 

    assert (lamb_var() == 11);

    return 0; 
}

Now, from expr.prim.lambda#capture-6 :现在,从expr.prim.lambda#capture-6

An init-capture without ellipsis behaves as if it declares and explicitly captures a variable of the form auto init-capture;没有省略号的 init-capture表现得好像它声明并显式捕获了auto init-capture; whose declarative region is the lambda-expression's compound-statement , except that:其声明区域是 lambda 表达式的复合语句,除了:

(emphasis mine) (强调我的)

This seems to indicate that the non-static data member has a name which in your given example is y .这似乎表明非静态数据成员的名称在您给定的示例中为y Now, by writing int y = 10;现在,通过写int y = 10; we're providing a redefinition of the same named variable y in the same declarative region and hence the error.我们在同一声明区域中提供了相同命名变量y的重新定义,因此出现了错误。


Note that we will get the same error(as expected due to the reason explained above), if we replace [y=x] with [x=x] and int y =10;请注意,如果我们将[y=x]替换为[x=x]并且int y =10;我们将得到相同的错误(由于上述原因)。 with int x = 10;int x = 10; as shown below:如下所示:

int main() {
    int x = 100;
    auto lamb_var = [x = x](){  //data member "named" x
                    int x = 10; //this will give same error 
                    return x + 1;
    }; 

    assert (lamb_var() == 11);

    return 0; 
}

Case 2案例2

Here we consider the second snippet:这里我们考虑第二个片段:

int main() {
    int x = 100;
    auto lamb_var = [x](){         //data member is unnamed
                    int x = 10;   //ok because we're defining an int variable with "name" x for the first time in this region
                    return x + 1;
    }; 

    assert (lamb_var() == 11);

    return 0; 
}

Here from expr.prim.lambda#capture-10 :这里来自expr.prim.lambda#capture-10

For each entity captured by copy, an unnamed non-static data member is declared in the closure type.对于通过副本捕获的每个实体,在闭包类型中声明了一个未命名的非静态数据成员 The declaration order of these members is unspecified....这些成员的声明顺序不详......

(emphasis mine) (强调我的)

In this case, the non-static data member is unnamed and so writing int x = 10;在这种情况下,非静态数据成员未命名,因此写作int x = 10; is not a redefinition error because we're definining a variable named x for the first time in this region.不是重新定义错误,因为我们在该区域中首次定义了一个名为x的变量。

暂无
暂无

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

相关问题 不推荐使用 C++20 中的 lambda 捕获 - Deprecated lambda capture in C++20 在 C++20(或更高版本)中完美转发 lambda 捕获 - Perfectly forwarding lambda capture in C++20 (or newer) 为什么 lambda 函数需要在 c++20 中显式捕获 [this] 指针? - Why do lambda functions need to capture [this] pointer explicitly in c++20? 我无法在屏幕上打印 output。 我正在使用 cppreference 端 (GCC 12.1 (c++20)) 编译器 - I am not able to print the output on the screen. I am using cppreference side (GCC 12.1 (c++20 )) compiler 如何在 gcc 或 clang 中使用 c++20(启用模块)包含多个预编译头文件 - How to include multiple precompiled headers in with c++20 (with modules enabled) in gcc or clang C++20 概念:在 MSVC 中,行外定义失败,但在 GCC 或 clang 中失败 - C++20 Concepts: out-of-line-definition fails with MSVC but not in GCC or clang C++20,如何用 Clang-10 或 GCC11 编译 - C++20, how to compile with Clang-10 or GCC11 C++20 中非类型文字参数的模板部分特化:clang 和 gcc 不一致 - Partial specialization of templates over non-type literal parameters in C++20: clang and gcc disagree Visual C ++初始化与gcc和clang的不一致 - Visual C++ initialization inconsistence with gcc and clang C++20 概念:GCC 和 Clang 中具有指针类型成员的复合需求表达式的行为差异 - C++20 Concepts: Difference in the behavior of the compound requirement expression with a pointer-type member in GCC and Clang
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM