在匿名联合成员的Lambda表达式中捕获

huangapple go评论59阅读模式
英文:

Capture in a lambda expression of anonymous union member

问题

正如我们所知,[匿名联合体](https://en.cppreference.com/w/cpp/language/union) 是一个未命名的联合体定义,不同时定义任何变量。并且匿名联合体的成员会被注入到封闭的作用域中。但在 lambda 表达式中捕获这些成员是否受到任何限制呢?

在下面的示例程序中
```cpp
int main() {
    union {
        int x{0};
        char y[4];
    };

    // 到处都是错误
    //[=]() { return x; };    
    //[&]() { return x; };

    // 仅在 GCC 中可以
    [x]() { return x; };
    [&x]() { return x; };

    // 在所有编译器中都可以
    [x=x]() { return x; };
    [&x=x]() { return x; };
}

所有编译器都拒绝进行隐式捕获(无论是按值 [=] 还是按引用 [&])。例如,Clang 的错误信息是

无法在 lambda 表达式中隐式捕获未命名变量

至于显式捕获(无论是按值 [x] 还是按引用 [&x]),各编译器存在分歧。MSVC 输出相同的错误信息:

错误 C3492: 无法捕获匿名联合体的成员 'x'

Clang 的错误信息发生变化,变得不太清晰:

捕获列表中的 'x' 未命名变量

而 GCC 则允许显式捕获,没有任何警告。在线演示:https://gcc.godbolt.org/z/Ghq66rjfW

在这里哪个编译器是正确的?


<details>
<summary>英文:</summary>

As we know [an anonymous union](https://en.cppreference.com/w/cpp/language/union) is an unnamed union definition that does not simultaneously define any variables. And members of an anonymous union are injected in the enclosing scope. But are there any restrictions on capturing these members in lambda expressions?

In the following example program

int main() {
union {
int x{0};
char y[4];
};

// error everywhere
//[=]() { return x; };    
//[&amp;]() { return x; };

// ok in GCC only
[x]() { return x; };
[&amp;x]() { return x; };

// ok in all
[x=x]() { return x; };
[&amp;x=x]() { return x; };

}

all compilers refuse to make implicit capture (both by value `[=]` and by reference `[&amp;]`). E.g. Clang&#39;s error is

unnamed variable cannot be implicitly captured in a lambda expression


As to explicit capture (both by value `[x]` and by reference `[&amp;x]`), here compilers diverge. MSVC prints the same error:

error C3492: 'x': you cannot capture a member of an anonymous union


The error from Clang changes and becomes less clear:

'x' in capture list does not name a variable


And GCC permits explicit capture without any warning. Online demo: https://gcc.godbolt.org/z/Ghq66rjfW

Which compiler is right here?

</details>


# 答案1
**得分**: 5

缺陷报告和[CWG 1612](https://cplusplus.github.io/CWG/issues/1612.html)的解决方案意味着不允许捕获匿名联合体的任何成员,无论是通过复制还是引用,无论是隐式还是显式。

请参见例如[\[expr.prim.lambda.capture\]/10](https://timsong-cpp.github.io/cppwp/n4868/expr.prim.lambda.capture#10.sentence-5)和[\[expr.prim.lambda.capture\]/12](https://timsong-cpp.github.io/cppwp/n4868/expr.prim.lambda.capture#12.sentence-4)在后C++20草案N4868中:

&gt; [...] 匿名联合体的成员不得被复制捕获。

&gt; [...] 位字段或匿名联合体的成员不得被引用捕获。

<details>
<summary>英文:</summary>

The defect report and resolution of [CWG 1612](https://cplusplus.github.io/CWG/issues/1612.html) means that it is not allowed to capture any member of an anonymous union, neither by copy or reference, neither implicitly nor explicitly.

See e.g. [\[expr.prim.lambda.capture\]/10](https://timsong-cpp.github.io/cppwp/n4868/expr.prim.lambda.capture#10.sentence-5) and [\[expr.prim.lambda.capture\]/12](https://timsong-cpp.github.io/cppwp/n4868/expr.prim.lambda.capture#12.sentence-4) in the post-C++20 draft N4868:

&gt; [...] A member of an anonymous union shall not be captured by copy.

&gt; [...] A bit-field or a member of an anonymous union shall not be captured by reference.

</details>



huangapple
  • 本文由 发表于 2023年5月28日 23:59:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/76352358.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定