无法构造线程调用模板成员函数,该如何解决?
解决std::thread调用模板成员函数的参数绑定问题
问题根源
std::thread构造时会对所有传入的参数执行**值衰减(decay)**操作——简单说就是把左值转换成右值副本。而你的模板函数x声明的参数是T&(这里实例化为int&),左值引用无法绑定到衰减后的右值上,这就触发了编译器的静态断言错误。
解决方法
1. 用std::ref传递引用
通过std::ref包裹参数,让std::thread传递原变量的引用而非值副本,这样函数x的左值引用就能正确绑定:
#include <thread> #include <functional> // 需包含此头文件使用std::ref struct S { S() { std::thread t(&S::x<int>, this, std::ref(p)); t.detach(); } template<class T> void x(T& t) { // 可正常修改t,实际操作的是S对象的p成员 } int p; };
注意:因为线程被detach,必须保证p的生命周期覆盖线程运行全程——这里S对象只要不提前销毁,p就有效。
2. 修改模板函数的参数类型
如果不需要修改原变量,可将参数改为const T&(能绑定右值);或者直接传值T,让函数接收副本:
// 方案A:const引用 template<class T> void x(const T& t) { // 只能读取t,无法修改原变量 } // 方案B:传值 template<class T> void x(T t) { // 修改的是副本,不影响原变量p }
这两种方式都不需要修改线程构造的代码,原代码std::thread t(&S::x<int>, this, p);就能正常编译。
3. 使用指针传递参数
把模板函数的参数改成指针类型,线程构造时传递&p,绕开引用绑定的问题:
struct S { S() { std::thread t(&S::x<int>, this, &p); t.detach(); } template<class T> void x(T* t) { if (t) { // 通过指针操作原变量p *t = 100; } } int p; };
内容的提问来源于stack exchange,提问作者intrigued_66
相关产品推荐
相关产品推荐

