Why can't I capture this by-reference ('&this') in lambda?

c++, c++11, lambda

Solution

The reason `[&this]` doesn't work is because it is a syntax error. Each comma-seperated parameter in the `lambda-introducer` is a `capture`:

capture:
    identifier
    & identifier
    this

You can see that `&this` isn't allowed syntactically. The reason it isn't allowed is because you would never want to capture `this` by reference, as it is a small const pointer. You would only ever want to pass it by value - so the language just doesn't support capturing `this` by reference.

To capture `this` explicitly you can use `[this]` as the `lambda-introducer`.

The first `capture` can be a `capture-default` which is:

capture-default:
    &
    =

This means capture automatically whatever I use, by reference (`&`) or by value (`=`) respectively - however the treatment of `this` is special - in both cases it is captured by value for the reasons given previously (even with a default capture of `&`, which usually means capture by reference).

5.1.2.7/8:

For purposes of name lookup (3.4), determining the type and value of `this` (9.3.2) and transforming id- expressions referring to non-static class members into class member access expressions using `(*this)` (9.3.1), the compound-statement [OF THE LAMBDA] is considered in the context of the lambda-expression.

So the lambda acts as if it is part of the enclosing member function when using member names (like in your example the use of the name `x`), so it will generate "implicit usages" of `this` just like a member function does.

If a lambda-capture includes a capture-default that is `&`, the identifiers in the lambda-capture shall not be preceded by `&`. If a lambda-capture includes a capture-default that is `=`, the lambda-capture shall not contain `this` and each identifier it contains shall be preceded by `&`. An identifier or `this` shall not appear more than once in a lambda-capture.

So you can use `[this]`, `[&]`, `[=]` or `[&,this]` as a `lambda-introducer` to capture the `this` pointer by value.

However `[&this]` and `[=, this]` are ill-formed. In the last case gcc forgivingly warns for `[=,this]` that `explicit by-copy capture of ‘this’ redundant with by-copy capture default` rather than errors.

Problem

I understand the correct way to capture `this` (to modify object properties) in a lambda is as follows: ``` auto f = [this] () { /* ... */ }; ``` But I'm curious as to the following peculiarity I've seen: ``` class C { public: void foo() { // auto f = [] () { // this not captured auto f = [&] () { // why does this work? // auto f = [&this] () { // Expected ',' before 'this' // auto f = [this] () { // works as expected x = 5; }; f(); } private: int x; }; ``` The oddity that I am confused by (and would like answered) is why the following works: ``` auto f = [&] () { /* ... */ }; // capture everything by reference ``` And why I cannot explicitly capture `this` by reference: ``` auto f = [&this] () { /* ... */ }; // a compiler error as seen above. ```

Original source