I want to move and call a boost::packaged_task inside a lambda.
However, I can't figure out an elegant solution.
e.g. This won't compile.
template<typename Func>
auto begin_invoke(Func&& func) -> boost::unique_future<decltype(func())> // noexcept
{
typedef boost::packaged_task<decltype(func())> task_type;
auto task = task_type(std::forward<Func>(func));
auto future = task.get_future();
execution_queue_.try_push([=]
{
try{task();}
catch(boost::task_already_started&){}
});
return std::move(future);
}
int _tmain(int argc, _TCHAR* argv[])
{
executor ex;
ex.begin_invoke([]{std::cout << "Hello world!";});
//error C3848: expression having type 'const boost::packaged_task<R>' would lose some const-volatile qualifiers in order to call 'void boost::packaged_task<R>::operator ()(void)'
// with
// [
// R=void
// ]
return 0;
}
My rather ugly solution:
struct task_adaptor_t
{
// copy-constructor acts as move constructor
task_adaptor_t(const task_adaptor_t& other) : task(std::move(other.task)){}
task_adaptor_t(task_type&& task) : task(std::move(task)){}
void operator()() const { task(); }
mutable task_type task;
} task_adaptor(std::move(task));
execution_queue_.try_push([=]
{
try{task_adaptor();}
catch(boost::task_already_started&){}
});
What is the "proper" way to move a packaged_task into a lambda which calls it?
With a proper implementation of std::bind (or something equivalent with respect to move-enabled types) you should be able to combine bind and a C++0x lambda like this:
task_type task (std::forward<Func>(func));
auto future = task.get_future();
execution_queue_.try_push(std::bind([](task_type const& task)
{
try{task();}
catch(boost::task_already_started&){}
},std::move(task)));
return future;
btw: You don't need a std::move around future because future is a local object. As such, it's already subject to potential copy elision and if the compiler is not able to do that elision it has to move construct the return value from 'future'. The explicit use of std::move in this case may actually inhibit a copy/move elision.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With