Нужно создать массив с элементами у которых разный размер. Размер массива, элементов, и их порядок известен в compile-time. В коде могу представить так:
template<int N = 5>
struct A {
  std::array<int, N> = {
    // Вот эти значения должны как то создаваться автоматически
    // 1...N, N = 5
    std::array<int, 1>,
    std::array<int, 2>,
    std::array<int, 3>,
    std::array<int, 4>,
    std::array<int, 5>, 
  };
};
template<int N = 3>
struct B {
  std::array<int, N> = {
    // Вот эти значения должны как то создаваться автоматически
    std::array<int, 1>,
    std::array<int, 2>,
    std::array<int, 3>,
  };
};
Есть что то готовое, что можно использовать, и работающее в компилтайме?
-----------------------------------------------------
Первое решение:
#include <type_traits>
#include <iostream>
#include <tuple>
#include <array>
template <typename... Ts>
class tuple_array_t : public std::tuple<Ts...> {
public:
    using std::tuple<Ts...>::tuple;
    template <size_t N>
    constexpr auto&& operator[](std::integral_constant<size_t, N>) {
        return std::get<N>(*this);
    }
    [[nodiscard]] constexpr auto size() const {
        return std::integral_constant<std::size_t, std::tuple_size_v<decltype(static_cast<std::tuple<Ts...>>(*this))>>();
    }
};
template <std::size_t From, std::size_t To, class F>
constexpr void constexpr_for_range(F&& f) {
    if constexpr (From < To) {
        f(std::integral_constant<size_t, From>());
        constexpr_for_range<(std::size_t)From + 1, (std::size_t)To>(f);
    }
}
template<typename T, size_t N, typename... Ts>
constexpr auto linear_tuple_array() {
    if constexpr (N > 1) {
        return linear_tuple_array<T, N - 1, Ts..., std::array<T, N>>();
    } else {
        return tuple_array_t<Ts..., std::array<T, N>>();
    }
}
constexpr auto generate_super_array() {
    auto linear_array = linear_tuple_array<float, 10>();
    auto linear_array_size = linear_array.size();
    constexpr_for_range<0, linear_array.size()>([&] (auto i) {
        constexpr auto n = linear_array_size - i;
        constexpr_for_range<0, n>([&] (auto j) {
            linear_array[i][j] = i * 1000 + j;
        });
    });
    return linear_array;
}
int main() {
    auto array = generate_super_array();
    auto x = std::integral_constant<std::size_t, 5>();
    auto y = std::integral_constant<std::size_t, 3>();
    
    // #output: 5003
    std::cout << array[x][y] << std::endl;
}
------------------------------------------------
Второе решение
#include <cstddef>
#include <type_traits>
#include <iostream>
template <typename T, size_t N>
class ctmat;
template <typename T>
class ctmat<T, 1>
{
public:
    template <size_t i, size_t j>
    typename std::enable_if<i == 0 && j == 0, T>::type& get() { return m_v[0]; }
    template <size_t i, size_t j>
    typename std::enable_if<i == 0 && j == 0, T>::type const& get() const { return m_v[0]; }
    template <typename U>
    friend std::ostream& operator<<(std::ostream& out, const ctmat<U, 1>& m);
private:
    T m_v[1];
};
template <typename T, size_t N>
class ctmat: public ctmat<T, N-1>
{
public:
    typedef ctmat<T, N-1> base_type;
    using base_type::get;
    template <size_t i, size_t j>
    typename std::enable_if<i == N-1 && j < N, T>::type& get() { return m_v[j]; }
    template <size_t i, size_t j>
    typename std::enable_if<i == N-1 && j < N, T>::type const& get() const { return m_v[j]; }
    base_type& base() { return static_cast<base_type>(*this); }
    base_type const& base() const { return static_cast<const base_type&>(*this); }
    template <typename U, size_t M>
    friend std::ostream& operator<<(std::ostream& out, const ctmat<U, M>& m);
private:
    T m_v[N];
};
template <typename T>
std::ostream& operator<<(std::ostream& out, const ctmat<T,1>& m)
{
    out << m.m_v[0] << std::endl;
    return out;
}
template <typename T, size_t N>
std::ostream& operator<<(std::ostream& out, const ctmat<T, N>& m)
{
    out << m.base();
    for (size_t j = 0; j != N; ++j)
        out << m.m_v[j] << ' ';
    out << std::endl;
    return out;
}
int main()
{
    ctmat<int, 1> m1;
    static_assert(sizeof(m1) == sizeof(int), "Unexpected size");
    m1.get<0,0>() = 1;
    //m1.get<1,0>() = 2;
    //m1.get<0,1>() = 3;
    std::cout << m1;
    ctmat<int, 2> m2;
    static_assert(sizeof(m2) == 3*sizeof(int), "Unexpected size");
    m2.get<0,0>() = 4;
    //m2.get<0,1>() = 5;
    m2.get<1,0>() = 6;
    m2.get<1,1>() = 7;
    std::cout << m2;
    return 0;
}




