Передайте * this как аргумент методу, вызываемому потоком - PullRequest
0 голосов
/ 23 апреля 2020

У меня есть функция-член, которую я не могу с легкостью выполнить модульным тестом (она слушает сокеты и т. Д. c):

void MyClass::func()
{
    listen();
    send();
}

Поэтому я хочу применить ее к шаблону, а затем я могу передать фиктивный объект в свой test:

template<class OBJECT>
void func(OBJECT& obj)
{
    obj.listen();
    obj.send();
}

, а затем я бы сделал:

func(*this);

Выше компилируется, когда я делаю нормальный вызов функции. Однако, когда я создаю поток и вызываю его:

std::thread t1(&MyClass::func, this, *this);

, я получаю ошибки компилятора (см. Ниже), относящиеся к decltype. Есть ли способ, которым я все еще могу достичь этого?

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

1 Ответ

2 голосов
/ 23 апреля 2020

В вашем коде есть две проблемы:

Во-первых, вы не можете передавать шаблоны функций в конструктор std :: thread. Вы должны явно указать, какую специализацию шаблона функции использовать, которая в этом случае будет &MyClass::func<MyClass>.

Во-вторых, вы пытаетесь передать ссылку в качестве аргумента конструктору std::thread. Когда вызывается конструктор std::thread, первый аргумент - это функция, выполняемая одновременно, а остальные - аргумент функции. Другие аргументы перемещаются и затем передаются в качестве аргумента функции. Это нормально, если аргумент является указателем или переменной, но вызывает проблему, если функция ожидает неконстантное lvalue в качестве аргумента.

Вы можете решить обе проблемы, создав std::thread с помощью лямбды:

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

И наоборот, вы можете использовать std :: ref, упаковщик ссылок, в конструкторе std :: thread и явно указать специализацию шаблона функции:

#include<functional>

std::thread t1(&MyClass::func<MyClass>, this, std::ref(*this));

Лично я Мы предпочитаем строить std::threads с лямбдами, так как он чище и менее подвержен ошибкам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...