#include <cassert>
#include <type_traits>

using std::is_same;
using std::declval;
using std::integral_constant;
using std::true_type;
using std::false_type;
using std::enable_if;

template <bool B, typename T = void>
using enable_if_t = typename enable_if<B, T>::type;

template <typename...> struct void_type { using type = void; };
template <typename... Ts> using void_t = typename void_type<Ts...>::type;

#define TYPIFY(x) integral_constant<decltype((x)), (x)>
#define DETYPIFY(x) x::value

// structure representing an array of types
template <typename...> struct type_array {};


/**** example starts here ****/


template <typename FirstCoef, typename T>
T combine(type_array<FirstCoef>, const T &value) {
    return DETYPIFY(FirstCoef) * value;
}

template <typename FirstCoef, typename... OtherCoefs,
          typename T, typename... Ts>
T combine(
    type_array<FirstCoef, OtherCoefs...>, // dummy parameter
    const T &value, const Ts &... other_values) {
    return DETYPIFY(FirstCoef) * value +
        combine(type_array<OtherCoefs...>{}, other_values...);
}


int main() {
    using coefs = type_array<TYPIFY(5), TYPIFY(2), TYPIFY(3)>;
    assert(combine(coefs{}, 1, 3, 2) == 5 + 3 * 2 + 3 * 2);
}