2

Is there a way to iterate over all the elements of a view into a Boost multi_array? It's clear how to iterate over a Boost multi_array; namely, go over the range [array.data(), array.data() + array.num_elements()). But if I create a view into this array (that cuts out some subset of the array), obviously a continuous access using pointers would be impossible: the view would not correspond to any continuous block of memory. Does Boost provide a mechanism to deal with this, or do I need to implement a solution by hand?

foxcub
  • 2,517
  • 2
  • 27
  • 27

2 Answers2

0

Luckily, the multi_array concept does not require any continuous block of memory. The fact that the reference implementation stores a stride for every dimension gives enough information to iterate correctly over the view. In fact, the multi_array concept requires the returned view to be iterable like a standard container.

burnpanck
  • 1,955
  • 1
  • 12
  • 36
0

Unfortunately no, Boost.MA doesn't give a way to iterate over all elements of a view generically. As burnpanck said, however you have all the information necessary in the stride information, although that would break the abstraction.

There are many ways to go through the elements and you didn't specify it (e.g. canonical order or leading axis first), however you can get an idea on how to iterate over all elements from the example here: https://www.boost.org/doc/libs/1_79_0/libs/multi_array/example/print_array.cpp This technique requires some sort of (template) recursion, terminating in the lower dimension.

Without worrying too much about performance or details, the technique is the following.

template<class Array, ElementAction action> 
void for_each_element(Array&& arr, ElementAction const& action) {
  for(long i = 0; i != arr.size(); ++i) {
    if constexpr(std::decay_t<Array>::dimensionality != 1) {
       for_each_element(arr[i], action);
    } else {
       action(arr[i]);
    }
  }
}

Use as

V = ... array view ..

for_each_element(V, [](auto& e) {e += 1;});

I have written a separate multidimensional array library which as a special accessor to the range of "linearized" elements.

V = ...;  // a view
...
for(auto& e : V.elements()) {  // V.elements() has begin() and end()
  e += 1;  // for example
}

which will cover V in the canonical order for arbitrary dimension, even if V is a view with non-trivial strides.

alfC
  • 14,261
  • 4
  • 67
  • 118