Search code examples
c++lambdalanguage-lawyerunions

Capture in a lambda expression of anonymous union member


As we know an anonymous 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; };    
    //[&]() { return x; };

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

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

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

unnamed variable cannot be implicitly captured in a lambda expression

As to explicit capture (both by value [x] and by reference [&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?


Solution

  • The defect report and resolution of CWG 1612 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 and [expr.prim.lambda.capture]/12 in the post-C++20 draft N4868:

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

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