I was trying the differents tutorials in Boost.Asio documentation and tried to replace boost components with C++11 ones. However, I got an error using std::bind in Timer.5 - Synchronising handlers in multithreaded programs. Here is the code proposed:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
class printer { /* Not relevent here */ };
int main()
{
boost::asio::io_service io;
printer p(io);
boost::thread t(boost::bind(&boost::asio::io_service::run, &io));
io.run();
t.join();
return 0;
}
I tried to replace boost::thread
by std::thread
and boost::bind
by std::bind
. Here is my code:
#include <functional>
#include <iostream>
#include <thread>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
class printer { /* Not relevent here */ };
int main() {
boost::asio::io_service io;
printer p(io);
std::thread t(std::bind(&boost::asio::io_service::run, &io));
io.run();
t.join();
}
When compiling with GCC 4.7, I got this compile-time error:
g++ -std=c++0x main.cpp -lboost_system -lboost_date_time -lpthread
main.cpp: In function ‘int main()’:
main.cpp:52:60: erreur: no matching function for call to ‘bind(<unresolved overloaded function type>, boost::asio::io_service*)’
main.cpp:52:60: note: candidates are:
/usr/include/c++/4.6/functional:1444:5: note: template<class _Functor, class ... _ArgTypes> typename std::_Bind_helper::type std::bind(_Functor&&, _ArgTypes&& ...)
/usr/include/c++/4.6/functional:1471:5: note: template<class _Result, class _Functor, class ... _ArgTypes> typename std::_Bindres_helper::type std::bind(_Functor&&, _ArgTypes&& ...)
Where is this error comming from, taking into account that I did not use any boost::asio::placeholders
(as explain in this stackoverflow question Should std::bind be compatible with boost::asio?)?
It is safe to post handlers from within a handler for a single instance of an io_service according to the documentation.
Boost. Bind defines placeholders from _1 to _9. These placeholders tell boost::bind() to return a function object that expects as many parameters as the placeholder with the greatest number.
The boost::asio::io_service::run()
member function is overloaded: one version takes no argument while another version takes one argument. That is, taking the address of the of boost::asio::io_service::run
requires a context in which the compiler can directly deduce the signature of the function. However, std::bind()
isn't required to do deduction magic while it seems that boost::bind()
attempts to locate a matching overload i.e. it seems for its first argument type to be readily constrained (assuming the boost example indeed compiles).
The work-around this problem you can explicitly specify the type of the first argument to std::bind()
(it should also work with boost::bind()
) e.g. like this:
std::bind(static_cast<size_t (boost::asio::io_service::*)()>(&boost::asio::io_service::run), &io);
I haven't checked whether the standard makes any requirements but if it indeed doesn't do any requirements I would consider an implementation which does not go to heroics to deduce the argument type to be of better quality although it does less work: it requires that the user writes code which can compile unchanged on another compiler.
Just a quick note, in C++11 onwards you can just use lambdas to avoid all the faff and simplify the whole thing greatly. The old:
boost::thread t(boost::bind(&boost::asio::io_service::run, &io));
or the std::version:
std::thread t(boost::bind(static_cast<size_t (boost::asio::io_service::*)()>(&boost::asio::io_service::run), &io_service));
become just:
std::thread t([&io_service](){io_service.run();});
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