使用线程可变参数模板构造函数时发生错误
An error occur when using a thread variadic template constractor
void f(vector<int>& v){
for(const auto& x:v) cout << x;
}
class F{
private:
vector<int> v;
public:
F(vector<int>& vc):v{vc}{}
void operator()(){
for(const auto& x:v) cout << x;
}
};
int main()
{
vector<int> some_vec{3,5,77,32,1};
vector<int> vec{66,8,90,45,777};
thread t1{f,some_vec};
thread t2{F(vec)};
t1.join();
t2.join();
cout << '\n';
}
发生错误“'class std::result_of< void (*(std::vector))(std::vector&)>' 中没有名为 'type' 的类型
如果f
中的参数向量声明为const
、void f(const vector<int>& v)
,则错误消失。
另一方面,带有函数对象 F
的代码工作得很好。
来自 Bjarne Stroustrup 的代码——C++ 编程语言 5.3.2 传递参数
std::thread
存储传递给其构造函数的参数的副本,然后使用这些副本的右值作为处理程序的参数。也就是说,函数 f
不能用 std::vector
的右值调用,因为它需要一个非常量左值引用。即使您将其更改为 const 左值引用,它也是实际传递给 t1
的构造函数的内容的副本。
相反,class F
有一个隐式定义的复制构造函数,它的函数调用运算符不需要参数,因此不会出错。 (并且 F
本身是在传递给线程的构造函数之前构造的)。
如果您希望函数 f
在 some_vec
实例上运行,您必须使用引用包装器对其进行包装:
#include <functional>
std::thread t1{f, std::ref(some_vec)};
// ~~~~~~~^
void f(vector<int>& v){
for(const auto& x:v) cout << x;
}
class F{
private:
vector<int> v;
public:
F(vector<int>& vc):v{vc}{}
void operator()(){
for(const auto& x:v) cout << x;
}
};
int main()
{
vector<int> some_vec{3,5,77,32,1};
vector<int> vec{66,8,90,45,777};
thread t1{f,some_vec};
thread t2{F(vec)};
t1.join();
t2.join();
cout << '\n';
}
发生错误“'class std::result_of< void (*(std::vector))(std::vector&)>' 中没有名为 'type' 的类型
如果f
中的参数向量声明为const
、void f(const vector<int>& v)
,则错误消失。
另一方面,带有函数对象 F
的代码工作得很好。
来自 Bjarne Stroustrup 的代码——C++ 编程语言 5.3.2 传递参数
std::thread
存储传递给其构造函数的参数的副本,然后使用这些副本的右值作为处理程序的参数。也就是说,函数 f
不能用 std::vector
的右值调用,因为它需要一个非常量左值引用。即使您将其更改为 const 左值引用,它也是实际传递给 t1
的构造函数的内容的副本。
相反,class F
有一个隐式定义的复制构造函数,它的函数调用运算符不需要参数,因此不会出错。 (并且 F
本身是在传递给线程的构造函数之前构造的)。
如果您希望函数 f
在 some_vec
实例上运行,您必须使用引用包装器对其进行包装:
#include <functional>
std::thread t1{f, std::ref(some_vec)};
// ~~~~~~~^