Boost logo

Boost Users :

Subject: [Boost-users] [MultiArray][Variant][Serialization]
From: Johann Goetz (jgoetz_at_[hidden])
Date: 2011-04-26 13:37:00


I am trying to serialize a multi_array object but keep the dimensions
variable (I only want to support 1, 2 and 3 dimensions). So I attempted to
create a Variant of the three multi_array's and the corresponding serialize
methods as shown below, but I am getting a run-time error when for the
1-Dimensional case. Here is the minimal code example I came up with that
shows the problem. I am using the boost SVN trunk as of this posting (April
26, 2011).

Maybe I am implementing the load() method incorrectly for the multi_array.
Should there be a special case for when Dim == 1?

Running the program, I get the following error:
> ./test
test:
/home/goetz/local/src/boost-trunk/boost/multi_array/multi_array_ref.hpp:487:
boost::multi_array_ref<T, NumDims>& boost::multi_array_ref<T,
NumDims>::operator=(const ConstMultiArray&) [with ConstMultiArray =
boost::multi_array<float, 1ul>, T = float, long unsigned int NumDims = 1ul,
boost::multi_array_ref<T, NumDims> = boost::multi_array_ref<float, 1ul>]:
Assertion `std::equal(other.shape(),other.shape()+this->num_dimensions(),
this->shape())' failed.
Aborted (core dumped)

/// Begin File: multiarray-variant-serialize.cpp
/**
 * gcc compile command:
 * g++ multiarray-variant-serialize.cpp -otest -lboost_serialization
 *
 * to run:
 * ./test
 **/
#include <fstream>
#include <string>

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/array.hpp>
#include <boost/serialization/variant.hpp>
#include <boost/multi_array.hpp>

typedef boost::variant<
    boost::multi_array<float,1>,
    boost::multi_array<float,2>,
    boost::multi_array<float,3>
> multi_array_variant;

namespace boost {
namespace serialization {

    template<class Archive, typename T, size_t Dim>
    void save(
        Archive& ar,
        const boost::multi_array<T,Dim>& ma,
        const unsigned int version)
    {
        ar << boost::serialization::make_array(ma.shape(), Dim);
        ar << boost::serialization::make_array(ma.data(),
ma.num_elements());
    }

    template<class Archive, typename T, size_t Dim>
    void load(
        Archive& ar,
        boost::multi_array<T,Dim>& ma,
        const unsigned int version)
    {
        typedef typename boost::multi_array<T,Dim>::index index_t;
        boost::array<index_t,Dim> shape;

        ar >> boost::serialization::make_array(shape.data(), Dim);
        ma.resize(shape);

        ar >> boost::serialization::make_array(ma.data(),
ma.num_elements());
    }

    template<class Archive, typename T, size_t Dim>
    void serialize(
        Archive & ar,
        boost::multi_array<T,Dim>& ma,
        const unsigned int version)
    {
        split_free(ar, ma, version);
    }
} /// namespace boost::serialization
} /// namespace boost

int main()
{
    boost::multi_array<float,1> a1(boost::extents[5]);
    /// replacing the above line with either of the following two
    /// works as anticipated. Only the 1-Dimension breaks
    /// breaks at run-time.
    //boost::multi_array<float,2> a1(boost::extents[5][5]);
    //boost::multi_array<float,3> a1(boost::extents[5][5][5]);

    multi_array_variant a3 = a1;
    multi_array_variant a4;

    std::string filename = "archive.tmp";
    {
        std::ofstream ofs(filename.c_str());
        boost::archive::text_oarchive oa(ofs);
        oa << a3;
    }
    {
        std::ifstream ifs(filename.c_str());
        boost::archive::text_iarchive ia(ifs);
        ia >> a4;
    }

    return 0;
}
/// EOF

-- 
Johann T. Goetz


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