C++ lambda capturing by copy of parent lambda's captured value

Viewed 358

Trying to compile the following code:

#include <functional>

void test() {

    int a = 5;

    std::function<void()> f = [a](){
        [a]()mutable{ // isn't it capture 'a' by copy???
            a = 13; // error: assignment of read-only variable 'a'
        }();
    };

}

gives the error: assignment of read-only variable 'a' error.

Changing the code by adding curly braces to a capturing:

#include <functional>

void test() {

    int a = 5;

    std::function<void()> f = [a](){
        [a{a}]()mutable{ // this explicitly copies a
            a = 13; // error: assignment of read-only variable ‘a’
        }();
    };

}

eliminates the compile error. I'm wondering why is it so? Isn't the first variant equivalent to the second?

This is when using g++ version 8.3.0 from Debian.

clang++ version 7.0.1 compiles it successfuly.

Bug in g++?

1 Answers

[C++11: 5.1.2/14]: An entity is captured by copy if it is implicitly captured and the capture-default is = or if it is explicitly captured with a capture that does not include an &. For each entity captured by copy, an unnamed non-static data member is declared in the closure type. The declaration order of these members is unspecified. The type of such a data member is the type of the corresponding captured entity if the entity is not a reference to an object, or the referenced type otherwise.

The type of a inside your mutable lambda is const int because it was captured by copy from a const int a of enclosing const lambda. Therefore, making both lambdas mutable solves this issue.

Related