С++ 11 Инициализация потока с помощью функций-членов, компилирующих ошибку
Я только начинаю использовать потоки С++ 11, и я боролся с (возможно, глупой) ошибкой.
Это моя примерная программа:
#include <iostream>
#include <thread>
#include <future>
using namespace std;
class A {
public:
A() {
cout << "A constructor\n";
}
void foo() {
cout << "I'm foo() and I greet you.\n";
}
static void foo2() {
cout << "I'm foo2() and I am static!\n";
}
void operator()() {
cout << "I'm the operator(). Hi there!\n";
}
};
void hello1() {
cout << "Hello from outside class A\n";
}
int main() {
A obj;
thread t1(hello1); // it works
thread t2(A::foo2); // it works
thread t3(obj.foo); // error
thread t4(obj); // it works
t1.join();
t2.join();
t3.join();
t4.join();
return 0;
}
Можно ли запустить поток из чистой функции-члена? Если это не так, как я могу обернуть мою функцию foo из объекта obj, чтобы иметь возможность создать такой поток?
Спасибо заранее!
Это компиляция:
thread_test.cpp: В функции 'int main(): thread_test.cpp: 32: 22: error: нет соответствующей функции для вызова 'std:: thread:: thread()
thread_test.cpp: 32: 22: примечание: кандидаты:
/usr/include/С++/4.6/thread: 133: 7: note: std:: thread:: thread (_Callable & &, _Args & &...) [с _Callable = void (A:: *)(), _Args = {}]
/usr/include/С++/4.6/thread: 133: 7: note: неизвестное преобразование для аргумента 1 от 'до' void (A:: * & &)()
/usr/include/С++/4.6/thread: 128: 5: note: std:: thread:: thread (std:: thread & &)
/usr/include/С++/4.6/thread: 128: 5: note: неизвестное преобразование для аргумента 1 из 'в' std:: thread &&
/usr/include/С++/4.6/thread: 124: 5: note: std:: thread:: thread()
/usr/include/С++/4.6/thread: 124: 5: примечание: кандидат ожидает 0 аргументов, 1 предоставлен
Ответы
Ответ 1
Вам нужен объект с вызовом без параметров, поэтому
thread t3(&A::foo, &obj);
должен сделать трюк. Это приводит к созданию вызываемого объекта, который вызывает A::foo
на obj
.
Причина в том, что нестатическая функция-член из A
принимает неявный первый параметр типа (возможно, cv) A*
. Когда вы вызываете obj.foo()
, вы фактически вызываете A::foo(&obj)
. Как только вы это знаете, вышеупомянутое заклинание имеет смысл.