mercredi 27 mai 2020

How are lambda captures initialised in case of nested lambdas?

Okay, so this is right off the bat from [expr.prim.lambda]p16 in n3337.pdf. Below code is given as an example:

int a = 1, b = 1, c = 1;
auto m1 = [a, &b, &c]() mutable
{
    auto m2 = [a, b, &c]() mutable
    {
        std::cout << a << b << c;     // Shouldn't this print 113 or 133?
        a = 4; b = 4; c = 4;
    };
    a = 3; b = 3; c = 3;
    m2();
};
a = 2; b = 2; c = 2;
m1();
std::cout << a << b << c;             // Okay, this prints 234

and that it shall generate below output:

123234

However, the way I have understood the text in [expr.prim.lambda] (which is somehow obviously flawed), I feel the output should be 113234, specifically the value of b printed in m2. Below is my understanding/explanation:

When std::cout << a << b << c; is executed inside m2, as per [expr.prim.lambda]p16 (emphasis mine):

If a lambda-expression m2 captures an entity and that entity is captured by an immediately enclosing lambda expression m1, then m2’s capture is transformed as follows:

if m1 captures the entity by copy, m2 captures the corresponding non-static data member of m1’s closure type;

Therefore, the a inside m2 shall capture the member generated to the corresponding a captured in the closure type m1. Since, a in m1 captures by copy, therefore a's value in m2 should be 1.

The standard goes on to say (again, emphasis mine):

if m1 captures the entity by reference, m2 captures the same entity captured by m1.

I believe "same entity" here refers to the entity captured by m1 via reference and that m2 shall also be a reference to the same entity if it's a capture by reference, or a copy of it if it's a capture by copy.

Therefore for b in m2 shall refer to the b defined outside both lambdas. The value of b in m2 then should be 1 as this should be equivalent to capture by copy.

Where am I going wrong? More specifically, when is b inside m2 initialised?

Aucun commentaire:

Enregistrer un commentaire