完美地将可变参数模板转发到标准线程
Perfect Forwarding Variadic Template to Standard Thread
我正在尝试制作一种 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...>
与 std::thread f, a...
给出的右值不匹配。
奇怪的是,如果我将std::forward<Function>(f)
更改为 std::ref(f)
,这将在 GCC4.9 和更新的 Clang 中编译。
这是传递函数和传递函数指针之间的差异产生差异的罕见情况之一。 如果您这样做:
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)...);
}
};
相关文章:
- 使用CMake检测支持的C++标准
- 如何理解C++标准N3337中的expr.const.cast子句8
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 编译标准库类型
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 正在折叠转发引用
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- 铸造标准::有没有回到原来的类型
- 标准 N3337 5.2.10 第 7 条中的C++"类型"是什么意思?
- this_thread::sleep_for和计时时钟之间的关系是否由C++11标准指定
- 标准库类型的赋值运算符的引用限定符
- 标准是否严格定义了该程序应该如何编译?
- 如何从Windows应用程序输出到标准?
- 常量转发引用给出错误 C2440:"正在初始化":无法从"常量标准::字符串"转换为"常量标准::字符串 &&"
- 使用标准::绑定在可变参数模板中完美转发引用
- 标准::<Func>呼叫时转发的效用
- C++11 标准::功能和完美的转发
- 合法地转发声明 C 标准库实体,但不C++标准库实体
- 如何转发标准::initializer_list<T>?
- 标准::绑定和完美转发