Boost logo

Boost :

Subject: Re: [boost] [serialization]Can I pass the grandparent class toBOOST_SERIALIZATION_BASE_OBJECT_NVP?
From: Takatoshi Kondo (redboltz_at_[hidden])
Date: 2011-04-04 10:48:03


Hi Robert.

On Mon, Apr 4, 2011 at 2:44 AM, Robert Ramey <ramey_at_[hidden]> wrote:

> Hi Takatoshi. Nice hear from you. Havn't heard from you in a while.

Thanks for reply.
BTW, I'll attend the boost-con 2011, I'm looking forward to seeing you again :)

> ... example and expanation in previous post.
>
>> ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(A); // My approach
>> // ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(B);
>
>> If I pass it B instead of A, the following exception would be
>> occurred. "unregistered void cast struct C<-struct A"
>
> Hmmm ... Are sure you don't mean to say "If I pass it A instead of B"

Oh.. I exactly want to say "If I pass it A instead of B".
Thanks for your mind-reading :)

> One of he side effects of BOOST_SERIALIZATION_BASE_OBJECT_NVP(A) (orB)
> is to invoke void_cast_register<base class, derived class> ...

My understanding is so.

> I would think that you could skip B in this case. But one would have
> to more carefully investigate how this macro is implemented.
>
> Note that if B is implemented as just another macro
> ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(A);
> so things can be done the normal way, I would hope that
> a release build would collapse the code to be equivalent
> to your method of skipping B.

Does "collapse" mean to be omitted by optimizer? (Good meaning?)

> It's also possible the the macro implementation could be
> refined and/or enhanced to permit the skipping of B if it
> doesn't do so already.
>
> Note that the tests/examples include one case where
> the void cast register is called directly - thereby eliminating
> the call to the macro. This short circuits the whole process
> and would be the most efficient. This is why I believe that
> the macro could be modified to directly pass A instead of B

I checked test_void_cast.cpp.
It's very interesting. I can remove the dependency
on the serialization library from class A, B and C completely.
I can add polymorphic serialization capability later (non intrusively).
Amazing!

#include <boost/serialization/serialization.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/export.hpp>

#include <fstream>

// -------------------------------------------------------------------------
struct A {
   explicit A(int vala_):vala(vala_) {}

   // pure virtual
   // to bypass serialize() requirement
   // If it is non pure, serialize() and default constructor are required.
   virtual ~A() = 0 {}
   int vala;
};

struct B : public A {
   B(int vala_, int valb_):A(vala_), valb(valb_) {}
   int valb;
};

struct C : public B {
   C(int vala_, int valb_, int valc_):B(vala_, valb_), valc(valc_) {}
   int valc;
};
// -------------------------------------------------------------------------

namespace boost { namespace serialization {

template<class Archive>
void serialize(Archive& /*ar*/, C&, unsigned int const /*version*/) {}

template<class Archive>
void save_construct_data(Archive& ar, C const* p, unsigned int const
/*version*/) {
   ar << boost::serialization::make_nvp("vala", p->vala);
   ar << boost::serialization::make_nvp("valb", p->valb);
   ar << boost::serialization::make_nvp("valc", p->valc);
}

template<class Archive>
void load_construct_data(Archive& ar, C* p, unsigned int const /*version*/) {
   int a, b, c;
   ar >> boost::serialization::make_nvp("vala", a);
   ar >> boost::serialization::make_nvp("valb", b);
   ar >> boost::serialization::make_nvp("valc", c);
   ::new(p) C(a, b, c);
}

}}

BOOST_CLASS_EXPORT(C)

int main()
{
  {
      std::ofstream ofs("test.xml");
      C c(1, 2, 3);
      A* a(&c);
      boost::archive::xml_oarchive oa(ofs);
      oa << boost::serialization::make_nvp("a", a);
  }
  {
      std::ifstream ifs("test.xml");
      boost::archive::xml_iarchive ia(ifs);
      A* a;
      ia >> boost::serialization::make_nvp("a", a);
      C* c = dynamic_cast<C*>(a);
      assert(c);
      assert(c->vala == 1);
      assert(c->valb == 2);
      assert(c->valc == 3);
      delete a;
  }
  // void_cast_register direct call
  boost::serialization::void_cast_register<C, A>(
      static_cast<C *>(NULL),
      static_cast<A *>(NULL)
  );
}

P.S.
I'm in the business trip now. I can't access my primary email account now.
This is my second email address.

Regards,
Takatoshi


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk