Narek
Narek

Reputation: 39881

Is it legal to re-capture variables with Lambda function?

Is it correct to write such code:

class A
{
private:
    int m_int;

public:
    void foo()
    {
        int a = 1;
        int b = 2;
        int c = 3;
        float f = 3.14f;
        std::string s("Something");

        const auto f1 = [=] ()
        {
            // use only a, b, c
            int d = a + b + c;

            const auto f2 = [=] 
            {
                // use f, s and also d
                std::cout << f << s << d ;
            }
        };
    }
};

The problem is inner lambda uses some variables that outer one does not require. If this is not valid, then how I should write?

NOTE: I could also capture pointer variables. So a, b, c, f, and s could be pointers too.

Upvotes: 1

Views: 151

Answers (4)

Vlad from Moscow
Vlad from Moscow

Reputation: 311068

According to the C++ Standard (5.1.2 Lambda expressions)

9 A lambda-expression whose smallest enclosing scope is a block scope (3.3.3) is a local lambda expression; any other lambda-expression shall not have a capture-default or simple-capture in its lambda-introducer. The reaching scope of a local lambda expression is the set of enclosing scopes up to and including the innermost enclosing function and its parameters. [ Note: This reaching scope includes any intervening lambda-expressions. —end note ]

So the reaching scope of the second lambda is the scope of the member function foo(). As the lambda expression has default capture then it can capture local variables in this reaching scope.

It is important also to pay attention to the following part of paragraph #13 of the same section

13 ... If a lambda-expression captures an entity and that entity is not defined or captured in the immediately enclosing lambda expression or function, the program is ill-formed.

In your example the enclosing lambda captures implicitly all required variables for the inner lambda from the function block scope using the default capture.

Upvotes: 2

ALEXANDER KONSTANTINOV
ALEXANDER KONSTANTINOV

Reputation: 913

This will work because you are capturing all local variables by value by typing [=]. So f, s and d will be visible inside f2, but it would be only the copies, not the actual variables

Upvotes: 0

David Haim
David Haim

Reputation: 26506

Quoting from http://en.cppreference.com/w/cpp/language/lambda

[=] captures all automatic variables odr-used in the body of the lambda by value

Because you capture all the variables of foo in f1 , there is not problem using them in f2.

so it is valid, although you might want to consider catching them by refernece.

Upvotes: 0

SergeyA
SergeyA

Reputation: 62603

The code in question as asked (notwithstanding typo in inner lambda declaration) is correct. Since the first lambda is going to capture everything from the enclosing function, the second lambda is going to have access to it through 'capture all' of the enclosing lambda.

Upvotes: 4

Related Questions