I was looking for some suitable 2D element container. What I want is the ability to iterate through every element of the container using, for example BOOST_FOREACH
and I also would like to have an ability to construct subview (slices / subranges) of my container and, probably iterate through them too.
Right now I am using boost::numeric::ublas::matrix
for these purposes, but, well, it doesn't look as a good solution for me, because, well, it's a BLAS matrix, although it behaves very well as a plain 2d element container (cus开发者_如何学编程tom unbounded
/ bounded
storages are also very sweet).
Another boost
alternative, boost::multi_array
is bad, because you can't iterate through every element using one BOOST_FOREACH
statement and because constructing views has extremely obfuscated syntax.
Any alternatives?
Thank you.
I do the following (array type is container/iterator range concept):
ublas::matrix<douple> A;
foreach (double & element, A.data())
{
}
However, this will not work for slices: your best solution is to write an iterator for them.
Here is an example of using multi_array
to provide storage of a custom class.
Perhaps you could do the same:
template<size_t N, typename T>
struct tensor_array : boost::multi_array_ref<T,N> {
typedef boost::multi_array_ref<T,N> base_type;
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
tensor_array() : base_type(NULL, extents())
{
// std::cout << "create" << std::endl;
}
template<class A>
tensor_array(const A &dims)
: base_type(NULL, extents())
{
//std::cout << "create" << std::endl;
resize(dims);
}
template<typename U>
void resize(const U (&dims)[N]) {
boost::array<U,N> dims_;
std::copy(dims, dims + N, dims_.begin());
resize(dims_);
}
template<typename U>
void resize(const boost::array<U,N> &dims) {
size_t size = 1;
boost::array<size_t,N> shape;
for (size_t i = 0; i < N; ++i) {
size *= dims[i];
shape[N-(i+1)] = dims[i];
}
data_.clear();
data_.resize(size, 0);
// update base_type parent
set_base_ptr(&data_[0]);
this->num_elements_ = size;
reshape(shape);
}
size_t size() const { return data_.size(); }
size_t size(size_t i) const { return this->shape()[N-(i+1)]; }
tensor_array& fill(const T &value) {
std::fill(data_.begin(), data_.end(), value);
return *this;
}
private:
typedef boost::detail::multi_array::extent_gen<N> extents;
std::vector<T> data_;
};
Define your own type (trivial), give it an iterator and const_interator (trivial), and BOOST_FOREACH will work with it.
http://beta.boost.org/doc/libs/1_39_0/doc/html/foreach.html
精彩评论