boost::thread和std::thread的区别

4

我有一个地方,使用boost::thread(例如使用boost::asio)可以使得事情工作。

  std::vector<boost::shared_ptr<boost::thread> > threads;
  for (std::size_t i = 0; i < io_services_.size(); ++i)
  {
    boost::shared_ptr<boost::thread> thread(new boost::thread(
          boost::bind(&boost::asio::io_service::run, io_services_[i])));
    threads.push_back(thread);
  }

如果我试图在std:thread中使用它,我会得到编译错误:
std::vector<std::thread> threads;
for (std::size_t i = 0; i < this->ioServices.size(); ++i)
{
    std::thread thread(&boost::asio::io_service::run, ioServices[i]); // compile error std::thread::thread : no overloaded function takes 2 arguments   

    threads.push_back(std::move(thread));
}

相关:https://dev59.com/Amkv5IYBdhLWcg3wfA8P - Bartek Banachewicz
你的编译错误中没有调用 boost::bind 吗? - Chad
@BartekBanachewicz 更新了标题,因为这涉及到 boost::thread 和 std::thread 之间的区别。 - Gmt
@Chad 谢谢你指出这个问题。已更新。 - Gmt
我仍然没有看到更新。您正在调用std::thread构造函数,并提供了两个它不期望的参数。如果您改为使用这两个参数构造一个boost::bind对象,我预计这将编译并正常工作。 - Chad
1个回答

2
理论上来说,两种方法都可以工作,因为std::thread具有可变参数构造函数,它会像使用std::bind一样调用其参数。问题似乎是,在我的实现(gcc 4.6.3)中,std::threadstd::bind都无法确定所需的run重载版本,导致编译错误。
然而,如果您使用boost::bind,这将起作用。因此我建议手动执行绑定:
std::vector<std::thread> threads;
for (std::size_t i = 0; i < this->ioServices.size(); ++i)
{
    std::thread thread(boost::bind(&boost::asio::io_service::run, ioServices[i])); 

    threads.push_back(std::move(thread));
}

编辑:看起来boost::bind之所以成功,是因为它有大量重载,根据提供的参数数量,在boost::bind的重载解析和模板替换期间,可以确定预期使用哪个boost::asio::io_service::run的重载。
然而,由于std::bindstd::thread依赖于可变参数模板,两个run的重载都是有效的,编译器无法解决使用哪一个。这种歧义导致无法确定结果,从而导致您看到的错误。
因此,另一种解决方案是:
std::vector<std::thread> threads;
typedef std::size_t (boost::asio::io_service::*signature_type)();
signature_type run_ptr = &boost::asio::io_service::run;

for (std::size_t i = 0; i < this->ioServices.size(); ++i)
{
    std::thread thread(run_ptr, ioServices[i]); 

    threads.push_back(std::move(thread));
}

我觉得这里有趣的是io_service :: run不是静态方法,而且不知道boot :: bind如何绑定到它... - Gmt
第一个提出的解决方案也可以。至少在VS2012下编译通过。 - Gmt
2
@Gmt: boost::bind(以及std::bind)能够使用成员函数指针来绑定到对象,并假设在绑定时间或调用时间提供的第一个参数是适当类型的引用或指针,然后使用该对象来调用成员函数。 - Dave S
@DaveS 没有考虑到“调用时间”的部分。我认为在成员函数的情况下,需要使用std::bind(&instance_member, objInstance, member_args..)。 - Ghita

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接