C++中thread调用“带mutex的类”的成员函数报错C2661:std::tuple解决方法
今天在做LeetCode的1114题《按序打印》,想在本地调试,写了如下代码:
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
using namespace std;
class Foo {
private:
mutex m;
public:
Foo() {
}
void first(function<void()> printFirst) {
// printFirst() outputs "first". Do not change or remove this line.
printFirst();
}
void second(function<void()> printSecond) {
// printSecond() outputs "second". Do not change or remove this line.
printSecond();
}
void third(function<void()> printThird) {
// printThird() outputs "third". Do not change or remove this line.
printThird();
}
};
int main()
{
//
function<void()> fun[3];
fun[0] = []() {printf("1"); };
fun[1] = []() {printf("2"); };
fun[2] = []() {printf("3"); };
vector<thread> vect;
vector<int> vec{ 2,1,3 };
Foo foo;
using Func = void(Foo::*)(function<void()>);
vector<Func> pmemfunc{ &Foo::first,&Foo::second,&Foo::third };
for (auto i : vec)
{
vect.push_back(thread(pmemfunc[i-1],foo,fun[i-1]));
}
for (auto& t : vect)
t.join();
system("pause");
return 0;
}
vect中插入3个线程对象,线程中调用类成员函数,之后进行join。题目所给的Foo类,只要加上一个mutex成员,编译就不通过,报错:
C2661 “std::tuple<void (__thiscall
Foo:: * )(std::function<void (void)>),Foo,std::function<void
(void)>>::tuple”: 没有重载函数接受 3 个参数 console_temp C:\Program Files
(x86)\Microsoft Visual
Studio\2019\Community\VC\Tools\MSVC\14.23.28105\include\memory 2057
之后参考了 https://stackoverrun.com/cn/q/12697417 。意思是说创建thread时,传入的类对象会触发拷贝动作,而mutex是不可拷贝对象,所以报错。把foo改为std::ref(foo)后,编译通过。
顺带给出这道题的一个解法:
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
using namespace std;
class Foo {
private:
mutex m;
condition_variable cv;
bool b1;
bool b2;
public:
Foo() {
b1 = false;
b2 = false;
}
void first(function<void()> printFirst) {
// printFirst() outputs "first". Do not change or remove this line.
unique_lock<mutex> ul(m);
printFirst();
b1 = true;
cv.notify_all();
}
void second(function<void()> printSecond) {
// printSecond() outputs "second". Do not change or remove this line.
unique_lock<mutex> ul(m);
cv.wait(ul, [&]() {return b1; });
printSecond();
b2 = true;
cv.notify_all();
}
void third(function<void()> printThird) {
// printThird() outputs "third". Do not change or remove this line.
unique_lock<mutex> ul(m);
cv.wait(ul, [this]() {return b2; });
printThird();
}
};
int main()
{
function<void()> fun[3];
fun[0] = []() {printf("1"); };
fun[1] = []() {printf("2"); };
fun[2] = []() {printf("3"); };
vector<thread> vect;
vector<int> vec{ 2,1,3 };
Foo foo;
using Func = void(Foo::*)(function<void()>);
vector<Func> pmemfunc{ &Foo::first,&Foo::second,&Foo::third };
for (auto i : vec)
{
vect.push_back(thread(pmemfunc[i-1],ref(foo),fun[i-1]));
}
for (auto& t : vect)
t.join();
system("pause");
return 0;
}
运行结果: