C++ 为什么可以';t std::bind和boost::bind在这个boost.Asio教程中可以互换使用
我尝试了Boost.Asio文档中的不同教程,并尝试用C++11替换Boost组件。但是,我在使用std::bind-in时出错。建议的守则如下:C++ 为什么可以';t std::bind和boost::bind在这个boost.Asio教程中可以互换使用,c++,boost,c++11,boost-asio,boost-bind,C++,Boost,C++11,Boost Asio,Boost Bind,我尝试了Boost.Asio文档中的不同教程,并尝试用C++11替换Boost组件。但是,我在使用std::bind-in时出错。建议的守则如下: #include <iostream> #include <boost/asio.hpp> #include <boost/thread/thread.hpp> #include <boost/bind.hpp> #include <boost/date_time/posix_time/posix
#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;
}
使用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&& ...)
g++-std=c++0x main.cpp-lboost\u系统-lboost\u日期\u时间-lpthread
main.cpp:在函数“int main()”中:
main.cpp:52:60:erreur:bind(,boost::asio::io_service*)调用没有匹配的函数
main.cpp:52:60:注:候选人为:
/usr/include/c++/4.6/functional:1444:5:注意:模板类型名称std::_Bind_helper::type std::Bind(_Functor&,_ArgTypes&&…)
/usr/include/c++/4.6/functional:1471:5:注意:模板类型名称std::_Bindres\u helper::type std::bind(_Functor&,_ArgTypes&&…)
考虑到我没有使用任何
boost::asio::占位符
(如stackoverflow问题中所解释的)这个boost::asio::io_service::run()
成员函数重载:一个版本不带参数,而另一个版本带一个参数。也就是说,获取ofboost::asio::io_service::run
的地址需要一个上下文,在该上下文中编译器可以直接推断函数的签名。然而,std::bind()
不需要执行演绎魔术,而boost::bind()
似乎试图找到匹配的重载,即它的第一个参数类型似乎很容易受到约束(假设boost示例确实编译)
解决此问题的方法您可以显式指定std::bind()
的第一个参数的类型(它也应该与boost::bind()
一起使用),例如:
std::bind(static_cast<size_t (boost::asio::io_service::*)()>(&boost::asio::io_service::run), &io);
// 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;
std::bind(static\u cast(&boost::asio::io\u service::run),&io);
我没有检查标准是否有任何要求,但是如果它确实没有任何要求,我会考虑一个执行<强>不/强>的实现,去英雄,推断参数类型是更好的质量,尽管它的工作量较小:它要求用户编写可以在另一个程序上编译不变的代码。编译器。
这是一个需要解决的巨大问题,因此感谢迪特玛的提示。对于使用boost::bind的用户,您的解决方案如下所示:std::bind(static_cast<size_t (boost::asio::io_service::*)()>(&boost::asio::io_service::run), &io);
// 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;
//创建io\U服务
boost::asio::io_服务io_服务;
//开始前,为asio分配一些工作
{
io_service.post(&some_work);//仅举个例子
....
}
boost::线程t(boost::bind(static_cast(&boost::asio::io_service::run),&io_service));
//工作应该在新线程中执行
t、 加入
返回;
请注意,在C++11以后的版本中,您可以使用lambdas来避免所有的错误,并大大简化整个过程。老一辈:
boost::threadt(boost::bind(&boost::asio::io_service::run,&io));
或std::版本:
std::threadt(boost::bind(static_cast(&boost::asio::io_service::run),&io_service));
变得公正:
std::线程t([&io_服务](){io_服务.run();});
因为您已经在使用C++11:lambdas可能是std::bind的替代品,例如std::thread t(&io{io.run();});。这就完全避免了重载解析 要获得正确的输出,解决方案(在asio standalone或boost::asio中)是:
请参阅“第31项避免默认捕获模式”下的“有效的现代C++”。可能的重复:请参阅)。由于您已经在使用C++11:lambdas可以替代
std::bind
,例如,std::thread t([&io](){io.run();})代码>。这完全避免了过载解决方案。只是更好!通常,您希望将该线程放入向量中。但是作为lambda编写的向量是不可移动的,因此需要使用threadPool.emplace_back(std::move(t))