Skip to content

A boost::multi_array façade

October 27, 2011

The Boost Multidimensional Array is a generic N-dimensional array class. You choose how many dimensions you want, and it provides an interface which lets you look at particular slices of the array as though it were a completely different array.

For example, if you wanted a 3-dimensional array of int, you would write:

boost::multi_array<int, 3> array;

then assuming that initialised it to be a 5 by 5 by 5 array, we could write the following:

auto slice = array[3];

and the slice variable could now be treated as a 2-dimensional array, of size 5 by 5, whose i,j-th elements are the same as array[3][i][j].

I recently had to write an interface to a multi_array so that the rest of the code in my project could use it. However, I still wanted to maintain this ability to write directly into the array, and to get slices of the array. Instead of just providing a function which returns the underlying array, I opted for writing an access function with variadic templates.

The following code presents the important parts of my class, ArrayN, which is also templated by type and number of dimensions.

template typename T, size_t N>
class ArrayN
{
  public:
  typedef boost::multi_array<T,N> type;
  type m_array;
 
  template <typename... Location>
  auto
  get(Location... loc) const
    -> decltype(array_get()(m_array, loc...))
  {
    return array_get()(m_array, loc...);
  }
}

This code makes use of a helper class array_get. Its definition is:

struct array_get
{
  template <typename Array>
  Array
  operator()(const Array&amp; a)
  {
    return a;
  }

  template <
    typename Array,
    typename First,
    typename... Location
  >
  auto
  operator()(const Array&amp; a, First f, Location... loc)
    -> decltype(operator()(a[f], loc...))
  {
    return operator()(a[f], loc...);
  }
}

Notice that in the variadic operator(), we are stripping off one argument each call. Then eventually when there are no arguments left the non-variadic operator() is called which simply returns what was given to it.

It can be used like so:

ArrayN<int, 5> array;
//initialise the array as appropriate
auto slice = array.get(3,4,5);
int sliceElement = slice[2][3];
int element = array.get(1,2,3,4,5);
Advertisements
4 Comments
  1. Larry E permalink

    Shouldn’t the line1 in the last code block be:

    ArrayN array;

    ?

    I say this because the line5 is:

    int element = array.get(1,2,3,4,5);

    which seems to indicate the T arg to ArrayN should be int
    and the N argument should be 5.

    • Larry E permalink

      OOPS, Apparently I don’t know how to enter angle bracket is the code because
      they are missing from the ArrayN provided in my comment.

      How should angles brackets be entered in comments?

  2. Larry E permalink

    Lets try again using “ampersand less_than” instead:

    ArrayN<int,5> array;

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: