#include <tuple>
#include <type_traits>
#include <array>
#include <typeinfo>
#include <iostream>

template<typename T1, typename T2>
struct concat_tuples;

template<typename... T1, typename... T2>
struct concat_tuples<std::tuple<T1...>, std::tuple<T2...>>
{
    using type = std::tuple<T1..., T2...>;
}; 

template<typename T, size_t n>
struct n_tuple;

template<typename T>
struct n_tuple<T, 0> 
{
    using type = std::tuple<>;
};

template<typename T, size_t n>
struct n_tuple
{
    using type = typename concat_tuples<
                    typename n_tuple<T, n-1>::type, 
                    std::tuple<T>
                >::type;
};

template <class Scalar, class Array, class Tuple>
struct Test;

template <class Scalar,  typename T, size_t n, typename... Ts>
struct Test<Scalar, std::array<T, n>, std::tuple<Ts...>>
{
    using type = typename concat_tuples<
                    typename concat_tuples<
                        std::tuple<Scalar>, 
                        typename n_tuple<T, n>::type
                    >::type, 
                    std::tuple<Ts...>
                >::type;
};

int main() {
    static_assert(std::is_same<n_tuple<int, 3>::type, std::tuple<int, int, int>>::value, "NOT EQUAL");
    static_assert(std::is_same<Test<float, std::array<int, 3>, std::tuple<char, bool>>::type, std::tuple<float, int, int, int, char, bool>>::value, "NOT EQUAL");
}
