0

Consider the following code:

int main() {
    int n = 0;
    return [n]  { return n; }(); // ok
}

According to https://cppinsights.io, the code above will be translated into the following code:

int main() {
    int n = 0;

    class __lambda_3_12 {
    public:
        inline /*constexpr */ int operator()() const {
            return n;
        }

    private:
        int n;

    public:
        __lambda_3_12(int& _n) : n{_n} {
        }

    } __lambda_3_12{n};

    return __lambda_3_12.operator()();
}

However, the following code is ill-formed:

int main() {
    int n = 0;
    // error: invalid use of 'this' outside of a non-static member function
    return [n]  { return this->n; }(); 
}

I think the C++ standard must have forbidden the compiler to use this pointer to access the captured variables. However, I cannot find the exact statements in 7.5.6 [expr.prim.lambda] of the C++ standard draft.

8
  • 4
    What you see on cppinsights is a specific implementation detail. While this is the most common way to implement it, the C++ specification doesn't really imply this as the only suitable implementation. Therefore you can't use this because a lambda isn't really a class or object in itself, from the C++ language perspective. There is no context in the lambda except the captures you have. Commented Jul 12 at 2:41
  • 4
    Besides, if you have a lambda inside an actual class and capture this, what would this then refer to? The compiler-generated class object, or the captured this? Commented Jul 12 at 2:43
  • 1
    You might use deducing this i.e [n](this auto& self) { return self.n; }. Commented Jul 12 at 3:17
  • 1
    @Jarod42, [n](this auto& self) { return self.n; } is ill-formed, either. Commented Jul 12 at 4:59
  • 1
    @xmllmx: oups, was accepted by msvc Demo :-/ Commented Jul 12 at 16:02

1 Answer 1

3

Below are the relevant sections from the latest C++ standard (emphasis mine):

7.5.6.2/p1&p2 [expr.prim.lambda.closure]

  • The type of a lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type, called the closure type, whose properties are described below.

  • The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression.

7.5.6.2/p15 [expr.prim.lambda.closure]

  • The lambda-expression's compound-statement yields the function-body ([dcl.fct.def]) of the function call operator, but it is not within the scope of the closure type.

[Example 10:

struct S1 {
    int x, y;
    int operator()(int);
    void f() {
        [=]()->int {
            // equivalent to S1​::​operator()(this->x + (*this).y)
            // this has type S1*
            return operator()(this->x + y); 
        };
    }
};

end example]

Note that the standard explicitly states:

The lambda-expression's compound-statement yields the function-body of the function call operator, but it is not within the scope of the closure type.

So, the statements in the lambda expression, which are not within the closure type's scope, cannot access the this pointer of the closure object.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.