可変引数マクロに渡された可変引数を合計する方法は?

可変個引数マクロを使用しないでください。 Visual C++ 14 (または 2015) は、C++11/14 準拠のコンパイラです。つまり、可変個引数テンプレートをサポートしています。パラメータ パックを簡単に再帰してパラメータの合計を取得できます。カウントは sizeof... を使用して取得できます。 .これにより、 count と書くことができます として

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

そして sum のように書くことができます

// 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...);
}

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

版画

3
12

この実例で見ることができます。

HolyBlackCat が示唆しているように、ダミー配列のトリックを使用して、再帰の使用を避けることができます。それはあなたに sum を与えるでしょう のようです

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;
}

std::valarray で示されているように、これはすべてのタイプで正しく機能しない可能性があることに注意してください。 .に変更

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;
}

おそらくもう少し改善される可能性がありますが、より正確なはずです(提案/編集を歓迎します)

C++17 準拠のコンパイラを使用できる場合、sum

のような折り式を使用して、さらに単純化できます。
template<typename... Args>
auto sum(Args&&... rest)
{
    return (rest + ...);
}

@NathanOliver に追加します。再帰なしで可変個引数テンプレートを使用する場合は、std::initializer_list を使用します。 と std::common_type どちらも C++11 で利用できるため、代わりにこれを行うことができます:

template <typename... Args,                                      
          typename T = typename std::common_type<Args...>::type> 
T sum(Args&&... args) {                                          
    std::initializer_list<T> l{args...};                         
    return std::accumulate(l.begin(), l.end(), T{});             
}                                                                

編集:このソリューションでは、共通の型に暗黙的に変換可能なすべての型で sum を呼び出すことができることに注意してください (つまり、common_type

例:

sum(1, 2, 3)    // Ok, all ints
sum(1, 2, true) // Ok, bool converts to int
sum(1, 2, 3.)   // Error, int to double is a narrowing conversion