I need to move a unique_ptr
to a std::function
closure. I'm using generalized lambda captures in C++14.
auto ptr = make_unique<Foo>();
// Works.
auto lambda = [p = move(ptr)] { };
// This does not compile.
std::function<void()> func = [p = move(ptr)] { };
It's trying to copy, rather than move, the lambda capture into the std::function
. The relevant error is:
copy constructor of '' is implicitly deleted because field '' has a deleted copy
constructor
std::function<void()> func = [p = move(ptr)] { };
The example here would make this seem to work.
Note that the answer here just repeats the example on isocpp.org.
I can move to a shared_ptr
as follows:
shared_ptr<Foo> s = move(ptr);
but that creates another issue, because I need to call a function that expects a unique_ptr
from within my lambda, and I can't convert a shared_ptr
back to a unique_ptr
.
Is it possible to capture a unique_ptr
in a std::function
?
std::function
is a type-erasure object that supports copying the object stored.
When you store a std::unique_ptr
in a lambda, that lambda does not support being copied.
So std::function
quite rightly complains. It is a type that can be copied, and when passed in something is works out how to copy it. "I cannot copy it" isn't a valid answer; all std::function
s can be copied.
There are two common approaches to solve this problem. First, you store the std::function
's state in a std::shared_ptr
of some kind. Second, you write or find a non-copying std::function
and use that instead.
More "modern" std::function
replacement libraries support a number of useful things:
I've personally had a need for every one of the above for various special purposes.
Then you'd use moveonly_function<void()>
when you don't need to copy the callable, and your code compiles.
However, this is probably too heavy for your needs right now.
template<class F>
auto make_shared_function( F&& f ) {
return
[pf = std::make_shared<std::decay_t<F>>(std::forward<F>(f))]
(auto&&...args)->decltype(auto)
{
return (*pf)( decltype(args)(args)... );
};
}
now whenever you run into this problem:
// This does not compile.
std::function<void()> func = make_shared_function([p = move(ptr)] { });
and the state of the callable object is now stored in a shared ptr.