Ваш код работает , если вы предоставляете только два аргумента для sum
.
Проблема в том, что когда вы вызываете что-то вроде sum(1, 2, 3)
, Addable<Head, Tail...>
становится Addable<int, int, int>
, что не соответствует вашей частичной специализации Addable<T, U, void>
.Если вы вызываете sum
с более чем тремя аргументами, то шаблон Addable
, который соответствует вообще, отсутствует, поскольку Addable
принимает только три параметра шаблона.
Если вы хотите иметь возможность работать с более чемдва аргумента, вам понадобится другой подход.Это то, что я придумал.Он использует подход, аналогичный тому, который вы использовали, только с дополнительным косвенным указанием уровня для поддержки более двух аргументов:
template <typename T, typename U, typename = void>
struct Helper : std::false_type {};
template <typename T, typename U>
struct Helper<T, U, std::void_t<decltype(std::declval<T>() + std::declval<U>())>> : std::true_type {};
template <typename, typename...>
struct Addable : std::false_type {};
template <typename T, typename U, typename... V>
struct Addable<T, U, V...> : std::conditional_t<Addable<T, U>::value,
Addable<U, V...>,
std::false_type> {};
template <typename T, typename U>
struct Addable<T, U> : Helper<T, U> {};
template<typename Head, typename ... Tail>
auto sum(Head h, Tail ... args) {
static_assert(Addable<Head, Tail...>::value, "Requires addable objects");
return h+(args+...);
}
Live Demo