On a recent thread, Bruno Martinez provided a std::for_each-like
function for multi_arrays which lets users apply a function to each
element in a multi_array or view without having to know anything about
the dimensions. I've been playing around with it (on MSVC 7.1) and it
works perfectly. It seems like a good utility for anyone using
boost.multi_array.
Working from Bruno's code, I wrote a similar std::accumulate-like
function, which could also be generally useful. I'm fairly new to
template programming, so if someone could look over the code below and
see if I've done something dangerous or stupid, it would be much
appreciated.
Also, is there some standard Boost way of making this sort of code
generally available? It probably isn't at a level where it could be
included in the library, but it seems like a shame to just let it
languish in the bowels of the mailing list archive.
Anyway, here are both algorithms:
My accumulate-like function:
template
struct accum_impl
{
F f;
T &val;
accum_impl(T &val, F f) : f(f), val(val) {}
T operator()(MA& ma)
{
std::for_each(ma.begin(), ma.end(), accum_implMA::const_reference::type, T, F, dim-1>(val, f));
return val;
}
};
template
struct accum_impl[
{
F f;
T &val;
accum_impl(T &val, F &f) : f(f), val(val) {}
T operator()(Ref r)
{
val = f(val, r);
return val;
}
};
template
T multi_accum(MA& ma, T init, F f)
{
accum_impl impl(init, f);
return impl(ma);
}
And a test:
typedef boost::multi_array array_type;
typedef array_type::index_range range;
typedef array_type::index index;
array_type B(boost::extents[4][2][3]);
int values = 0;
for(index i = 0; i != 4; ++i)
for(index j = 0; j != 2; ++j)
for(index k = 0; k != 3; ++k)
B[i][j][k] = values++;
array_type::array_view<2>::type myview =
B[ boost::indices[range(1,3)][1][range(0,2)] ];
cout << "Sum: " << multi_accum(myview, 0, std::plus<int>()) << endl;
cout << "Product: " << multi_accum(myview, 1, std::multiplies<int>()) <<
endl;
Bruno Martinez's for_each-like function:
template
struct for_each_impl
{
F f;
for_each_impl(F f) : f(f) {}
void operator()(MA& ma)
{
std::for_each(ma.begin(), ma.end(), for_each_impl(f));
}
};
template
struct for_each_impl][
{
F f;
for_each_impl(F f) : f(f) {}
void operator()(Ref r)
{
f(r);
}
};
template
void multi_for_each(MA& ma, F f)
{
for_each_impl impl(f);
impl(ma);
}
And a test:
typedef boost::multi_array array_type;
typedef array_type::index index;
array_type myarray(boost::extents[3][4][2]);
typedef array_type::index_range range;
array_type::array_view<3>::type myview =
myarray[ boost::indices[range(0,2)][range(1,3)][range(0,4,2)] ];
multi_for_each(myview, _1 = 56);]