Primer (basic usage)

In this example, we initialize a 2-dimensional array of numbers, and then we inspect the properties of this array, copy the array, and manipulate the element values. The example can be followed online.

The individual elements are initialized from a nested rectangular list.

multi::array<double, 2> A = {
    {1.0, 2.0, 3.0},
    {4.0, 5.0, 6.0},
};

auto const [n, m] = A.sizes();

assert( n == 2 );  // or std::get<0>(A.sizes()) == 2
assert( m == 3 );  // or std::get<1>(A.sizes()) == 3

assert( A.size() == 2 );  // size in first dimension, same as std::get<0>(A.sizes())
assert( A.num_elements() == 6 );  // total number of elements

Individual elements can be accessed by the multidimensional indices, using brackets.

assert( A[1][2] == 6.0 );

The value of an array can be copied, (moved,) and compared; copies are equal but independent (disjoint).

multi::array<double, 2> B = A;                 // we make a copy

assert(  B              ==  A              );  // copies are equal
assert(  B.extensions() ==  A.extensions() );  // extensions (sizes) are equal
assert(  B[0][1]        ==  A[0][1]        );  // all elements are equal
assert( &B[0][1]        != &A[0][1]        );  // elements are independent (dfferent addresses)

An array can be initialized from its sizes alone, in which case the element values are defaulted:

multi::array<double, 3> C({3, 4, 5});
assert( C.num_elements() == 3*4*5 );   // 60 elements with unspecified values

Arrays can be passed by value or by reference. Most of the time, arguments should be passed through generic parameters to also allow functions to work with parts (subblocks, slices, etc.) of an array. The most useful functions work on the concept of an array rather than on a concrete type, for example:

template<class ArrayDouble2D>  // instead of the overspecific argument multi::array<double, 2>
auto element_1_1(ArrayDouble2D const& m) -> double const& { return m[1][1]; }
...
assert( &element_1_1(A) == &A[1][1] );

The function expects any array or subarray of dimension 2 (or greater) and returns an element with type double.

The generic function template arguments that are not intended to be modified are passed by const&; otherwise, they are passed by forward-reference &&. In this way, the functions can be applied to subblocks of larger matrices.

assert( &element_1_1(C[0]) == &C[0][1][1] );

(Although most of the examples use numeric elements for conciseness, the library is designed to hold general types (e.g. non-numeric, non-trivial types, like std::string, other containers or, in general, user-defined value-types.)