Boost logo

Boost Users :

From: Martin Ecker (martin.ecker_at_[hidden])
Date: 2005-07-10 03:21:58


Hi,

Ivan Rachev wrote:
> Does anyone have an idea how to serialize dynamic arrays of objects?
>
> An example follows at the end.

Please post fully working examples. That will make it easier for people to help
you. Your example requires a file test.txt that you didn't send along in your
e-mail.

> Its weakness shows up when an outside
> pointer points to an element in the array. The problem is that the type
> being serialized is T but not T*.

This should actually work fine. I modified your sample to use a memory buffer
instead of a file and added an assert to make sure the deserialized
second-element pointer points to the correct element. The assert does
not trigger with MSVC 7.1.

#include <sstream>

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/split_member.hpp>

class A
{ friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version) {}
};

//IVAN Element always points to the beginning of an array of
// 'Size' elements. The array is NOT null-terminated. If
// size == 0, Elements may hold an undefined value. User
// is responsible for initializing, new-ing and delete-ing.
// Assumption: if there is an outside pointer to an object
// inside this array, after loading the array
// that pointer will hold a different object.
template <typename T>
struct DynamicArray
{
    int Size;
    T* Element;

    friend class boost::serialization::access;
    template<class Archive>
    void save(Archive & ar, const unsigned int version) const
    {
      ar & Size;
      for (int i = 0; i < Size; ++i)
        ar & Element[i];
    }
    template<class Archive>
    void load(Archive & ar, const unsigned int version)
    {
      ar & Size;
      //TODO: assert(Size >=0);
      if (Size > 0)
        {
        Element = new T[Size];
        for (int i = 0; i < Size; ++i)
          ar & Element[i];
        }
    }
    BOOST_SERIALIZATION_SPLIT_MEMBER()
};

int main(int argc, char* argv[])
{
    DynamicArray<A> ArrayOfAs, ArrayOfAs2;
    ArrayOfAs.Element = new A[5];
    ArrayOfAs.Size = 5;
    A* secondElement = &ArrayOfAs.Element[1];
    A* secondElement2;

    std::stringstream stream;
    {
     boost::archive::text_oarchive oa(stream);
     oa & ArrayOfAs;
     oa & secondElement; // this guy will point to a copy of the
                         // 2nd element but NOT the 2nd element itself
    }

    {
    boost::archive::text_iarchive ia(stream);
    ia & ArrayOfAs2;
    ia & secondElement2; // this guy will point to a copy of the
                        // 2nd element but NOT the 2nd element itself
    }

    // does not trigger, so the above should work
    assert(secondElement2 == &ArrayOfAs2.Element[1]);

   delete [] ArrayOfAs.Element;
   delete [] ArrayOfAs2.Element;
}

Best Regards,
Martin


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