From several integral constants, it is possible to define a trait Sum
that returns the sum of all constants. For instance, we can define the following:
#include <type_traits>
template<typename...ARGS>
struct Sum : std::integral_constant<int,0> {};
template<typename T, typename...ARGS>
struct Sum<T,ARGS...> : std::integral_constant<int,T::value + Sum<ARGS...>::value> {};
struct One : std::integral_constant<int,1> {};
struct Two : std::integral_constant<int,2> {};
struct Three : std::integral_constant<int,3> {};
static_assert (Sum<One,Two,Three>::value == 6);
Q1: does the standard library hold such a trait ? (I mean, I don't want to reinvent the wheel)
Q2: would it be possible to define this trait without using template specialization ?
Does the standard library hold such a trait?
No, the C++ standard library does not provide a direct equivalent to the Sum
trait you've defined.
Would it be possible to define this trait without using template specialization?
There are many ways. One way with minimal change to your original code, would be:
template<typename... Args>
struct Sum : std::integral_constant<int, (0 + ... + Args::value)> {};
struct One : std::integral_constant<int, 1> {};
struct Two : std::integral_constant<int, 2> {};
struct Three : std::integral_constant<int, 3> {};
static_assert(Sum<One, Two, Three>::value == 6);
static_assert(Sum<>::value == 0); // Empty sum is zero
Or with variable template and template lambda (requires compiler supports c++20 or later)
template<int N> using Int = std::integral_constant<int, N>;
constexpr auto Sum = []<typename... Args>() { return (0 + ... + Args::value); };
static_assert(Sum.template operator()<Int<1>, Int<2>, Int<3>> () == 6);
static_assert(Sum.template operator()<>() == 0); // Empty sum is zero
Or just use a simple template function for calculation (Requires compiler support c++17 or higher, because of fold expressions usage).
template<int N> using Int = std::integral_constant<int, N>;
template<typename... Args> constexpr auto Sum() { return (0 + ... + Args::value); }
static_assert(Sum<Int<1>, Int<2>, Int<3>>() == 6);
static_assert(Sum<>() == 0); // Empty sum is zero