Search code examples
c++multithreadingvariadic-functions

How is 'std::thread' is able to determine the number of variadic arguments passed to the constructor


When calling the constructor of std::thread you pass a function and its desired arguments. How does std::thread determine the total number of arguments meant to be passed to the function?

#include <iostream>
#include <thread>

void task(int i, char c, bool b)
{
    return;
}

int main(int argc, char** argv)
{
    std::thread t(task, 10, 'c', true); // these 3 arguments
    t.join();
}

Solution

  • The std::thread constructor is implemented using a variadic template:

    template< class Function, class... Args >
    explicit thread( Function&& f, Args&&... args );
    

    Where:

    • Function is the type of callable object that will be invoked by the thread (whether that be a function, a lambda, a functor, etc).
    • Args is the list of types in the args variadic parameter.
    • f is the actual callable object that the thread will invoke.
    • args is the list of values that will be passed to f.

    std::thread is then able to forward args to f using parameter pack expansion, similar to f(args...);. The compiler itself, not std::thread, will expand args... to the actual values, ie: f(arg1, arg2, ..., argN).

    So, std::thread t(task, 10, 'c', true); will create a worker thread that make a call similar to to f(args...), which will have been expanded to task(10, 'c', true).

    Thus, the arguments you pass to the std::thread constructor must match the arguments of the f callable you pass in, otherwise the code fails to compile.