[Boost-users] boost::serialization throwing “input stream error” on base class ptr XML serialization

1,014 views
Skip to first unread message

jvetter

unread,
Apr 17, 2013, 8:15:44 AM4/17/13
to boost...@lists.boost.org
Hello,

This seems straight forward to me, but yet I'm stilling getting a input
stream error and I don't understand why.

The weird part about it is if I un-comment the serialization of the base
class in my example it works, otherwise it does not. Here is the code:

struct A
{
virtual ~A() {};

int i1 = 10;

friend class boost::serialization::access;
template <class Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & make_nvp("int", i1);
}
};
struct B : A
{
virtual ~B() {};

float f1 = 5.0F

friend class boost::serialization::access;
template <class Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & boost::serialization::base_object<A>(*this);
ar & make_nvp("float", f1);
}
};
struct C : A
{
virtual ~C() {};

long l1 = 24;

friend class boost::serialization::access;
template <class Archive>
void serialize(Archive& ar, const unsigned int version)
{
ar & boost::serialization::base_object<A>(*this);
ar & make_nvp("long", l1);
}
};

//Why do these need to be wrappers??
namespace boost
{
namespace serialization
{
template<> struct is_wrapper<A*> : mpl::true_ {};
template<> struct is_wrapper<A> : mpl::true_ {};
template<> struct is_wrapper<const A> : mpl::true_ {};
}
}

BOOST_SERIALIZATION_ASSUME_ABSTRACT(A);
BOOST_CLASS_EXPORT(B)
BOOST_CLASS_EXPORT(C)

int main(int argc, char** argv)
{
//A* a = new A();
A* b = new B();
A* c = new C();
//A* a1 = nullptr;
A* a2 = nullptr;
A* a3 = nullptr;

ostringstream ostream;
xml_oarchive oarchive(ostream);

oarchive /*<< BOOST_SERIALIZATION_NVP(a)*/
<< BOOST_SERIALIZATION_NVP(b)
<< BOOST_SERIALIZATION_NVP(c);

istringstream istream(ostream.str());
xml_iarchive iarchive(istream);

iarchive /*>> BOOST_SERIALIZATION_NVP(a1)*/
>> BOOST_SERIALIZATION_NVP(a2)
>> BOOST_SERIALIZATION_NVP(a3);

//delete a;
delete b;
delete c;
//delete a1;
delete a2;
delete a3;
}

It's worth mentioning that this is with Boost 1.53 and GCC 4.8.0 w/
--std=c++11.

The same code works fine in both cases worth the text and binary
archives. I have tried changing the nvp's in the main to have the same
key and in the input case no key, but I get the same error.

Am I doing something wrong or is there an issue with the xml archive?

Thanks,
Jaime

_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users

Jari

unread,
Apr 22, 2013, 6:39:49 PM4/22/13
to boost...@lists.boost.org
hi think there's a problem with the way you are using BOOST_SERIALIZATION_NVP macros. Because its xml you are saving in you need to specify the name written and read to xml. 
But now you are saving "b" and "c" to xml and reading for "a2" and "a3". 

Use boost::serialization::make_nvp(name, var) instead to specify the name written to the xml for the variables your trying to read/write. Or use same c++ variable on read/write :)


like this:

    ostringstream ostream;
    xml_oarchive oarchive(ostream);

    oarchive << BOOST_SERIALIZATION_NVP("TestVar1",a);

    istringstream istream(ostream.str());
    xml_iarchive iarchive(istream);

    iarchive >> boost::serialization::make_nvp("TestVar1",a1);

Robert Ramey

unread,
Apr 26, 2013, 2:20:12 PM4/26/13
to boost...@lists.boost.org
Jari wrote:
>
> //Why do these need to be wrappers??
> namespace boost
> {
> namespace serialization
> {
> template<> struct is_wrapper<A*> : mpl::true_ {};
> template<> struct is_wrapper<A> : mpl::true_ {};
> template<> struct is_wrapper<const A> : mpl::true_ {};
> }
> }

I don't know why the above is there. It should be taken out
The problem is:

oarchive << BOOST_SERIALIZATION_NVP(a) creates an item <a ...> data </a>
iarchive >> BOOST_SERIALIZATION_NVP(a1) expects an item <a1 ...> data </a1>

The serialization library verifies that the name used to save is the name
used to load
because that's usually a bug. If you want the above to work you'l ahve to
use:

use the following instead so that the tag is always a

oarchive << make_nvp("a", a) creates an item <a ...> data </a>
iarchive >> make_nvp("a", a1) expects an item <a...> data </a1>
Reply all
Reply to author
Forward
0 new messages