I have implemented multidimensional utilities in C ++ 17.

Here is the header `dimension.hpp`

:

```
/ **
* @file dimension.hpp
* Implements multidimensional utilities.
* /
#ifndef INC_DIMENSION_HPP_CAdUgZHijL
#define INC_DIMENSION_HPP_CAdUgZHijL
#understand
#understand
#understand
#understand
/ **
* The library of L. F.
* /
namespace LF_lib {
/ **
* Multidimensional utilities.
* /
multi namespace {
/ **
* Tag type to indicate unverified versions of functions.
* /
struct unchecked_t {
explicit unchecked_t () = default;
};
/ **
* Tag object to indicate unverified versions of functions.
* /
inline constexpr unchecked_t unchecked {};
/ **
* Encapsulates the dimensions @c N.
* Aggregate type containing only one public member type
````std :: array`.
* @c N can be zero.
*
* @tparam N The number of dimensions
* /
model
struct Dimension {
using dimension_t = std :: array; /// <Type for dimensions.
using index_t = std :: array; /// <Type for indexes.
dimension_t dimensions; /// <Store the dimensions @c N.
/ **
* @observer names
* @ {
* /
/ **
* Returns the number of dimensions.
*
* @return @c N
* /
static constexpr std :: size_t order () noexcept {return N; }
/ **
* Returns the total size.
*
* @return The product of all dimensions
* /
constexpr std :: size_t size () const noexcept
{
std :: size_t res = 1;
for (std :: size_t dim: dimensions)
res * = dim;
returns res;
}
/ **
* @}
* /
/ **
* @name Access to items
* @ {
* /
/ **
* Check if the given clues are in the range.
*
* @param indices The indices
*
* @return @c true if `clues[i] <dimensions[i]` for `i = 0, 1, 2, ..., N-1`, @c false otherwise
* /
constexpr valid bool (const index_t & indices) const noexcept
{
for (std :: size_t i = 0; i < N; ++i)
if (indices[i] >= dimensions[i])
returns false;
return true;
}
/ **
* Returns the flat index of the element at @c indices.
*
* @param indices The indices
*
* @pre `valid (indices)`
* @throw std :: out_of_range At least one index is out of bounds
*
* @return `(... ((indices[0] * dimensions[1] + indices[1]) * dimensions[2] + indices[2]) * ...) * dimensions[N-1] + indices[N-1]`
* /
constexpr std :: size_t to (const index_t & indices) const
{
if (! valid (indices))
throws std :: out_of_range {"LF_lib :: multi :: Dimension::at "
"out-of-range indices"};
return to (unverified, indices);
}
/ **
* Uncontrolled version of @c at.
* /
constexpr std :: size_t to (unchecked_t, const index_t & indices) const noexcept
{
std :: size_t res = 0;
for (std :: size_t i = 0; i <N; ++ i)
res = res * dimensions[i] + indices[i];
returns res;
}
/ **
* Parentheses notation from @c to.
* Let `clues` denote `index_t {static_cast(args) ...}`.
*
* @tparam Args The types of the indices
* @param args Indices
*
* @pre `sizeof ... (Args) == N`
* @pre `std :: conjunction_v <std :: is_convertible...>`
* @pre `valid (indices)`
* @return `at (indices)`
* @throw std :: out_of_range At least one index is out of bounds
* /
model
constexpr std :: size_t operator () (Args && ... args) const
{
static_assert (sizeof ... (Args) == N,
"LF_lib :: multi :: Dimension:: operator () "
"must be called with N arguments");
static_assert (std :: conjunction_v <std :: is_convertible...>
"LF_lib :: multi :: Dimension:: operator () "
"must be called with arguments"
"implicitly convertible to std :: size_t");
index_t index {static_cast(args) ...};
if (! valid (indices))
throws std :: out_of_range {"LF_lib :: multi :: Dimension:: operator () "
"out-of-range indices"};
return to (unverified, indices);
}
/ **
* @}
* /
};
/ **
* Guide to deduction.
* Deduced `Dimension` for the @c N. arguments
* /
model
Dimension (Args ...) -> Dimension;
}
}
#end if

You can run Doxygen to generate the documentation.

Here is a test, which is also an example of how `Dimension`

can be used:

```
#include "dimension.hpp"
#understand
using namespace LF_lib :: multi;
int main ()
{
{
Dimension constexpr<5> dim {1, 2, 3, 4, 5};
static_assert (dim.order () == 5);
static_assert (dim.size () == 120);
static_assert (! dim.valid ({1, 1, 1, 1, 1}));
static_assert (dim.at ({0, 1, 2, 3, 4}) == 119);
static_assert (dim.at ({0, 1, 2, 3, 4}) == dim.at (unchecked, {0, 1, 2, 3, 4}));
// static_assert (dim.at ({1, 1, 1, 1, 1}));
static_assert (dim (0, 1, 2, 2, 4) == dim.at ({0, 1, 2, 2, 4}));
}
{
Dimension constexpr<0> dim = {};
static_assert (dim.order () == 0);
static_assert (dim.size () == 1);
static_assert (dim.valid ({}));
static_assert (dim.at ({}) == 0);
static_assert (dim.at ({}) == dim.at (unchecked, {}));
static_assert (dim () == 0);
}
{
static_assert (std :: is_same_v <Dimension<5>, decltype (Dimension {1, 2, 3, 4, 5})>);
// static_assert (std :: is_same_v <Dimension<5>, decltype (Dimension (1, 2, 3, 4, 5))>);
static_assert (std :: is_same_v <Dimension<0>, decltype (Dimension {})>);
static_assert (std :: is_same_v <Dimension<0>, decltype (Dimension ())>);
}
}
```