Как насчет чего-то следующего?
#include <iostream>
template <typename T, T...>
struct add
{ static constexpr T value = 0; };
template <typename T, T head, T ... tail>
struct add<T, head, tail...>
{ static constexpr T value = head + add<T, tail...>::value; };
int main()
{
std::cout << add<int, 1, 2, 3, 4>::value << std::endl;
std::cout << add<long, 10l, 20l, 30l, 40l>::value << std::endl;
}
Или, может быть, лучше, наследуя от std::integral_constant
template <typename T, T...>
struct add : public std::integral_constant<T, T{0}>
{ };
template <typename T, T head, T ... tail>
struct add<T, head, tail...>
: public std::integral_constant<T, head + add<T, tail...>::value>
{ };
Если вы можете использовать C ++ 17, вам больше не нужна рекурсия, но вы можете использовать свертывание шаблонов.
template <typename T, T... Is>
struct add : public std::integral_constant<T, (... + Is)>
{ };
C ++ 17 также предлагает вам возможность избавиться от аргумента типа typename T
, используя auto
для значений.
Проблема становится такой: какой тип является value
, учитывая, что значения шаблона могут быть разных типов?
Я полагаю, что std::common_type
может быть решением этого вопроса, поэтому
#include <iostream>
#include <type_traits>
template <auto ... Is>
struct add :
public std::integral_constant<std::common_type_t<decltype(Is)...>,
(... + Is)>
{ };
int main()
{
std::cout << add<1, 2, 3, 4>::value << std::endl;
std::cout << add<10l, 20l, 30l, 40l>::value << std::endl;
}
или, может быть, просто используя decltype((... + Is))
template <auto ... Is>
struct add :
public std::integral_constant<decltype((... + Is)), (... + Is)>
{ };
Не по теме: оригинал add
можно немного упростить следующим образом
template <int...>
struct add
{ static constexpr int value = 0; };
template <int i, int... tail>
struct add<i, tail...>
{ static constexpr int value = i + add<tail...>::value; };
Я имею в виду: не две специализации, а основная версия (это основание для рекурсии) и одна специализация (случай рекурсии).
Или, по крайней мере, я вижу это как небольшое упрощение.