# How to sum variadic arguments passed in to a variadic macro?

• A+
Category：Languages

I want a program that defines a macro that can count the number of arguments and pass them to a function `sum` which sums the arguments' values and returns the total. I managed to do it on GCC but I want to achieve it on Visual C++ 14.

``#include "stdafx.h" #include <iostream> #include <cstdarg>   #define ELEVENTH_ARGUMENT(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, ...) a11 #define COUNT_ARGUMENTS(...) ELEVENTH_ARGUMENT(dummy, ## __VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)  #define SUM(...) sum(ELEVENTH_ARGUMENT(dummy, ## __VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))   int sum(int n, ...) {      int sz{ n };     va_list ap;     va_start(ap, n);     int tmp{};     while (--sz)         tmp += va_arg(ap, int);      va_end(ap);      return tmp; }  int main() {      std::cout << COUNT_ARGUMENTS(4,57,22,10,5,6,2,8,68,24,24,86,89,89,96,86) << std::endl; // 1     std::cout << SUM(5, 57, 4, 5) << std::endl; // 0     std::cout << COUNT_ARGUMENTS(5, 57, 10) << std::endl;// 1       std::cout << std::endl;     std::cin.get(); } ``

I don't know what's wrong with my code, it always gives me the sum is 0.

Don't use a variadic macro. Visual C++ 14 (or 2015) is a C++11/14 compliant compiler. That means it it supports variadic templates. You can easily recurse a parameter pack to get the sum of the parameters and getting the count can be done by using `sizeof...`. This lets you write `count` as

``template<typename... Args> auto count(Args&&...) {     return sizeof...(Args); } ``

and then `sum` can be written as

``// base case template<typename T> auto sum(T&& first) {     return first; }  // multiple parameters case template<typename T, typename... Args> auto sum(T&& first, Args&&... rest) {     return first + sum(rest...); } ``

using those in

``int main() {     std::cout << count(3,4,5) << "/n";     std::cout << sum(3,4,5); } ``

prints

``3 12 ``

which you can see in this live example.

As suggested by HolyBlackCat you can use the dummy array trick to avoid using recursion. That would give you a `sum` that looks like

``template <typename ...P>  auto sum(const P &... params) {     using dummy_array = int[];     std::common_type_t<P...> ret{}; // common_type_t is to find the appropriate type all of the parameter can be added to     (void)dummy_array{(void(ret += params), 0)..., 0}; // add the parameter to ret, discard it's result, return the value of 0 for the array element     return ret; } ``

Do note though that this might not work correctly for all types, like shown here with `std::valarray`. Changing it to

``template <typename T, typename ...P>  auto sum(T first, P&&... rest) // copy the first parameter to use it as the accumulator {     using dummy_array = int[];     (void)dummy_array{(void(first += params), 0)..., 0}; // add the parameter to ret, discard it's result, return the value of 0 for the array element     return first; } ``

should be more correct, although it could probably be improved some more (suggestions/edits welcomed)

If you can use a C++17 complaint compiler then `sum` can be even further simplified using a fold expression like

``template<typename... Args> auto sum(Args&&... rest) {     return (rest + ...); } ``