Do you really need a nested array?
You could also use a flat array and an adapter for the index, e,g,
template
concept is_convertible_to = std::is_convertible_v;
template
struct array_adapter
{
std::array m_a;
constexpr array_adapter(is_convertible_to<T> auto ... t) requires
(sizeof...(t) == Index::size()): m_a{t ...} {}
constexpr T operator()(is_convertible_tostd::size_t auto ... i)
const
requires (sizeof...(i) == Index::dim())
{
return m_a[Index{}(i...)];
}
constexpr T& operator()(is_convertible_tostd::size_t auto ... i)
requires (sizeof...(i) == Index::dim())
{
return m_a[Index{}(i...)];
}
};
For Index, you might e.g. use
template
struct row_major_index
{
static constexpr std::size_t size()
{
return (N*...);
}
template
constexpr static std::size_t first(is_convertible_tostd::size_t
auto... n)
{
if constexpr(i == 0)
{
return std::get<0>(std::make_tuple(n...));
}
else
{
return
std::get<i>(std::make_tuple(n...))+std::get<i>(std::make_tuple(N...))*f
irst<i-1>(n...);
}
}
constexpr std::size_t operator()(is_convertible_tostd::size_t
auto... n)
{
return first(n...);
}
static constexpr std::size_t dim()
{
return sizeof...(N);
}
};
This can be used as follows:
nt main()
{
static const int N1 = 2;
static const int N2 = 3;
static const int N3 = 4;
array_adapter>
a{111.,112.,113.,114.,
121.,122.,123.,124.,
131.,132.,133.,134.,
211.,212.,213.,214.,
221.,222.,223.,224.,
231.,232.,233.,234.};
for(int n1=0; n1 != N1; ++n1)
{
for(int n2=0; n2!=N2; ++n2)
{
for(int n3=0; n3!=N3; ++n3)
{
std::cout << "a(" << n1 << "," << n2 << "," << n3 << ")="
<< a(n1,n2,n3) << std::endl;
}
}
}
return 0;
}
Of course, this could be generaized to different types of arrays (e.g.
std:.vecrtor) usng some policy class and
template struct
array_index_adapter { ... };
Helmut