I have the following pieces of C++14 code
boost::asio::io_service service_;
I want to submit pieces of work into the io_service
, using the following code that takes any function, it's input arguments and returns me a std::future
to the return value.
template <typename F, typename... Args>
auto enqueue(F &&f, Args &&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
typedef typename std::result_of<F(Args...)>::type rType;
auto task = std::make_shared<std::packaged_task<rType()>>(std::bind(std::forward<F>(f),
std::forward<Args>(args)...));
std::future<rType> res = task->get_future();
service_.post(task);
return res;
}
This was then called using
enqueue([] (int i) {
return i+1;
}, 100);
This doesnt seem to be working. I get an error saying that service_.post()
was not expecting this input.
xxxxxxxxxxxxxx:49:3: required from ‘std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> enqueue(F&&, Args&& ...) [with F = main()::<lambda()>::<lambda()>; Args = {int}; typename std::result_of<_Functor(_ArgTypes ...)>::type = int]’
xxxxxxxxxxxxxx:44:6: required from here
/usr/include/boost/asio/impl/io_service.hpp:102:3: error: static assertion failed: CompletionHandler type requirements not met
BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
^
/usr/include/boost/asio/impl/io_service.hpp:85:3: error: no match for call to ‘(std::shared_ptr<std::packaged_task<void()> >) ()’
BOOST_ASIO_COMPLETION_HANDLER_CHECK(CompletionHandler, handler) type_check;
^
As far as I understand the boost::asio
documentation, this can be done. Any ideas?
From the documentation for post()
:
handler
The handler to be called. The io_service will make a copy of the handler object as required. The function signature of the handler must be:
void handler();
You are passing in a std::shared_ptr<std::packaged_task<int()>>
. A shared_ptr
doesn't have operator()
defined. And packaged_task
unwrapped isn't copyable.
So in order to make this work, you'll have to make a shared_ptr<promise>
:
using R = std::result_of_t<F(Args&&...)>;
auto promise = std::make_shared<std::promise<R>>();
std::future<R> res = promise->get_future();
service.post([promise = std::move(promise),
f = std::forward<F>(f),
args = std::make_tuple(std::forward<Args>(args)...)]{
promise->set_value(std::experimental::apply(f, args));
});
return res;