Reputation: 571
I'm new to variadic templates and recently came across it. I think I've not fully understood how it works in the background. I tried to write a variadic function min which returns the minimum of the arguments.
Here's the code:
#include <iostream>
template<typename T>
T min(T v) {
std::cout << "Base func: " << __PRETTY_FUNCTION__ << "\n";
return v;
}
template<typename T, typename... Args>
T min(T first, Args... args) {
std::cout << "Variadic func: " << __PRETTY_FUNCTION__ << "\n";
return first < min(args...) ? first : min(args...);
}
int main(){
std::cout << min(3,2,1,0) << std::endl;
return 0;
}
I used __PRETTY_FUNCTION__
to get more details of the instantiation of the functions and here's the output:
Variadic func: T min(T, Args ...) [with T = int; Args = {int, int, int}]
Variadic func: T min(T, Args ...) [with T = int; Args = {int, int}]
Variadic func: T min(T, Args ...) [with T = int; Args = {int}]
Base func: T min(T) [with T = int]
Base func: T min(T) [with T = int]
Variadic func: T min(T, Args ...) [with T = int; Args = {int}]
Base func: T min(T) [with T = int]
Base func: T min(T) [with T = int]
Variadic func: T min(T, Args ...) [with T = int; Args = {int, int}]
Variadic func: T min(T, Args ...) [with T = int; Args = {int}]
Base func: T min(T) [with T = int]
Base func: T min(T) [with T = int]
Variadic func: T min(T, Args ...) [with T = int; Args = {int}]
Base func: T min(T) [with T = int]
Base func: T min(T) [with T = int]
0
The code returns a correct output but I'm still fuzzy how functions are being called. Are all arguments are compared with each other? E.g. 3
will be compared with 2,1,0
, 2
will be compared with 1,0
and 1
will be compared with 0
? It'll be great if someone can give a solid reasoning to what exactly is happening?
Thanks
Upvotes: 0
Views: 169
Reputation: 10333
If you unroll the template calls and fix tbe double recursion by caching the result of the recurse value, it should look like this
And this is not meant to be c++, the c++ is the template code in the question, this is just a hand debug of passing 3 args
min (a, b, c)
First = a;
Tailmin = min (b, c);
if (first < Tailmin)
return first;
return Tailmin;
min (b, c)
First = b;
Tailmin = min (c);
if (first < Tailmin)
return first;
return Tailmin;
min (c)
// base stops recursion
return c
Upvotes: 1
Reputation: 5044
The call hierarchy is the following. The variadic function calls the "one less" function twice because first < min(args...) ? first : min(args...);
calls it once to compare it to first
(marked with // compare
) and a second time if that comparison is false
(marked with // value
).
min(3,2,1,0) // compare
-> min(2,1,0) // compare
-> min(1,0) // compare
->min(0) // compare
->min(0) // value
-> min(1,0) // value
->min(0) // compare
->min(0) // value
-> min(2,1,0) // value
-> min(1,0) // compare
->min(0) // compare
->min(0) // value
-> min(1,0) // value
->min(0) // compare
->min(0) // value
I hope this makes it more readable for you.
Upvotes: 3