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;
}

运行结果:
在这里插入图片描述

posted @ 2020-02-08 17:26  tomwillow  阅读(204)  评论(0编辑  收藏  举报