I was reading about variadic templates and I came across this example. The book mentions that to end the recursion process, the function print()
is used. I really can't understand its use. Why does the author use this empty print()
function?
void print () // can't get why this function is used
{
}
template <typename T, typename... Types>
void print (const T& firstArg, const Types&... args)
{
std::cout << firstArg << std::endl; // print first argument
print(args...); // call print() for remaining arguments
}
With the variadic templates feature, you can define class or function templates that have any number (including zero) of parameters. To achieve this goal, this feature introduces a kind of parameter called parameter pack to represent a list of zero or more parameters for templates.
Variadic functions are functions that can take a variable number of arguments. In C programming, a variadic function adds flexibility to the program. It takes one fixed argument and then any number of arguments can be passed.
Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration. However, variadic templates help to overcome this issue.
variadic (not comparable) (computing, mathematics, linguistics) Taking a variable number of arguments; especially, taking arbitrarily many arguments.
A variadic expression can capture 0 arguments or more.
Take for example the call print(1)
. Then T
captures int
and Types = {}
- it captures no arguments. Thus the call print(args...);
expands to print();
, which is why you need a base case.
You don't need the recursion at all. I always use the following debuglog
function in my code (modified for your needs):
template<typename F, typename ... Args>
void
print(const F& first, const Args&... args) // At least one argument
{
std::cout << first << std::endl;
int sink[] =
{ 0, ((void)(std::cout << args << std::endl), 0)... };
(void) sink;
}
Because this variadic function takes at least one argument, you are free to use print(void)
for whatever you like now.
It is recursive because the variadic part of the template is reduced each call, for example a call would recursively look like this
print(1, 2, 3, 4, 5) // firstArg == 1
// ...args == 2,3,4,5
print(2, 3, 4, 5) // firstArg == 2
// ...args == 3,4,5
print(3, 4, 5) // firstArg == 3
// ...args == 4,5
print(4, 5) // firstArg == 4
// ...args == 5
print(5) // firstArg == 5
// ...args == {}
print()
The print()
is necessary as a base case for when the variadic list is empty.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With