2

I'm trying to std::bind a std::move on a std::unique_ptr. The resulting function object seems to be immutable, so it would be impossible to perform the move when the functor is invoked.

I suspect this is because of the same reason why lambdas are immutable by default - invoking them should do the same thing every time. However there are cases where they need to be mutable, which is why we have the mutable keyword.

void foo(std::unique_ptr<int>&& ptr)
{
    cout << *ptr << endl;
}

int main()
{
    std::unique_ptr<int> ptr = std::make_unique<int>(123);
    std::bind(foo, std::move(ptr))();             // Doesn't compile
    [&ptr]() { foo(std::move(ptr)); }();          // Equivalent, doesn't compile
    [&ptr]() mutable { foo(std::move(ptr)); }();  // Compiles
    return 0;
}

Instad of using bind I could wrap a function call in a mutable lambda. However at least to me personally bind looks much cleaner and simpler in this case.

I understand that invoking the mutable lambda twice would lead to undefined behavior, because I would be moving again from an already moved-from pointer. But in my case I know the functor will only be called once.

Is there a way I could use std::bind to do this? Is there a bind_mutable of sorts? If not, how should I go about writing it myself?

Gediminas Masaitis
  • 3,172
  • 14
  • 35
  • 2
    Your claim is wrong, both lambda works: [Demo](http://coliru.stacked-crooked.com/a/b21ee8e7d660955b). What you would need for bind would be a `rvalue_refence_wrapper`. See [is-there-a-reference-wrapper-for-rvalue-references](https://stackoverflow.com/questions/5126219/is-there-a-reference-wrapper-for-rvalue-references). – Jarod42 Oct 27 '17 at 09:50
  • Are you actually stuck in [tag:C++11], or does your compiler have some [tag:C++14] features? Because the need for `bind` here is basically gone in [tag:C++14]. – Yakk - Adam Nevraumont Oct 27 '17 at 14:13

1 Answers1

2

However at least to me personally bind looks much cleaner and simpler in this case.

Do not use std::bind in C++11. Use lambdas instead. std::bind has several issues excellently explained in this talk by Stephan T. Lavavej “functional: What's New, And Proper Usage".

screenshot from talk

It might look simpler and cleaner in this case, but it's not recommended.

Writing...

[&ptr]{ foo(std::move(ptr)); }(); 

...is the proper way of solving this problem.

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416