我在Boost.Asio文档中尝试了不同的教程,并尝试用C ++ 11替换boost组件。但是,我在Timer.5 - Synchronising handlers in multithreaded programs中使用std :: bind时出错了。这是建议的代码:
#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;
}
我尝试将boost::thread
替换为std::thread
,将boost::bind
替换为std::bind
。这是我的代码:
#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();
}
使用GCC 4.7进行编译时,出现了编译时错误:
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&& ...)
此错误来自何处,考虑到我没有使用任何boost::asio::placeholders
(如此stackoverflow问题Should std::bind be compatible with boost::asio?中的解释)?
答案 0 :(得分:35)
boost::asio::io_service::run()
成员函数被重载:一个版本不带参数,而另一个版本带一个参数。也就是说,取boost::asio::io_service::run
的地址需要一个上下文,在该上下文中编译器可以直接推导出函数的签名。但是,std::bind()
不需要执行演绎魔法,而boost::bind()
似乎试图找到匹配的重载,即它的第一个参数类型似乎很容易被约束(假设增强示例确实编译)
解决这个问题,您可以明确指定std::bind()
的第一个参数的类型(它也适用于boost::bind()
),例如像这样:
std::bind(static_cast<size_t (boost::asio::io_service::*)()>(&boost::asio::io_service::run), &io);
我没有检查标准是否有任何要求,但如果它确实没有做任何要求,我会考虑一个实现,不去英雄主义推断参数类型是更好的质量,虽然它的工作量更少:它要求用户编写可以在另一个编译器上编译的代码。
答案 1 :(得分:12)
快速说明一下,在C ++ 11之后,你可以使用lambdas来避免所有的faff并大大简化整个事情。老人:
boost::thread t(boost::bind(&boost::asio::io_service::run, &io));
或std :: version:
std::thread t(boost::bind(static_cast<size_t (boost::asio::io_service::*)()>(&boost::asio::io_service::run), &io_service));
变得只是:
std::thread t([&io_service](){io_service.run();});
答案 2 :(得分:1)
这是一个巨大的PITA,所以谢谢Dietmar的暗示。对于那些使用boost :: bind的人,你的解决方案看起来像这样:
// create the io_service
boost::asio::io_service io_service;
// assign some work to asio before starting
{
io_service.post(&some_work); // just for example
....
}
boost::thread t(boost::bind(static_cast<size_t (boost::asio::io_service::*)()>(&boost::asio::io_service::run), &io_service));
// work should be executed in a new thread
t.join()
return;
答案 3 :(得分:0)
由于您已经在使用C ++ 11:lambdas可能是std :: bind的替代品,例如std :: thread t(&amp; io {io.run();}); 。这完全避免了重载决策。
要获得正确的输出,解决方案(在asio standalone或boost :: asio中)是:
asio::io_service io;
auto ptrToIoService = &io;
printer p(io);
//asio::thread t(std::bind(&asio::io_service::run, &io));
//asio::thread t([&io]() {io.run();});
asio::thread t([ptrToIoService] () { ptrToIoService->run();});
参见&#34;有效的现代C ++&#34;在&#34;项目31下避免默认捕获模式。&#34;