Conventional variadic functions are messy and not type-safe, but in C++11 you can do this cleanly using variadic templates and (compile-time) recursion:
// Base case for recursion
template <typename T>
inline T sum(T n) {
return n;
}
// Recursive case
template <typename T, typename... Args>
inline T sum(T n, Args... args) {
return n + sum(args...);
}
Since it's a template, this'll work for any types that have an operator+
defined:
std::cout << sum(1, 2, 3) << std::endl; // Prints 6
std::cout << sum(3.14, 2.72) << std::endl; // Prints 5.86
However, because the return type of the recursive template function is taken from the first argument only, you can get suprising results if you mix different argument types in one call: sum(2.5, 2)
returns 4.5 as expected, but sum(2, 2.5)
returns 2 because the return type is int
, not double
. If you want to be fancy, you can use the new alternative function syntax to specify that the return type is whatever the natural type of n + sum(args...)
would be:
// Recursive case
template <typename T, typename... Args>
inline auto sum(T n, Args... args) -> decltype(n + sum(args...)) {
return n + sum(args...);
}
Now sum(2.5, 2)
and sum(2, 2.5)
both return 4.5.
If your actual logic is more complex than summation, and you don't want it inlined, you can use the inline template functions to put all the values into some sort of container (such as a std::vector
or std::array
) and pass that into the non-inline function to do the real work at the end.