Конструктор потока std принимает функцию потока * Variadi c? - PullRequest
1 голос
/ 30 мая 2020

Я пытаюсь передать переменное количество функций обратного вызова (все с одинаковой подписью) в функцию потока. Я придумал следующий код

using namespace std;

void callback(int i)
{
    cout<<"thread "<<i<<" running"<<endl;
}

template<typename ...CallbackType>
void threadProc(int id, CallbackType ...callbackPack)
{
    auto callbacks = {callbackPack...};
    for(auto callback : callbacks)
    {
        callback(id);
    }
}

int main()
{
    thread t(threadProc<void(int)>, 1, callback);
    t.join();
    return 0;
}

Этот код не компилируется с

error: no matching function for call to ‘std::thread::thread(, int, void (&)(int))’
 thread t(threadProc<void(int)>, 1, callback);

Все будет работать нормально, если threadProc() не использует какой-либо пакет параметров. Есть ли правильный способ запустить поток с функцией Variadi c thread?

Ответы [ 2 ]

3 голосов
/ 30 мая 2020

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

thread t{threadProc<void(*)(int)>, 1, callback};

Здесь https://godbolt.org/z/Hzp9EP

1 голос
/ 30 мая 2020

В вашем коде все в порядке. Кажется, это просто ошибка в G CC, которая не имеет ничего общего с потоками. Минимальный тестовый пример, воспроизводящий ошибку:

template <typename... T>
void foo(T...) {}

int main()
{
    auto* pfoo = foo<void(int)>;

    return 0;
}

Кажется, G CC не нравится тот факт, что foo имеет параметр типа void(int). Тем не менее, правила языка ясны: это разрешено, и тип функции настраивается на соответствующий тип указателя функции, когда он появляется как тип параметра.

У других компиляторов, похоже, нет проблем с этим. См. https://godbolt.org/z/tgaV7B

В качестве обходного пути вы можете написать:

thread t(threadProc<void(*)(int)>, 1, callback);

Или:

thread t(threadProc<decltype(&callback)>, 1, callback);
...