views:

590

answers:

1

See below a main() and two very simple classes. Then per Boost serialization (and what is shown) my questions are:

1) Does class B need the normal overloaded stream insertion operators '<<' and '>>' to be defined? Currently in my real code it doesn't have these.

2) Does class A in the store() and load() methods need to iterate through the map and multimap containers explicitely, storing/loading their key:value pairs explicitely? e.g. something like:

void A::store(const char* filename){

std::ofstream ofs(filename);
boost::archive::text_oarchive oa(ofs);

std::map< std::string, B >::iterator it;

BMap.size();
oa << BMap.size();
for( it = BMap.begin(); it != BMap.end(); it++ ){
 oa <<  it->first;
 oa << it->second;
}

//similar for strMultimap
}

I assume that I don't need to do this, but am not certain.

3) Assuming class B has only the two data members shown, does it need a default contructor included explicitely? (as opposed to the implicit default constructor)

4) Does B need to have an overide for the comparison operator '>'? I assume that it doesn't since this is a very simple class.

Finally, any other comments per anything that I've failed to cover is appreciated!

Example code for my above questions:

//includes ommitted

int main() {

    std::string file("test.dat");

    A * pA = new A;

    pA->store(file.c_str());
    pA->fillMaps();
    //release data
    pA->load(file.c_str());

    return 0;
}

//includes ommitted

class A
{
    friend class boost::serialization::access;

public:

    std::map< std::string, B > BMap;
    std::multimap< std::string, std::string > strMultimap;

    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
     ar & BMap;
     ar & strMultimap;
    }

    void store(const char* filename){

    std::ofstream ofs(filename);
    boost::archive::text_oarchive oa(ofs);
    oa << this;
  }

  void load(const char* filename){

    std::ifstream ifs(filename);
    boost::archive::text_iarchive ia(ifs);
    ia >> this;

  }

  void fillMaps(){

//code to allocate B objects and put them in BMap and fill strMultimap with whatever number of key:value pairs

}

class B
{
friend class boost::serialization::access;

public:

    std::string str;
    unsigned int num;

    B::B(void)
    : str("a string")
    , num(7)
    {
    }

    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & str;
        ar & num;
    }
}
+1  A: 

1) You don't need stream operators for class B, but it does need a serialize() method. I had to wrap the serialization with the BOOST_SERIALIZATION_NVP (name value pair) macro:

ar & BOOST_SERIALIZATION_NVP(someNamedValue); // use this macro for everything you want to name

There might be a way to avoid naming your map, but I don't know how that's done.

2) No, class A doesn't need map-specific serialization code. Just make sure you include <boost/serialization/map.hpp>.

3) The implicit default constructor should be fine. You only ever need an explicit default constructor if a) you've already provided a non-default constructor or b) you want to change the behavior of the default constructor.

4) No operator < is needed :)

Here's some sample code which compiled, but I haven't run:

#include <boost/serialization/map.hpp>

struct A
{
    struct B
    {
        template<class Archive>
        void serialize(Archive &ar, const unsigned int version)
        {
        }
    };
    typedef std::map<int, SomeClass> MyMap;
    MyMap myMap;

    template<class Archive>
    void serialize(Archive &ar, const unsigned int version)
    {
        ar & BOOST_SERIALIZATION_NVP(myMap);
    }
};
Alex McCarthy