Boost logo

Boost Users :

Subject: Re: [Boost-users] Boost-users Digest, Vol 2158, Issue 1
From: Ben (midfield_at_[hidden])
Date: 2009-10-24 14:58:00


> Ahhh - so try
>
> ar >> static_cast<A* &>(a2p);
>
> Robert Ramey
>
> troy d. straszheim wrote:
>> Ben wrote:
>>> {
>>> std::ifstream ifs(fname);
>>> boost::archive::binary_iarchive ar(ifs);
>>> ar >> static_cast<A*>(a2p);
>>> }
>>
>> You're trying to write to an rvalue. Note that
>>
>> int *ip = 0;
>> static_cast<int*>(ip) = 0; // lvalue required as
>> // left operand of assignment
>>
>> doesn't compile either...

Wow, that was silly of me. Thanks for the quick response. Any clue
to the main question I had (repeated below) about serializing classes
with references? I don't think it's an rvalue thing, as the problem
occurs even in the save_construct_data bit. Generally, I'm trying to
copy what the documentation says to do.

Best, Ben

Date: Fri, 23 Oct 2009 15:27:48 -0700
From: Ben <midfield_at_[hidden]>
To: boost-users_at_[hidden]
Subject: [Boost-users] [serialization] Serializing a reference
Message-ID:
       <9157df230910231527x686ff3b4n16ec1e9eabc9515_at_[hidden]>
Content-Type: text/plain; charset=ISO-8859-1

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