Related questions have been asked here before, but I still haven't found a satisfactory answer, so I will try to explain my problem and hope someone can enlighten me.
I am currently writing some code using boost::multi_array, and the code itself is also dimension independent. I need to loop over all elements stored in the multi_array and do something with them. I am looking to do this in a STL-like way:
for_each(begin(array), end(array), function);
Or something similar. Other questions have pointed me to an example on the boost page itself:
for_each example
for_each implementation
Which is more or less exactly what I want. The problem comes when one tries to simply import this code into a larger program. One would naturally like to both wrap the function itself in some namespace, and use for example the C++ functionals as the function object. Doing any of these two will create template lookup problems for the compiler.
Does anyone know either how I can work around the template lookup issue, or an alternative way of doing it (that is hopefully as pretty)?
Additional info:
Compilation error when wrapping the for_each definitions in a namespace
./for_each.hpp:28:3: error: call to function 'for_each' that is neither visible in the template definition nor found by
argument-dependent lookup
for_each(type_dispatch,A.begin(),A.end(),xform);
^
./for_each.hpp:41:5: note: in instantiation of function template specialization
'boost_utilites::for_each<boost::detail::multi_array::sub_array<double, 1>,
double, times_five>' requested here
for_each(type_dispatch,*begin,xform);
^
./for_each.hpp:50:3: note: in instantiation of function template specialization 'boost_utilites::for_each<double,
boost::detail::multi_array::array_iterator<double, double *, mpl_::size_t<2>, boost::detail::multi_array::sub_array<double,
1>,
boost::random_access_traversal_tag>, times_five>' requested here
for_each(boost::type<typename Array::element>(),A.begin(),A.end(),xform);
^
foreach_test.cpp:46:19: note: in instantiation of function template specialization
'boost_utilites::for_each<boost::multi_array<double, 2,
std::allocator<double> >, times_five>' requested here
boost_utilites::for_each(A,times_five());
^
./for_each.hpp:37:6: note: 'for_each' should be declared prior to the call site or in an associated namespace of one of its
arguments
void for_each (const boost::type<Element>& type_dispatch,
^
1 error generated.
When using a std::function object instead of the times_five object in the example, one gets basically the same compilation error.
Compiled with clang version 3.4-1ubuntu3.
Just
std::for_each(array.data(), array.data() + array.num_elements(), function);
To make it work with functions that expect an random-access range (with .begin()
, .end()
and .size()
) use
auto elements = boost::make_iterator_range(array.data(), array.data() + array.num_elements();
// e.g.
for (auto& element : elements) {
...
}
I personally like to use this with generate_n
or fill_n
etc.:
std::for_each(array.data(), array.num_elements(), 0);
Reference docs
element* data();
const element* data() const;
This returns a pointer to the beginning of the contiguous block that contains the array's data. If all dimensions of the array are 0-indexed and stored in ascending order, this is equivalent to origin(). Note that const_multi_array_ref only provides the const version of this function.
and
size_type a.num_elements()
This returns the number of elements contained in the array. It is equivalent to the following code:
std::accumulate(a.shape(),a.shape+a.num_dimensions(), size_type(1),std::multiplies<size_type>());>