Perfect Forwarding Variadic Template to Standard Thread
c++, c++11, perfect-forwarding, rvalue-reference, stdthread
Solution
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);
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)...);
}
};
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)...);
}
};
Problem
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 } ``` 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)' ``` and ``` note: in instantiation of function template specialization 'std::thread::thread<void (void (&)(int, int), int &&, int &&), void (&)(int, int), int, int>' requested here ``` Which I think is hinting at a mismatch between `Wrapper<Function, Args...>` and the rvalues `f, a...` being given to std::thread. Curiously this compiles in GCC4.9 and newer Clang if I change the `std::forward<Function>(f)` to `std::ref(f)`.