Boost logo

Boost Users :

Subject: [Boost-users] [serialization] Serializing a reference
From: Ben (midfield_at_[hidden])
Date: 2009-10-23 18:27:48


Hello Boost Experts --

And now for my real question. Again, g++ 4.2.1, OS X 10.6.1, boost
1.40. I'm trying to follow the instructions in the document for
serializing classes with reference members, which suggests I serialize
them as pointers. First, a program which works, that uses pointers
and not references:

#include <iostream>
#include <fstream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>

struct A {
  int v;

  template<class Ar>
  void serialize(Ar & ar, const unsigned int ver) {
    ar & v;
  }
};

struct B {
  A *ap;

  B(A *ap_) : ap(ap_) {}

  template<class Ar>
  void serialize(Ar & ar, const unsigned int ver) {}
};

template<class Ar>
void save_construct_data(Ar & ar, const B * b, const unsigned int ver) {
  ar << b->ap;
}

template<class Ar>
void load_construct_data(Ar & ar, B * b, const unsigned int ver) {
  A * ap_;
  ar >> ap_;
  ::new(b)B(ap_);
}

int
main(int ac, char ** argv) {
  A a; a.v = 10;
  B * b1p;
  b1p = new B(&a);

  const char * fname = "test.bin";
  {
    std::ofstream ofs(fname);
    boost::archive::binary_oarchive ar(ofs);
    ar << b1p;
  }

  B * b2p;

  {
    std::ifstream ifs(fname);
    boost::archive::binary_iarchive ar(ifs);
    ar >> b2p;
  }

  std::cout << b2p->ap->v << std::endl;

  return 0;
}

What I would really like to do is to modify this program so that class
B has a reference to class A instead of a pointer. The documentation
suggests I do the following: "This raises the question of how and
where the objects being referred to are stored and how are they
created. Also there is the question about references to polymorphic
base classes. Basically, these are the same questions that arise
regarding pointers. This is no surprise as references are really a
special kind of pointer. We address these questions by serializing
references as though they were pointers." The example given after
this serializes the address of the referenced object, similar to the
above. My translation of that code is:

#include <iostream>
#include <fstream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>

struct A {
  int v;

  template<class Ar>
  void serialize(Ar & ar, const unsigned int ver) {
    ar & v;
  }
};

struct B {
  A &a;

  B(A &a_) : a(a_) {}

  template<class Ar>
  void serialize(Ar & ar, const unsigned int ver) {}
};

template<class Ar>
void save_construct_data(Ar & ar, const B * b, const unsigned int ver) {
  ar << (&(b->a));
}

template<class Ar>
void load_construct_data(Ar & ar, B * b, const unsigned int ver) {
  A * ap_;
  ar >> ap_;
  ::new(b)B(*ap_);
}

int
main(int ac, char ** argv) {
  A a; a.v = 10;
  B * b1p;
  b1p = new B(a);

  const char * fname = "test.bin";
  {
    std::ofstream ofs(fname);
    boost::archive::binary_oarchive ar(ofs);
    ar << b1p;
  }

  B * b2p;

  {
    std::ifstream ifs(fname);
    boost::archive::binary_iarchive ar(ifs);
    ar >> b2p;
  }

  std::cout << b2p->a.v << std::endl;

  return 0;
}

This however fails to compile, with the message:

Compilation started at Fri Oct 23 15:25:29

make -k debug
make all "CXX_FLAGS = -g -fno-inline -m64 -I. -I..
-I/opt/local/include -Wall -Wextra -Wpointer-arith -Wcast-align
-Wwrite-strings -Wconversion -Woverloaded-virtual -Wno-sign-compare
-Wno-unused -fno-nonansi-builtins" \
                 "LD_FLAGS = -g -m64"
g++ -g -fno-inline -m64 -I. -I.. -I/opt/local/include -Wall -Wextra
-Wpointer-arith -Wcast-align -Wwrite-strings -Wconversion
-Woverloaded-virtual -Wno-sign-compare -Wno-unused
-fno-nonansi-builtins -c test.cc -o test.o
test.cc: In function 'void save_construct_data(Ar&, const B*, unsigned
int) [with Ar = boost::archive::binary_oarchive]':
/opt/local/include/boost/serialization/serialization.hpp:148:
instantiated from 'void
boost::serialization::save_construct_data_adl(Archive&, const T*,
unsigned int) [with Archive = boost::archive::binary_oarchive, T = B]'
/opt/local/include/boost/archive/detail/oserializer.hpp:179:
instantiated from 'void
boost::archive::detail::pointer_oserializer<Archive,
T>::save_object_ptr(boost::archive::detail::basic_oarchive&, const
void*) const [with Archive = boost::archive::binary_oarchive, T = B]'
test.cc:60: instantiated from here
test.cc:27: error: no match for 'operator<<' in 'ar << (A*)b->B::a'
/opt/local/include/boost/archive/detail/interface_oarchive.hpp:63:
note: candidates are: Archive&
boost::archive::detail::interface_oarchive<Archive>::operator<<(T&)
[with T = A*, Archive = boost::archive::binary_oarchive]
make[1]: *** [test.o] Error 1
make[1]: Target `all' not remade because of errors.
make: *** [debug] Error 2

Compilation exited abnormally with code 2 at Fri Oct 23 15:25:30

What am I doing wrong?

Best regards, Ben


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