Baruch
Baruch

Reputation: 21518

Why is the move constructor not called when moving in a lambda?

I am trying to compile the following code:

#include <utility>

struct C2 {
        C2() = default;
        C2(C2 const&) = delete;
        C2(C2&&) = default;
};

int main() {
        C2 p2;
        ([p2_1{ std::move(p2) }]() {
                auto p2_2 = std::move(p2_1); // <---
        })();
        return 0;
}

However, this doesn't compile and gives an error that the assignment to p2_2 is calling a deleted function, namely the copy constructor. Note that the move to p2_1 is fine. Why is this not using the move constructor?

Upvotes: 19

Views: 1288

Answers (1)

NathanOliver
NathanOliver

Reputation: 180720

The catch here is that the operator() of the anonymous class type the lambda represents is const by default. That means you can't move from p2_1 since the this of the lambda is const& in the function. What you need to do is use the mutable keyword like

int main() {
        C2 p2;
        ([p2_1{ std::move(p2) }]() mutable {
                auto p2_2 = std::move(p2_1); // <---
        })();
        return 0;
}

Which makes the function non const which in turn means you can mutate its members. This allows you to move p2_1 instead of trying to copy it.

Upvotes: 27

Related Questions