I am working on a simple serialization class. I keep throwing an exception on the input stream. I have put together the below example of what I am attempting to accomplish in simple terms.
I have this simple example of boost serialization that I am getting an exception on:
#include <boost/serialization/serialization.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/export.hpp>
#define NVP(X) X
class base {
public:
friend class boost::serialization::access;
base (){ v1 = 10;}
int v1;
template<class Archive>
void serialize(Archive & ar, const unsigned int file_version)
{
ar & NVP(v1);
}
virtual void bla()=0;
};
class derived : public base {
public:
friend class boost::serialization::access;
int v2 ;
derived() { v2 = 100;}
template<class Archive>
void serialize(Archive & ar, const unsigned int file_version){
boost::serialization::base_object<base>(* this);
ar & NVP(v2);
}
virtual void bla(){};
};
BOOST_CLASS_EXPORT(base);
BOOST_CLASS_EXPORT_GUID(derived, "derived");
int main ( )
{
std::stringstream ss;
boost::archive::text_oarchive ar(ss);
base *b = new derived();
ar << NVP(b);
std::cout << ss.str()<<std::endl;
std::istringstream ssi;
base *b1 = new derived();
{
boost::archive::text_iarchive ar1(ssi);
ar1 >> b1;
}
//std::cout << ssi.str();
std::cout << "v1: " << b1->v1 << std::endl;
}
The exception that I am getting is:
terminate called after throwing an instance of 'boost::archive::archive_exception'
what(): input stream error
Any help would be appreciated.
You're reading from an empty stream:
std::istringstream ssi;
// ...
boost::archive::text_iarchive ar1(ssi);
Also, you leak this object:
base *b1 = new derived();
Here's a fixed example, notes:
BOOST_CLASS_EXPORT_GUID(derived, "derived")
doesn't add anything beyond BOOST_CLASS_EXPORT(derived)
you can print the v2 conditionally:
if (auto* d = dynamic_cast<derived*>(b1))
std::cout << "v2: " << d->v2 << std::endl;
I've used bla()
as an example to print the values instead
NVP()
is a bit iffy there. Why not just leave it out for non-tagged archives (ie. other than XML)? If you intend to support XML, just use BOOST_SERIALIZATION_NVP
, boost::serialization::make_nvp
etc.
std::cout << "v2: " << b1->v2 << std::endl;
was completely out of place
just initialize b1
to null so you don't leak it; remember to free all pointers (use smart pointers!)
the mix of public:
and friend
in your types didn't really mean much
Live On Coliru
#include <boost/serialization/serialization.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/export.hpp>
#include <sstream>
class base {
public:
base(int v1) : v1(v1) {}
virtual void bla() const = 0;
private:
friend class boost::serialization::access;
template <class Archive> void serialize(Archive &ar, unsigned /*int const file_version*/) {
ar & BOOST_SERIALIZATION_NVP(v1);
}
protected:
int v1;
};
class derived : public base {
public:
derived(int v1 = 10, int v2 = 100) : base(v1), v2(v2) {}
virtual void bla() const {
std::cout << "v1: " << v1 << ", v2: " << v2 << "\n";
}
private:
friend class boost::serialization::access;
int v2;
template <class Archive> void serialize(Archive &ar, unsigned /*int const file_version*/) {
boost::serialization::base_object<base>(*this);
ar & BOOST_SERIALIZATION_NVP(v2);
}
};
BOOST_CLASS_EXPORT(base)
BOOST_CLASS_EXPORT(derived)
int main() {
std::stringstream ss;
{
boost::archive::text_oarchive ar(ss);
base *b = new derived();
ar << boost::serialization::make_nvp("base", b);
delete b; // TODO use RAII instead
}
std::cout << ss.str() << std::endl;
base *deserialized = nullptr;
{
boost::archive::text_iarchive ar1(ss);
ar1 >> boost::serialization::make_nvp("base", deserialized);
}
deserialized->bla();
delete deserialized;
}
Prints
22 serialization::archive 12 0 7 derived 1 0
0 100
v1: 10, v2: 100
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With