完美地将可变参数模板转发到标准线程 [英] Perfect Forwarding Variadic Template to Standard Thread
问题描述
我正在尝试形成一种std :: thread形式,该形式将包装器封装在该线程中执行的代码周围。不幸的是,由于我不太了解rvalues和我尝试传递的 Function
模板化类型,因此我无法编译它。这是我的代码:
I'm trying to make a form of std::thread that puts a wrapper around the code executed in the thread. Unfortunately I can't get it to compile due likely to my poor understanding of rvalues and the Function
templated type I'm trying to pass. Here's my code:
#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输出是:
The Clang3.0 output that seems important here is:
/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 ...> $ c $之间的不匹配c>和右值
f,给std :: thread一个a ...
。
Which I think is hinting at a mismatch between Wrapper<Function, Args...>
and the rvalues f, a...
being given to std::thread.
奇怪的是,它可以编译如果我将 std :: forward< Function>(f)
更改为 std :: ref(f),则在GCC4.9和更高版本的Clang中使用
。
Curiously this compiles in GCC4.9 and newer Clang if I change the std::forward<Function>(f)
to std::ref(f)
.
推荐答案
这是在少数情况下d传递函数和传递函数指针之间的区别。如果您这样做:
This is one of those rare cases where the difference between passing a function and passing a function pointer makes a difference. If you do:
pool.Binder(&Simple2, 3, 4);
它应该可以工作。或者,您也可以让 Binder
将其参数衰减为函数指针:
it should work. Or alternatively you can have Binder
decay its argument to a function pointer:
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中简化为:
which in C++14 simplifies to:
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)...);
}
};
这篇关于完美地将可变参数模板转发到标准线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!