c++lambdabindmoveunique-ptr

pass std::unique_ptr to std::bind


if i pass simple int or string all is okay. but when i pass unique_ptr it moves inside bind object (bind_f) and i can't call bind_f();

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

using namespace std;

template <typename F, typename... Args>
void TestF(F&& fnc, Args&&... args) {
    auto bind_f = std::bind(std::move(fnc), std::move(args)...);
    bind_f(); // error: no match for call to '(std::_Bind<main()::
              // <lambda(std::unique_ptr<int>)>(std::unique_ptr<int>)>) ()'
              // [build]   383 |     bind_f();
              // [build]       |     ~~~~~~^~
}

int main() {

    std::unique_ptr<int> ptr = std::make_unique<int>(11);

    auto work = [](std::unique_ptr<int> val) {
        cout << *val << endl;
    };

    auto work2 = [](int val, std::string str) {
        cout << val << endl;
    };

    TestF(std::move(work2), 10, "ssdf"s);
    TestF(std::move(work), std::move(ptr));

    cout << "done" << endl;

}

Solution

  • This is because the return object of bind passes it's ordinary arguments as lvalue references to the bound function when called. It doesn't know that you only intend to call it once, and that you want the pointer to be moved.