I am trying to understand how to properly implement a function to calculate the mathematical sample mean, with two initial required characteristics:
1) using variadic arguments.
2) not using two functions to do the job, that is, not using a caller function and then a second function that actually does the calculation.
3) function should be as generic as possible
I am very aware that a pretty similar question has been already asked: Calculate the average of several values using a variadic-template function However, while the accepted answer to that question seems to have taught the OP how to do the small part he didn't know, it presents a code that is actually wrong and does not compile.
So, my own first attempt was along these lines:
template <class... Args>
double mean(const Args & ... args)
{
auto total = 0;
for (auto value : { ...args })
{
total += value;
}
return (double)total / sizeof...(args);
}
The problem here is that in the line auto total = 0;
the compile naturally can't automatically identify the type that object total
should have.
Then, my second attempt:
template <class T, class... Args>
T mean(const T &t, const Args & ... args)
{
T total = 0;
for (auto value : { args... })
{
total += value;
}
return (T)(total / sizeof...(args));
}
That version the following problem. It does not work if the caller calls the function with arguments of mixed type, like in mean(1, 2.5)
, where the first arguments is automatically detected as an int
and the second is detected as a double
.
I was able to solve that by doing the following:
template <class T, class... Args>
T mean(const T &t, const Args & ... args)
{
size_t argsSize = sizeof...(args);
T total = t;
T arg_array[] = { args... };
for (size_t i = 0; i< argsSize; i++)
{
total += (T)arg_array[i];
}
return (T)(total / argsSize) ;
}
This one works even when passed arguments are of different types (of course, provided that such types can be converted to T
). The problem now, however, is that the function only works with a minimum of two arguments. If it is called like in mean(3.14)
, while it should return 3.14, it actually raises an error because T arg_array[] = { args... }
can't be compiled because it is impossible to have a static array be created with size 0
. Sure, I could substitute it for a dynamic array, but that would make me have to do one memory allocation and one memory deallocation every time that the function is called - which is an unacceptable waste.
So, what would be the correct way to implement such a function that avoids the mentioned problems and that follows my two initial conditions?