#include <iostream>
#include <array>

// -- Generate a sequence.
template <int... Is>
struct seq {};
template <int I, int... Is>
struct gen_seq : gen_seq<I - 1, I - 1, Is...> {};
template <int... Is>
struct gen_seq<0, Is...> : seq<Is...> {};


// -- Array summation function.
template <typename T>
constexpr T sum(std::array<T, 1> arr, decltype(gen_seq<0>{})) {
    return std::get<0>(arr);
}

template <typename T, std::size_t N, int... Is>
constexpr auto sum(std::array<T, N> arr, seq<Is...>) -> decltype(T() + T()) {
    return sum(std::array<T, N - 1>{ { std::get<Is>(arr)... } },
                gen_seq<N - 2>()) +
           std::get<N - 1>(arr);
}

// The interface - sum all elements of a given array.
template <typename T, std::size_t N>
constexpr auto sum(std::array<T, N> arr)
    -> decltype(sum(arr, gen_seq<N - 1>{})) {
    return sum(arr, gen_seq<N - 1>{});
}


// -- Demonstration
int main() {
    std::cout << sum(std::array<int, 1>{{1}}) << std::endl;
    std::cout << sum(std::array<int, 2>{{1, 2}}) << std::endl;
    std::cout << sum(std::array<int, 5>{{1, 2, 3, 4, 5}}) << std::endl;
}