Pranav
Pranav

Reputation: 571

understanding variadic template function

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

Answers (2)

Glenn Teitelbaum
Glenn Teitelbaum

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

WorldSEnder
WorldSEnder

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

Related Questions