c++ - 完美转发可变参数模板到标准线程

标签 c++ c++11 rvalue-reference stdthread perfect-forwarding

我正在尝试制作一种 std::thread 形式,它在线程中执行的代码周围放置一个包装器。不幸的是,由于我对右值和 Function 的理解不足,我无法编译它。我试图传递的模板化类型。这是我的代码:

#include <vector>
#include <thread>
#include <utility>

void Simple2(int a, int b) {}

template <typename Function, typename... Args>
void Wrapper(Function&& f, Args&&... a) {
  f(std::forward<Args>(a)...);
}

class Pool {
 public:
  template <typename Function, typename... Args>
  void Binder(Function&& f, Args&&... a) {
    std::thread t(Wrapper<Function, Args...>,
                  std::forward<Function>(f), std::forward<Args>(a)...);
  }
};

int main() {
  Wrapper(Simple2, 3, 4);       // Works

  Pool pool;
  pool.Binder(Simple2, 3, 4);   // Doesn't compile
}

这里看起来很重要的 Clang3.0 输出是:

/usr/include/c++/4.6/functional:1286:9: error: non-const lvalue reference to type 'void (int, int)' cannot bind to a value of unrelated type 'void (*)(int, int)'

note: in instantiation of function template specialization 'std::thread::thread<void (void (&)(int, int), int &&, int &&), void (&)(int, int), int, int>' requested here

我认为这暗示 Wrapper<Function, Args...> 之间不匹配和右值 f, a...被赋予 std::thread。

奇怪的是,如果我更改 std::forward<Function>(f),这会在 GCC4.9 和更新的 Clang 中编译至 std::ref(f) .

最佳答案

这是极少数情况之一,传递函数和传递函数指针之间的区别会有所不同。如果你这样做:

pool.Binder(&Simple2, 3, 4);  

它应该可以工作。或者,您可以让 Binder 将其参数衰减为函数指针:

class Pool {
 public:
  template <typename Function, typename... Args>
  void Binder(Function&& f, Args&&... a) {
    std::thread t(Wrapper<typename std::decay<Function>::type, Args...>,
                  std::forward<Function>(f), std::forward<Args>(a)...);
  }
};

在 C++14 中简化为:

class Pool {
 public:
  template <typename Function, typename... Args>
  void Binder(Function&& f, Args&&... a) {
    std::thread t(Wrapper<std::decay_t<Function>, Args...>,
                  std::forward<Function>(f), std::forward<Args>(a)...);
  }
};

关于c++ - 完美转发可变参数模板到标准线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27029048/

相关文章:

c++ - 需要大量计算,并且需要在耦合策略模式下的两个行为之间共享。应该在哪里完成并举行

c++ - 编写条件可选构造函数的最佳方法

c++ - 为什么不允许前向声明将是 typedef 的类?

c++ - 为什么 std::move() 没有 _Remove_reference 就不能工作?

指针的 C++ 运算符重载

c++ - C++ 中带有继承类的链表?

c++ - char和const char的区别

c++ - 什么终止将输入读入 int

c++ - 基于<chrono>改进一个定时器类

c++ - 右值引用和类设计