Boost logo

Boost Users :

From: Ronald Garcia (garcia_at_[hidden])
Date: 2008-07-17 15:19:47


Hello Johann,

On Jul 11, 2008, at 6:17 AM, Dr Johann A. Briffa wrote:

> I realize this topic has been discussed before (I've seen at least a
> thread in 2006 and another in 2007), but I believe there is more to
> add. At issue is the decision that multi_array objects cannot be
> assigned [with the operator=() that is] unless the target is already
> the same size as the source. Further, there is no documented way to
> easily resize an existing array to the same size and range as some
> other array.

Indeed there is no built-in way to easily resize a multi_array to be
the same size as another multi_array. While there is no resize member
function that takes a pointer, there is one that takes a model of the
Collection concept (classes like boost::array and std::vector are
concepts). Based on this interface, here is a stop-gap non-invasive
solution that can resize a multi_array based on another model of
MultiArray (multi_array, multi_array_ref, etc.):

//
=
=
=
=
=
=
=
=
=
=
========================================================================

#include <boost/multi_array.hpp>
#include <boost/static_assert.hpp>
#include <boost/array.hpp>
#include <algorithm>

template <typename T, typename U, std::size_t N>
void
resize_from_MultiArray(boost::multi_array<T,N>& marray, U& other) {

   // U must be a model of MultiArray
   boost::function_requires<
    
boost
::detail::multi_array::ConstMultiArrayConcept<U,U::dimensionality> >();
   // U must have U::dimensionality == N
   BOOST_STATIC_ASSERT(U::dimensionality == N);

   boost::array<typename boost::multi_array<T,N>::size_type, N> shape;

   std::copy(other.shape(), other.shape()+N, shape.begin());

   marray.resize(shape);

}

//
// Example usage
//

#include <iostream>

int main () {

   boost::multi_array<int,2> A(boost::extents[5][4]), B;
   boost::multi_array<int,3> C;

   resize_from_MultiArray(B,A);

#if 0
   resize_from_MultiArray(C,A); // Compile-time error
#endif

   std::cout << B.shape()[0] << ", " << B.shape()[1] << '\n';

}

//
=
=
=
=
=
=
=
=
=
=
=
=
=
========================================================================

One can use this function to easily resize a multi_array in terms of
another multi_array. This does not solve the problem you describe
below, where you want operator=() to resize a multi_array.

>
> As far as my needs are concerned, a multi_array that cannot be
> assigned is next to useless. Allow me to elaborate: I am using
> multi_array as a replacement to my own (old) 2/3D containers, as
> recently I've had need for higher dimensions. I have classes
> containing array members, where the size of the arrays is dynamic
> through the object lifetime. So my class default constructor uses
> the array default constructor for its member objects, creating empty
> arrays. Eventually as my classes get used, the array members are
> updated accordingly, and get to have some non-zero size. Now the
> problem is that my classes need to be assignable, and the only way
> that can be achieved is if the array members are assignable; the
> alternative is to have to write a specific assignment operator for
> any of my classes that use arrays, resizing each member of the
> target before copying. Clearly that would involve a lot of extra
> effort.
>

I believe that in a previous discussion I had suggested a template
argument-based solution to this, where a multi_array type would have
resizing assignment (and thereby no longer be a model of the
MultiArray concept). I don't recall getting feedback on that proposal.

Cheers,
ron


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net