Home > database >  Copy lambda which captures moved object
Copy lambda which captures moved object

Time:04-16

Why this code snippet does not compile?

#include <functional>
#include <iostream>
#include <memory>

int main()
{
    std::unique_ptr<int> uniq_ptr(new int{6});
    auto foo_a = [&uniq_ptr]{std::cout << *uniq_ptr << std::endl;};
    std::bind(foo_a)(); //works
    foo_a();            //works

    auto foo_b = [up = std::move(uniq_ptr)]()mutable{*up = 5; std::cout << *up << std::endl;};
    foo_b();           //works;

#ifdef CHOOSE_1
    auto foo_b1 = foo_b; //Surprised!  I think `up` could be copied.But the compiler complains: Error: use of deleted function 'main()::<lambda()>::<lambda>(const main()::<lambda()>&)'
#else
    std::bind(foo_b);    //Same error!
#endif
}

For auto foo_b = [up = std::move(uniq_ptr)]()mutable{//...}, I think foo_b could be copied since up a rvalue, and it could be copied by move constructor.

CodePudding user response:

[up = std::move(uniq_ptr)] just moves uniq_ptr to a member variable of the lambda.

std::bind will internally construct a copy of foo_b. Since foo_b contains a unique_ptr that is not copyable, foo_b itself is not copyable.

You should move foo_b into std::bind:

std::bind(std::move(foo_b));

Or move foo_b into foo_b1

auto foo_b1 = std::move(foo_b);
  • Related