Reputation: 14869
My scheme is (more or less) the following:
asio_socket
is the abc with a single pure virtual method:
virtual void schedule(
boost::asio::ip::tcp::resolver::query &,
boost::asio::ip::tcp::resolver &,
boost::asio::io_service &
) = 0;
Another class asio_socket_http
inherits from it, and also inherits from another asio_helper
. Another class asio_socket_https
also follows the same scheme.
The asio_socket_http
implements the asio_async handlers, for an http connection.
Other classes (which define specific URI/URL-related operations) inherit either from asio_socket_http
or asio_socket_https
.
There exists a job scheduler:
void run_job(const std::shared_ptr<asio_socket> job);
Internally all it does is:
void run_job(const std::shared_ptr<asio_socket> job)
{
boost::asio::io_service io;
boost::asio::ip::tcp::resolver resolver(io);
job->schedule(query_, resolver, io);
io.run();
}
I want to add a deadline timer, which will deal with the async nature of asio:
void run_job(const std::shared_ptr<asio_socket> job)
{
boost::asio::io_service io;
boost::asio::ip::tcp::resolver resolver(io);
boost::asio::deadline_timer timer(io, boost::posix_time::seconds(3));
timer.async_wait(boost::bind(&asio_socket::schedule, *job));
// I also have to bind the 3 params: query_, resolver, io
io.run();
}
Doing so, I get template argument deduction/substitution failed:
and the actual error is:
‘void (rapp::cloud::asio_socket::*)(boost::asio::ip::basic_resolver<boost::asio::ip::tcp>::query&, boost::asio::ip::tcp::resolver&, boost::asio::io_service&) {aka void (rapp::cloud::asio_socket::*)(boost::asio::ip::basic_resolver_query<boost::asio::ip::tcp>&, boost::asio::ip::basic_resolver<boost::asio::ip::tcp>&, boost::asio::io_service&)}’ is not derived from ‘boost::type<R>’
timer.async_wait(boost::bind(&asio_socket::schedule, *job));
How can I bind the method schedule
of the (polymorphic) shared pointer job
, and also bind the parameters?
Trying:
timer.async_wait(boost::bind(&asio_socket::schedule, *job, _1, _2, _3)(&query_, &resolver, &io))
Complains about passing 5 arguments whilst the candidate expects 2 arguments.
My guess is that timer.async_wait
wants to bind a method to an object?
Upvotes: 0
Views: 368
Reputation: 69902
If you want to pass references into bind
you need to pass them as a reference_wapper<>
, which you can make with boost::ref(x)
or boost::cref(x)
.
If you don't, the bind
call will try to copy them, which of course can't work for a non-copyable asio
object.
Something like this should work:
timer.async_wait(boost::bind(&asio_socket::schedule,
job, // should bind to a shared_ptr just fine
boost::ref(query_),
boost:;ref(resolver),
boost::ref(io),
boost::placeholders::_1);
schedule will need the following signature:
(boost::asio::ip::tcp::resolver::query &,
boost::asio::ip::tcp::resolver &,
boost::asio::io_service &,
const boost::system::error_code& ec)
because async_wait demands that its handler is able to accept an error code argument as its 'first' unbound argument.
This is why you have to specify boost::placeholders::_1 - to marshal the 'first' argument in the binder (created by bind) to the fourth argument of your class's handler method.
Upvotes: 1