问题
I have a member function which I cannot unit test easily (it listens to sockets etc):
void MyClass::func()
{
listen();
send();
}
So I want to template it and then I can pass a mock object in my test:
template<class OBJECT>
void func(OBJECT& obj)
{
obj.listen();
obj.send();
}
and then I'd do:
func(*this);
The above compiles when I do a normal function call. However, when I spawn a thread and call it:
std::thread t1(&MyClass::func, this, *this);
I get compiler errors (see below) referring to decltype. Is there a way I can still achieve this?
/opt/gcc-8.2.0/lib/gcc/x86_64-unknown-linux/8.2.0/../../../../include/c++/8.2.0/thread:127:8: note: in instantiation of template class 'std::thread::_Invoker<std::tuple<void (MyClass::*)(MyClass &),
MyClass *, MyClass> >' requested here
__make_invoker(std::forward<_Callable>(__f),
However, the following works:
void MyClass::x()
{
func(*this);
}
std::thread t1(&MyClass::x, this);
回答1:
There are two issue in your code:
First, you cannot pass function templates to the std::thread constructor. You must explicitly specify what specialisation of the function template to use, which in this case, would be &MyClass::func<MyClass>
.
Second you are trying to pass a reference as an argument to the constructor of std::thread
. When the std::thread
constructor is called, the first argument is the function to run concurrently, and the others are the argument to the function. The other arguments are moved and then passed as argument to the function. This is fine if the argument is a pointer or a variable, but causes an issue if the function expects a non-const lvalue as an argument.
You can solve both issues by constructing std::thread
with lambdas:
std::thread t1([=]{
this->func(*this);
});
Conversely, you could use std::ref, a reference wrapper, in the std::thread constructor, and explicitly specify the function template specialisation:
#include<functional>
std::thread t1(&MyClass::func<MyClass>, this, std::ref(*this));
Personally, I much prefer constructing std::threads
with lambdas, as it is cleaner and less error prone.
来源:https://stackoverflow.com/questions/61376914/pass-this-as-argument-to-method-invoked-by-thread