I am attempting to write a class which can store a movable (but non-copyable) callable object as a member variable. I understand that std::function must be copyable (although I don't understand the motivation behind this requirement), I'm looking for advice on if I can make this work some other way. see simplified code below which uses std::function and does not compile:
#include <iostream>
#include <memory>
#include <functional>
class Worker {
public:
using Callback = std::function<void()>;
template <typename Cb>
void DoAsyncWork(Cb&& cb) {
cb_ = std::forward<Cb>(cb);
// initiate some asynchronous code to be completed later
}
// after the asynchronous work has completed
void OnWorkComplete() {
cb_();
}
private:
Callback cb_;
};
int main() {
Worker worker;
auto x = std::make_unique<int>(123);
// i want to give ownership of x to the lambda
worker.DoAsyncWork([x = std::move(x)]() mutable { std::cout << *x << std::endl; });
}
This code does not compile with g++ 8.1.0:
g++ -std=c++17 main.cpp
In file included from /usr/local/include/c++/8.1.0/functional:59,
from async.cpp:3:
/usr/local/include/c++/8.1.0/bits/std_function.h: In instantiation of ‘static void std::_Function_base::_Base_manager<_Functor>::_M_clone(std::_Any_data&, const std::_Any_data&, std::false_type) [with _Functor = main()::<lambda()>; std::false_type = std::integral_constant<bool, false>]’:
/usr/local/include/c++/8.1.0/bits/std_function.h:208:16: required from ‘static bool std::_Function_base::_Base_manager<_Functor>::_M_manager(std::_Any_data&, const std::_Any_data&, std::_Manager_operation) [with _Functor = main()::<lambda()>]’
/usr/local/include/c++/8.1.0/bits/std_function.h:676:19: required from ‘std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor = main()::<lambda()>; <template-parameter-2-2> = void; <template-parameter-2-3> = void; _Res = void; _ArgTypes = {}]’
/usr/local/include/c++/8.1.0/bits/std_function.h:524:4: required from ‘std::function<_Res(_ArgTypes ...)>::_Requires<std::function<_Res(_ArgTypes ...)>::_Callable<typename std::decay<_U1>::type>, std::function<_Res(_ArgTypes ...)>&> std::function<_Res(_ArgTypes ...)>::operator=(_Functor&&) [with _Functor = main()::<lambda()>; _Res = void; _ArgTypes = {}; std::function<_Res(_ArgTypes ...)>::_Requires<std::function<_Res(_ArgTypes ...)>::_Callable<typename std::decay<_U1>::type>, std::function<_Res(_ArgTypes ...)>&> = std::function<void()>&]’
async.cpp:11:13: required from ‘void Worker::DoAsyncWork(Cb&&) [with Cb = main()::<lambda()>]’
async.cpp:29:86: required from here
/usr/local/include/c++/8.1.0/bits/std_function.h:173:6: error: use of deleted function ‘main()::<lambda()>::<lambda>(const main()::<lambda()>&)’
new _Functor(*__source._M_access<_Functor*>());
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
async.cpp:29:41: note: ‘main()::<lambda()>::<lambda>(const main()::<lambda()>&)’ is implicitly deleted because the default definition would be ill-formed:
worker.DoAsyncWork([x = std::move(x)]() mutable { std::cout << *x << std::endl; });
^
async.cpp:29:41: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = int; _Dp = std::default_delete<int>]’
In file included from /usr/local/include/c++/8.1.0/memory:80,
from async.cpp:2:
/usr/local/include/c++/8.1.0/bits/unique_ptr.h:394:7: note: declared here
unique_ptr(const unique_ptr&) = delete;
^~~~~~~~~~
Is there any way I can pass ownership of the unique_ptr
into the lambda and store it as a class member of Worker
? Thanks in advance