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

Viewed 65

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();
}
2 Answers

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.

std::thread's constructor has the form of

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

As you can see, the first argument is the function to run, and the rest are the arguments to be passed to it. If those don't match, you get some sort of compiler error

Related