Boost logo

Boost Users :

From: Jeffrey A. Edlund (jedlund_at_[hidden])
Date: 2008-04-08 02:11:37


I'm trying to serialize a hierarchical data structure like the
following:

class StorageVar;

typedef std::vector<StorageVar> sv_list;
typedef std::map<std::string, StorageVar > sv_dict;
typedef std::pair<std::string, StorageVar > sv_dict_pair;

typedef boost::variant <
boost::shared_ptr<size_t>,boost::shared_ptr<int>,boost::shared_ptr<double>,boost::shared_ptr<std::string>,
boost::shared_ptr<std::vector<size_t> >,
boost::shared_ptr<std::vector<int> >,
boost::shared_ptr<std::vector<double> >,
boost::recursive_wrapper<boost::shared_ptr< sv_list > >,
boost::recursive_wrapper<boost::shared_ptr< sv_dict > >,
boost::recursive_wrapper<boost::shared_ptr< sv_dict_pair > > > StorageVar_data_imp;

class StorageVar_imp {
    public:
    StorageVar_imp(): data(new StorageVar_data_imp) {};
    boost::shared_ptr<StorageVar_data_imp> data;
    boost::shared_ptr<sv_dict> attributes;
};

class StorageVar {
public:
    boost::shared_ptr<StorageVar_imp> content;
    StorageVar(): content(new StorageVar_imp) {};
    /* Further functionality removed for clarity. */
}

I had been hoping to serialize this nonintrustively, but quickly ran
into problems. Here's my understanding of the situation: As has been
mentioned on the list before, Boost.Serialize refuses to serialize
shared_ptrs to primitive types because tracking is turned off for
primitive types and cannot be turned on. Primitive types used in my
example include size_t,int,double, and std::string. I can understand
(sort of) why you wouldn't want to track all the numeric types, but I
don't understand why std::string is considered now considered a
primitive. (Looking at boost/serialization/string.hpp indicates that
it wasn't a primitive type at some point.)

The way that's mentioned in the archive to get around this is to use
BOOST_STRONG_TYPEDEF(int,tracked_int) etc. This would require that I
change the data structure (an intrusive change) and add a static_cast<
T&>(variable) everywhere these wrapped variables are used. (This is
because the "strong" typedef really just makes a new class with your
type inside it with basic methods defined.)

The other possible solution that I've looked at is to define
void serialize(Archive &ar, boost::shared_ptr<T> & arg, const unsigned
int version) myself for all my primitive types. That seems like
the wrong thing to do, but I'll probably do something with that until I
find a better way.

I might be missing something, but couldn't
boost/serialization/shared_ptr.hpp be rewritten to keep track of all the
pointers that it sees without turning tracking on for all primitive
types? Basically just automatically track anything that's inside a
shared_ptr. The programmer shouldn't be storing both a shared_ptr to
memory and a normal pointer to the same memory anyway.

Other info: Boost trunk r44086 (yesterday) built on Ubuntu with
g++. (I had been using 1.33.1 but that seemed to have problems
serializing vector<int>.)

Thanks,

Jeffrey


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