问题
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
}
回答1:
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.
回答2:
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.
回答3:
Consider a call to the template function with a single argument.
print(1);
firstArg
would bind to the 1
(T = int
), and Types...
would bind to nothing. A variadic argument pack is zero or more arguments.
Thus, in this call:
print(args...);
args...
is an empty parameter pack. So it expands into:
print();
Since your function template matches any call to print with one or more arguments, you need a separate function to handle zero arguments. Which in this case is the trivial function:
void print () { }
回答4:
Assume the following code:
int a, b, c;
print(a, b, c);
The compiler will implicitly create the following code:
print(const int& firstArg)
{
std::cout << firstArg << std::endl; // print first argument
print(); // call print() for remaining arguments
}
print(const int& firstArg, const int& arg2)
{
std::cout << firstArg << std::endl; // print first argument
print(arg2); // call print() for remaining arguments
}
print(const int& firstArg, const int& arg2, const int& arg3)
{
std::cout << firstArg << std::endl; // print first argument
print(arg2, arg3); // call print() for remaining arguments
}
as you can see in the version with only one argument, the compiler will call a "print" method with no arguments. Since the variadic print function ALWAYS requires at least one parameter this will not match...
来源:https://stackoverflow.com/questions/30937379/cant-understand-variadic-templates-in-c