Vélimir
Vélimir

Reputation: 421

Lambda function returning lvalue from higher scope

int main() {
    int x;
    auto& getx = [&]() {
        return x;
    }
    
    getx() = 1;
}

This doesn't seem possible, as it gives me:

error: cannot bind non-const lvalue reference of type 'main()::<lambda()>&' to an rvalue of type 'main()::<lambda()>'|

Why ? and how to do it

Upvotes: 1

Views: 523

Answers (2)

NathanOliver
NathanOliver

Reputation: 180500

A lambda expression creates a temporary object (called a closure) of an unknown class type. Temporary objects can't be assigned to non-const references. That means you need

auto&& getx = [&]() {
    return x;
}

so that you get an rvalue reference to the closure, or

auto getx = [&]() {
    return x;
}

so you just get the closure.

That will get the code to compile, but still needs one more bit to make getx's return value to be a reference to x. To do that you need to add

auto getx = [&]() -> int& {
    return x;
}

// or

auto getx = [&]() -> auto& {
    return x;
}

// or

auto getx = [&]() -> decltype(auto) {
    return x;
};

Also note that main must always return an int. You should turn up your compiler warning level so that it errors out if you try and use void main.

Upvotes: 3

rafix07
rafix07

Reputation: 20918

You have to specify that lambda returns reference to int - int&, and call closure by ():

auto& getx = [&]() -> int& { // -> int& added
    return x;
}();                         // () added

Temporary value cannot be bound to lvalue reference. If you want to make getx to be as a reference to x variable, you have to return reference from your lambda.

Upvotes: 2

Related Questions