#include <iostream>
namespace details
{
template<typename arg1_t>
inline constexpr bool same_type()
{
return true;
}
template<typename arg1_t, typename arg2_t, typename... args_t>
inline constexpr bool same_type()
{
return std::is_same<arg1_t, arg2_t>::value && same_type<arg2_t, args_t...>();
}
template<typename arg_t>
arg_t sum(arg_t value)
{
return value;
}
template<typename arg_t, typename... args_t>
arg_t sum(arg_t value, args_t... values)
{
return value + sum(std::forward<args_t>(values)...);
}
}
template<typename arg_t, typename... args_t>
auto sum(arg_t value, args_t... values)
-> typename std::enable_if<details::same_type<arg_t, args_t...>(), arg_t>::type
{
return details::sum(value, values...);
}
int main()
{
static_assert(details::same_type<int>());
static_assert(details::same_type<int, int>());
static_assert(details::same_type<int, int, int>());
static_assert(!details::same_type<int, int, double>());
std::cout << sum(1, 2, 3);
return 0;
}