Variadic average function in C++ The following code was inspired from a tutorial I found online:

#include &lt;cstdio&gt;
#include &lt;cstdarg&gt;

double average_function(const int num_elements, ...)
{
    va_list elements;
    double sum = 0.0;

    va_start(elements, num_elements);
    for(int i = 0; i &lt; num_elements; ++i) {
        sum += va_arg(elements, double);
    }
    va_end(elements);
    return sum / num_elements;
}

int main( int argc, char ** argv ) {

    printf("Average: %lf", average_function(5, 25.0, 35.7, 50.1, 127.6, 75.0));
    return 0;

}


I believe that the same can be done in many different ways. 

Is there a better way to do the same without having as first arguments of the function the number of elements we want to sum? For example having instead a function to compute the average that have in its input only the set of elements we want to take into account without a their length?
One possibility would be to use an std::initializer_list:

#include &lt;initializer_list&gt;
#include &lt;numeric&gt;
#include &lt;iostream&gt;

double average(std::initializer_list&lt;double&gt; input) { 
    double sum = std::accumulate(input.begin(), input.end(), 0.0);
    return sum / input.size();
}

int main() { 
     std::cout &lt;&lt; "Average: " &lt;&lt; average({1, 2, 3, 4, 5, 6, 7, 8});
}


You could have the function take (for example) a vector instead, and it'd still work pretty much the same way (because vector already has a constructor that takes an initializer_list). Either way works out pretty much the same way though.

If you want to use just a list of numbers rather than having to add the {} around the list to force it into an initializer_list you can add var-args template function to wrap the call.

template&lt;typename... Args&gt;
double average(Args... args)
{
    return average({args...});
}


Looking at your code, a few things nearly jump out. First and foremost, you're using a C-style variable parameter list. This is mostly frowned upon in C++ for a number of reasons such as lack of type-safety. For example, if you'd accidentally passed your 25.0 as just 25, it'd be passed as an int instead of a double, and the whole thing would break.

The second is similar: using printf to print out the result has exactly the same problem for exactly the same reason (printf also uses a C-style variable parameter list).

Third, related to those but technically a separate issue (since it's about values, not types) is the problem you've apparently already noticed: it requires you to count the number of parameters. If you make a mistake, you get bad results (and if you tell it you're passing more parameters than you really do, undefined behavior).

Simply put, although your code won't compile as-is with a C compiler, it's still basically C-style code. It does nothing to fit with (or take advantage of) anything in C++ that wasn't a part of C 20+ years ago. If used correctly, it works, but it's all too easy to use it incorrectly.