Enlico
Enlico

Reputation: 28396

"Capture by move" does not prevent capture by reference

When I write [&,x](){ /* making use of x */ }, x is captured by value.

When I write [=,&x](){ /* making use of x */ }, x is captured by reference.

If I try writing [&x, x](){ … } I get an error telling me x can appear only once in a capture list.

However, [&x, y = std::move(x)](){ /* making use of x and y */ }(); compiles fine but I get a segmentation fault.

Why does the code even compile? Why does the standard allow that I capture a variable by reference and I also use it in a "capture by-move" init capture?

Upvotes: 4

Views: 144

Answers (1)

alex_noname
alex_noname

Reputation: 32073

The case [&x, y = std::move(x)](){ }; is quite legal from the point of view of the compiler, because different identifiers are used for capture. The standard says the following:

[expr.prim.lambda/capture-2]

Ignoring appearances in initializers of init-captures, an identifier or this shall not appear more than once in a lambda-capture.

[&i, a = i]{ };    // OK
[&i, a = std::move(i)]{ };    // OK

[&i, i]{ };       // error: i repeat
[&i, i = std::move(i)]{ };    // error: i repeated

Upvotes: 4

Related Questions