将 *this 作为参数传递给线程调用的方法 [英] Pass *this as argument to method invoked by thread

查看:35
本文介绍了将 *this 作为参数传递给线程调用的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个无法轻松进行单元测试的成员函数(它侦听套接字等):

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

然后我会这样做:

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

我收到与 decltype 相关的编译器错误(见下文).我还有什么办法可以做到这一点吗?

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),

但是,以下有效:

void MyClass::x()
{
    func(*this);
}

std::thread t1(&MyClass::x, this);

推荐答案

您的代码中有两个问题:

There are two issue in your code:

首先,您不能将函数模板传递给 std::thread 构造函数.您必须明确指定要使用的函数模板的哪个特化,在这种情况下,将是 &MyClass::func<MyClass>.

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>.

其次,您试图将引用作为参数传递给 std::thread 的构造函数.当std::thread 构造函数被调用时,第一个参数是要并发运行的函数,其他参数是函数的参数.其他参数被移动,然后作为参数传递给函数.如果参数是指针或变量,这很好,但如果函数需要非常量左值作为参数,则会导致问题.

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.

您可以通过使用 lambdas 构造 std::thread 来解决这两个问题:

You can solve both issues by constructing std::thread with lambdas:

std::thread t1([=]{
    this->func(*this);
});

相反,您可以在 std::thread 构造函数中使用引用包装器 std::ref,并明确指定函数模板专业化:

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

就我个人而言,我更喜欢用 lambdas 构建 std::threads,因为它更简洁且不易出错.

Personally, I much prefer constructing std::threads with lambdas, as it is cleaner and less error prone.

这篇关于将 *this 作为参数传递给线程调用的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆