可変個引数マクロを使用しないでください。 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