【问题标题】:Does std thread constructor take variadic thread function?std 线程构造函数是否采用可变线程函数?
【发布时间】:2025-12-20 11:55:12
【问题描述】:

我正在尝试将可变计数的回调函数(所有相同的签名)传递给线程函数。我想出了以下代码

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() 没有使用任何参数包,一切都会正常工作。是否有正确的方法来启动具有可变线程功能的线程?

【问题讨论】:

标签: c++ multithreading variadic-templates stdthread


【解决方案1】:

你的第一个参数是一个函数指针,因此使用

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

这里https://godbolt.org/z/Hzp9EP

【讨论】:

    【解决方案2】:

    您的代码没有问题。这似乎只是 GCC 中的一个 bug,与线程无关。重现错误的最小测试用例是:

    template <typename... T>
    void foo(T...) {}
    
    int main()
    {
        auto* pfoo = foo<void(int)>;
    
        return 0;
    }
    

    GCC 似乎不喜欢foo 具有void(int) 类型的参数这一事实。然而语言的规则是明确的:这是允许的,并且函数类型在作为参数类型出现时被调整为对应的函数指针类型。

    其他编译器似乎没有问题。见https://godbolt.org/z/tgaV7B

    作为一种解决方法,您可以编写:

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

    或者:

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

    【讨论】: