This answer explains how to move-capture a variable within a lambda in C++14.
But once you've move-captured an un-copyable object (such as a std::unique_ptr
) within a lambda, you cannot copy the lambda itself.
This would be fine if you could move the lambda, but I get a compile error when trying to do so:
using namespace std;
class HasCallback
{
public:
void setCallback(std::function<void(void)>&& f)
{
callback = move(f);
}
std::function<void(void)> callback;
};
int main()
{
auto uniq = make_unique<std::string>("Blah blah blah");
HasCallback hc;
hc.setCallback(
[uniq = move(uniq)](void)
{
std::cout << *uniq << std::endl;
});
hc.callback();
}
This produces the following error with g++
(I've attempted to copy only the relevant line):
error: use of deleted function ‘main()::<lambda()>::<lambda>(const main()::<lambda()>&’
...implying, I think, that my attempt to move the lambda has failed.
clang++
gives a similar error.
I tried explicitly move
ing the lambda (even though it's a temporary value), but that did not help.
EDIT: The answers below adequately address the compile errors produced by the above code. For an alternate approach, simply release
the unique pointer's target value into a std::shared_ptr
, which can be copied. (I'm not writing this as an answer, because that would assume that this is an XY problem, but the underlying reason why unique_ptr
can't be used in a lambda that gets converted to a std::function
is important to understand.)
EDIT 2: Hilariously enough, I just realized auto_ptr
would actually do the right thing here (!), as far as I can tell. It acts essentially like unique_ptr
, but allows copy-construction in place of move-construction.
You can move the lambda, that's fine. That's not what your problem is though, you're trying to instantiate a std::function
with a noncopyable lambda. And the:
template< class F >
function( F f );
constructor of function
does:
5) Initializes the target with a copy of
f
.
This is because std::function
:
satisfies the requirements of CopyConstructible and CopyAssignable.
Since function
has to be copyable, everything you put into it must also be copyable. And a move-only lambda does not meet that requirement.