Невозможно скомпилировать с потоком, который использует функцию-член в том же классе - PullRequest
1 голос
/ 09 января 2020

Я пытаюсь создать поток, который вызывает функцию-член внутри того же класса.

Я видел несколько похожих вопросов, таких как этот .

Однако мой, похоже, не работает. Я получаю ошибку,

std::thread arguments must be invocable after conversion to rvalues

При такой настройке:

void MyClass::myFuncThread(
    const unsigned threadID,
    std::vector<myType*>& column,
    const unsigned x,
    const unsigned y) const
{
  // Each thread will write once to a single unique index of the vector, which should work 
  // despite vector not being thread-safe
  // Contents of this function omitted since it's not relevant to the error
}

void MyClass::myFunc(
    std::vector<myType*>& column,
    const unsigned x,
    const unsigned y) const
{
  column.resize(x, y);

  // Create a vector of threads
  std::vector<std::thread> threads;
  threads.resize(numThreads);

  // Launch all threads
  for (unsigned i = 0; i < threads.size(); i++)
    {
      threads[i] = std::thread(
          &MyClass::myFuncThread, this, i, column,
          x, y);
    }

  // Join all the threads
  for (unsigned i = 0; i < threads.size(); i++)
    {
      threads[i].join();
    }
}

Вот полная ошибка при попытке компиляции: (отредактировано с именами generi c)

/usr/include/c++/8/thread: In instantiation of ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (MyClass*)(unsigned int, std::vector<myType*>&, unsigned int, unsigned int) const; _Args = {const MyClass*, unsigned int&, std::vector<myType*>&, const unsigned int&, const unsigned int&}; <template-parameter-1-3> = void]’:
myclass.cpp:100:23:   required from here
/usr/include/c++/8/thread:120:17: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues
  static_assert( __is_invocable<typename decay<_Callable>::type,
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
           typename decay<_Args>::type...>::value,
           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Это может быть ссылка. Только std::vector должен быть ссылкой, остальные могут быть просто копиями. Мне все еще нужно что-то завернуть в std::ref() по какой-то причине? Или у меня просто синтаксис std::thread неправильный как-то? Нужно ли мне по каким-то причинам использовать «будущее» и asyn c?

1 Ответ

4 голосов
/ 09 января 2020

Это может быть связано со ссылкой.

Это так.

Нужно ли мне что-то еще обернуть в std :: ref () по какой-то причине? ?

Да. Вам нужно использовать std::ref.

Вокруг чего?

Вокруг column.

не будет оборачивать его с помощью std :: ref сделать ссылку на ссылку?

Не может быть std::reference_wrapper ссылки. Шаблон будет выведен как std::reference_wrapper<std::vector<myType*>>, что вам нужно.

Работает! Могу я спросить, зачем именно там нужен std :: ref ()?

Поскольку, согласно документации, std::thread делает копии своих аргументов (перемещая, если это возможно). В случае columns, которое является lvalue для вектора, будет сделана копия вектора. Копии передаются в функцию как значения. Неконстантные ссылки на lvalue (например, аргумент is) не привязываются к rvalue, поэтому программа плохо сформирована.

что она выполняет?

std::reference_wrapper - это копируемый объект, который внутренне поддерживает косвенность и неявно преобразует в lvalue упомянутого типа, что позволяет передавать его в ссылочные аргументы. Вместо того чтобы копировать указанный вектор, поток создаст копию эталонной оболочки.

Что вы подразумевали под шаблоном, выводимым здесь?

std::ref - это шаблон функции. Вам не нужно явно указывать его аргумент шаблона, потому что он может быть выведен из аргумента, который передается в него.

PS Будьте очень осторожны, чтобы поддерживать указанный вектор живым, по крайней мере, до тех пор, пока выполняется поток.

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