Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ : Function overloading vs Variadic function vs Variadic template vs default parameter [closed]

I have seen these questions:

  • Overload a method or use default values? c++
  • function overloading vs default argument in c++

but they do not consider variadic functions and variadic template .

Consider the problem of writing a function to find the average of either 2 or 3 positive numbers .

There are four ways we could implement this function:

  1. Using a default parameter:

    int average(int x , int y , int z=-1);
    
  2. Using function overloads:

    int average(int x , int y);
    int average(int x , int y , int z);
    
  3. Using a variadic function

    int average(int x,int y, ...);
    
  4. Using a variadic template

    int sum=0;
    int count=0;
    void average(){
       return;
    }
    template <class A, class ...B> void average(A argHead, B... argTail){
       sum =sum+argHead;
       count+=1;
       average(argTail...);
    }
    

What are the pros and cons of using one method over another ?

like image 789
sonus21 Avatar asked Feb 26 '26 01:02

sonus21


1 Answers

Given the constraints, namely average of either two or three positive numbers, the second option is the best.

The first option, with the optional argument, requires a test for positivity:

int average(int x,int y,int z=-1) {
    if (z<0) return (x+y)/2;
    else return (x+y+z)/3;
}

In term of providing the service of finding an average, that test is unnecessary. Further, it is brittle: it's reasonable to consider finding the average of numbers that could also be negative, and this solution is not compatible with that case.

The third option, the variadic function, is inappropriate because you will need to provide information in the call to indicate how many arguments are present, e.g. with a terminating negative number, or with the first parameter indicating the number of remaining arguments. This complicates the interface. Further, it is not type safe, and the burden then rests on the users of the function to be scrupulous in calling it only with ints — the compiler will not prohibit or warn about incorrect usage.

Using a variadic template is a good, general solution that extends easily to any number of parameters. Here though, we need only the two and three argument cases, and so it's overly complex for the application. If you were to use this though, you'd want to use a different implementation that did not require global variables. The following uses a namespace to hide some of the implementation details, and forces the use of int arguments by fixing the head type before the recursion:

namespace impl {
    int sum() { return 0; }

    template <typename... V>
    int sum(int a,V... rest) { return a+sum(rest...); }
}

template <typename... V>
int average(int a,V... rest) {
    return impl::sum(a,rest...)/(1+sizeof...(V));
}
like image 154
halfflat Avatar answered Feb 28 '26 20:02

halfflat



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!