是否可以将重载方法传递给std :: thread

时间:2017-08-30 17:37:56

标签: c++ multithreading c++11

我是线程新手,我试图将重载方法传递给std :: thread,如下例所示

#include <iostream>    
#include <thread>    

int do_calculation(int x)    
{    
   std::cout<<x;    
}    

float do_calculation(float x)    
{    
   std::cout<<x;    
}    

int main()    
{    
   std::thread t1(do_calculation,20);    
   std::thread t2(do_calculation,200.0f);    
   return 0;    
}

但该程序没有编译并抛出错误 no matching function for call to 'std::thread::thread(<unresolved overloaded function type>, int)' std::thread t1(do_calculation,20);

有没有办法在线程中调用重载方法?

4 个答案:

答案 0 :(得分:8)

您需要转换函数来解决重载问题:

std::thread t1(static_cast<int(*)(int)>(do_calculation),20);    
std::thread t2(static_cast<float(*)(float)>(do_calculation),200.0f);  

此外,您需要joindetach您的帖子,以免您冒险前往std::terminate

t1.join();
t2.join();

Demo

答案 1 :(得分:7)

或者,您可以将调用包装在lambda中

std::thread t1([](int e) {do_calculation(e);}, 20);
std::thread t2([]() { do_calculation(200.0f); });

答案 2 :(得分:3)

如果您可以使用C ++ 14,那么作为转换的替代方法,您可以将函数调用包装在lambda中,即自动参数类型推导。这将允许重载解析和类型扣除为您工作

std::thread t1([](auto var){ do_calculation(var); },20);    
std::thread t2([](auto var){ do_calculation(var); },200.0f);  

答案 3 :(得分:1)

#define RETURNS( ... ) \
  noexcept(noexcept( __VA_ARGS__ )) \
  -> decltype( __VA_ARGS__ ) \
  { return __VA_ARGS__; }

#define OVERLOAD_SET( ... ) \
  struct { \
    template<class...Ts> \
    auto operator()(Ts&&...ts)const\
    RETURNS( __VA_ARGS__( std::forward<Ts>(ts)... ) )\
  }

现在我们可以做到:

static OVERLOAD_SET( do_calculation ) do_calculation_v;

do_calculation_v是一个对象,表示do_calculation的重载集。

int main() {    
  std::thread t1(do_calculation_v,20);    
  std::thread t2(do_calculation_v,200.0f);    
  return 0;    
}

中,我们可以使用lambdas执行此操作,而不需要命名对象:

#define OVERLOAD_SET( ... ) \
  [](auto&&...args) RETURNS( __VA_ARGS__( decltype(args)(args)... ) )

int main() {    
  std::thread t1(OVERLOAD_SET(do_calculation),20);    
  std::thread t2(OVERLOAD_SET(do_calculation),200.0f);    
}

有一个提案可以让你在没有宏的情况下更简单一点:

int main() {    
  std::thread t1([](auto...args)=>do_calculation(decltype(args)(args)...),20);    
  std::thread t2([](auto...args)=>do_calculation(decltype(args)(args)...),200.0f);    
}

备份到,如果我们不关心noexcept或返回值等,我们可以这样做:

int main() {    
  std::thread t1([]{do_calculation(20);});    
  std::thread t1([]{do_calculation(200.f);});    
}

涉及90%涉及的案件。如果您的值不是硬编码的并且复制起来很便宜,那么只需在[] lambda捕获列表中捕获它们。