Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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++?

like image 488
igagis Avatar asked Jul 09 '20 15:07

igagis


People also ask

Does lambda capture reference by value?

The mutable keyword is used so that the body of the lambda expression can modify its copies of the external variables x and y , which the lambda expression captures by value. Because the lambda expression captures the original variables x and y by value, their values remain 1 after the lambda executes.

What is capture in lambda function?

Captures default to const value. By default, variables are captured by const value . This means when the lambda is created, the lambda captures a constant copy of the outer scope variable, which means that the lambda is not allowed to modify them.

How do you capture a member variable in lambda?

To capture the member variables inside lambda function, capture the “this” pointer by value i.e. std::for_each(vec. begin(), vec. end(), [this](int element){ //.... }

What is capture clause in c++?

A capture clause of lambda definition is used to specify which variables are captured and whether they are captured by reference or by value. An empty capture closure [ ], indicates that no variables are used by lambda which means it can only access variables that are local to it.


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.

like image 132
alex_noname Avatar answered Oct 11 '22 09:10

alex_noname