boost serialization of struct derived from struct list - c++

I'm not sure how do i serialize a struct which derives from another struct of list type.
Below is sample code of what I'm asking :
//Nodes.hpp
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/optional.hpp>
#include <boost/serialization/list.hpp>
struct Node
{
std::string firstname;
std::string lastname;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & firstname;
ar & lastname;
}
};
struct Nodes : public std::list<Node>
{
std::string address;
std::string country;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & address;
ar & country;
}
};
BOOST_CLASS_EXPORT_KEY(Node);
BOOST_CLASS_EXPORT_KEY(Nodes);
BOOST_CLASS_EXPORT_IMPLEMENT(Nodes);
BOOST_CLASS_IMPLEMENTATION(Nodes,boost::serialization::object_serializable);
BOOST_CLASS_TRACKING(Nodes,boost::serialization::track_never);
Please look at the line "public std::list" and let me know if my serialization is correct or not.

I don't know what you wanted to ask. However I do know
it's not recommended to inherit from standard containers (they weren't designed for this)
if you do, you'll still have to specify you want the base class serialized:
struct Nodes : public std::list<Node>
{
std::string address;
std::string country;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & boost::serialization::base_object<std::list<Node> >(*this);
ar & address;
ar & country;
}
};
Of course, I'd suggest making the list a member intead of a base. Don't forget to include boost/serialization/list.hpp: see it Live On Coliru
#include <boost/serialization/serialization.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/optional.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <list>
struct Node
{
std::string firstname;
std::string lastname;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & firstname;
ar & lastname;
}
};
struct Nodes : public std::list<Node>
{
std::string address;
std::string country;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int version)
{
ar & boost::serialization::base_object<std::list<Node> >(*this);
ar & address;
ar & country;
}
};
BOOST_CLASS_EXPORT_KEY(Node);
BOOST_CLASS_EXPORT_KEY(Nodes);
BOOST_CLASS_EXPORT_IMPLEMENT(Nodes);
BOOST_CLASS_IMPLEMENTATION(Nodes , boost::serialization::object_serializable);
BOOST_CLASS_TRACKING(Nodes , boost::serialization::track_never);
int main()
{
boost::archive::text_oarchive oa(std::cout);
Nodes nodes;
nodes.address = "Mr.";
nodes.country = "Puerto Mazarique";
nodes.insert(nodes.end(), Node{"John", "Doe"});
nodes.insert(nodes.end(), Node{"Jane", "Greenwalt"});
nodes.insert(nodes.end(), Node{"Morgan", "Cheese"});
nodes.insert(nodes.end(), Node{"Walton", "Whiz"});
oa << nodes;
}

Related

Boost XML archiving compiling error with polymorphic classes

I am trying to save my files in XML format using boost archiving.
I get these two errors at compile time.
Error C2664 'int boost::mpl::assertion_failed(boost::mpl::assert::type)': cannot convert argument 1 from 'boost::mpl::failed ***********boost::serialization::is_wrapper:: ***********' to 'boost::mpl::assert::type'
Error C2789 'mpl_assertion_in_line_6': an object of const-qualified type must be initialized
This happens because of these two lines.
BOOST_CLASS_EXPORT_GUID(SumKeyframeXYZ, "SumKeyframeXYZ")
BOOST_CLASS_EXPORT_GUID(SumPosition_Channel, "SumPosition_Channel")
This is the Main function.
#include "Container.h"
BOOST_CLASS_EXPORT_GUID(SumKeyframeXYZ, "SumKeyframeXYZ")
BOOST_CLASS_EXPORT_GUID(SumPosition_Channel, "SumPosition_Channel")
int main()
{
std::ofstream ofs("D:\\output.xml");
Container cont;
cont.AddPositionChannel();
boost::archive::xml_oarchive oa(ofs);
oa << BOOST_SERIALIZATION_NVP(cont);
return 0;
}
This is how the classes structure looks like.
Container.h
#include <string>
#include "SumChannel.h"
#include "SumPosition_Channel.h"
#include <fstream>
#include <iostream>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/shared_ptr.hpp>
class Container
{
private:
std::string stdstrName;
std::vector<std::shared_ptr<SumChannel>> Channels;
public:
Container() { stdstrName = "Container Name"; }
void AddPositionChannel() {
std::shared_ptr< SumPosition_Channel> posChannel = std::make_shared<SumPosition_Channel>();
Channels.push_back(posChannel);
};
private:
friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar,
const unsigned int version) const {
ar & BOOST_SERIALIZATION_NVP(stdstrName);
ar & BOOST_SERIALIZATION_NVP(Channels);
}
};
//////////////////////////////////////////////////////////
SumChannel.h
#include <fstream>
#include <iostream>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/serialization/vector.hpp>
class SumChannel
{
public:
float offset;
SumChannel() { offset = 1.0; }
private:
friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar,
const unsigned int version) const {
ar & BOOST_SERIALIZATION_NVP(offset);
}
};
SumPosition_Channel
#include "SumKeyframeXYZ.h"
#include "SumChannel.h"
#include <vector>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/serialization/vector.hpp>
class SumPosition_Channel : public SumChannel
{
public:
std::vector<SumKeyframeXYZ> keyframes;
void AddKeyframe() { SumKeyframeXYZ key; keyframes.push_back(key); }
private:
friend class boost::serialization::access;
typedef SumChannel _Super;
template<class Archive> void serialize(Archive & ar,
const unsigned int version) const {
ar & boost::serialization::base_object<_Super>(*this);
ar & BOOST_SERIALIZATION_NVP(keyframes);
}
};
KeyFrameBase.h
#include <iostream>
#include <fstream>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
class Keyframebase
{
public:
std::string stdstrName;
float time;
Keyframebase() { stdstrName = "BaseKey"; time = 50.0; }
private:
friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar,
const unsigned int version) {
ar & BOOST_SERIALIZATION_NVP(stdstrName);
ar & BOOST_SERIALIZATION_NVP(time);
}
};
SumKeyframeXYZ.h
#include "KeyframeBase.h"
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/serialization/vector.hpp>
class SumKeyframeXYZ : public Keyframebase
{
public:
float x;
float y;
float z;
SumKeyframeXYZ() { x = 150.0; y = 200.0; z = 300.0; }
private:
friend class boost::serialization::access;
template<class Archive> void serialize(Archive & ar,
const unsigned int version) const {
ar & boost::serialization::base_object<Keyframebase>(*this);
ar & BOOST_SERIALIZATION_NVP(x);
ar & BOOST_SERIALIZATION_NVP(y);
ar & BOOST_SERIALIZATION_NVP(z);
}
};
The issue with the code was that i was not writing NVP to the base class
I changed the Base class archiving code from
ar & boost::serialization::base_object<_Super>(*this);
to this for all the base classes.
typedef SumChannel _Super;
ar & boost::serialization::make_nvp("SumChannel", boost::serialization::base_object<_Super>(*this));
and removed the const from the serilize function.

deserialization from an abstract base fails for boost serialization

I'm able to serialize an object through an abstract base using boost::serialization. However, when I try to add deserialization, I get compile errors about the abstract base. Here's my serialization code that works:
/*
g++ -Iinclude/ -Llib -lboost_serialization ~/Desktop/ser_ex.cpp -o stest
*/
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <boost/serialization/export.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <memory>
namespace bser = boost::serialization;
using namespace std;
namespace foo {
class AA
{
public:
virtual void foo() = 0;
virtual ~AA() {}
std::string name;
template<class Archive>
void serialize(Archive & ar, unsigned int )
{
ar & name;
}
};
BOOST_SERIALIZATION_ASSUME_ABSTRACT( AA );
class BB : public AA
{
public:
virtual void foo() = 0;
virtual void bar() = 0;
virtual ~BB () {}
int thing;
template<class Archive>
void serialize(Archive & ar, unsigned int )
{
ar.template register_type< AA >();
ar & boost::serialization::base_object<AA>(*this);
ar & thing;
}
};
BOOST_SERIALIZATION_ASSUME_ABSTRACT( BB );
class CC : public BB
{
public:
virtual void foo() {}
virtual void bar() {}
virtual ~CC() {}
int otherThing;
template<class Archive>
void serialize(Archive & ar, unsigned int )
{
ar.template register_type< BB >();
ar & boost::serialization::base_object<BB>(*this);
ar & otherThing;
}
};
}
BOOST_CLASS_EXPORT_KEY(foo::CC)
BOOST_CLASS_EXPORT_IMPLEMENT(foo::CC)
int main (int , char const **)
{
std::vector< shared_ptr<foo::AA> > vv;
vv.push_back( make_shared<foo::CC>() );
std::ostringstream oss;
boost::archive::binary_oarchive out_archive( oss );
out_archive << vv;
std::cout << oss.str() << std::endl;
}
Just add this line right below the include for binary_oarchive.hpp causes the code not to compile.
#include <boost/archive/binary_iarchive.hpp>
dawilcox-macOS:debug dawilcox$ make foo
dependencies: foo_main.o
building: foo_main.o
In file included from /Users/dawilcox/src/axle/foo_main.cpp:5:
In file included from /usr/local/include/boost/serialization/serialization.hpp:43:
/usr/local/include/boost/serialization/access.hpp:130:17: error: allocating an object of abstract class type 'foo::AA'
::new(t)T;
Boost is complaining that it can't instantiate my base type. That's kind of the point -- it's an abstract base type.
What's the proper way to deserialize an abstract base?
Looks like the thing I have wrong is that I was registering against the base class in the deserialize function. So, I got rid of:
ar.template register_type< AA >();
and changed
ar.template register_type< BB >();
to
ar.template register_type< CC >();
Here's my full code:
/*
g++ -Iinclude/ -Llib -lboost_serialization ~/Desktop/ser_ex.cpp -o stest
*/
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <OMNIMAKE/lib/boost_serialization>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <boost/serialization/export.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <memory>
namespace bser = boost::serialization;
using namespace std;
namespace foo {
class AA
{
public:
virtual void foo() = 0;
virtual ~AA() {}
std::string name;
template<class Archive>
void serialize(Archive & ar, unsigned int )
{
ar & name;
}
};
BOOST_SERIALIZATION_ASSUME_ABSTRACT( AA );
class BB : public AA
{
public:
virtual void foo() = 0;
virtual void bar() = 0;
virtual ~BB () {}
int thing;
template<class Archive>
void serialize(Archive & ar, unsigned int )
{
ar & boost::serialization::base_object<AA>(*this);
ar & thing;
}
};
BOOST_SERIALIZATION_ASSUME_ABSTRACT( BB );
class CC : public BB
{
public:
virtual void foo() {}
virtual void bar() {}
virtual ~CC() {}
int otherThing;
template<class Archive>
void serialize(Archive & ar, unsigned int )
{
ar.template register_type< CC >();
ar & boost::serialization::base_object<BB>(*this);
ar & otherThing;
}
};
}
BOOST_CLASS_EXPORT_KEY(foo::CC)
BOOST_CLASS_EXPORT_IMPLEMENT(foo::CC)
int main (int , char const **)
{
std::vector< shared_ptr<foo::AA> > vv;
vv.push_back( make_shared<foo::CC>() );
std::ostringstream oss;
boost::archive::binary_oarchive out_archive( oss );
out_archive << vv;
std::cout << oss.str() << std::endl;
}

Simple extension of boost::archive::text_oarchive

I am trying to add a member variable to a Boost archive class. Following this, I came up with:
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <fstream>
class MyOArchive : public boost::archive::text_oarchive_impl<MyOArchive>
{
public:
bool MyData;
friend class boost::archive::detail::common_oarchive<MyOArchive>;
friend class basic_text_oarchive<MyOArchive>;
//friend class boost::serialization::save_access; // save_access in namespace boost::serialization does not name a type
MyOArchive(std::ostream& os, unsigned int flags = 0) : boost::archive::text_oarchive_impl<MyOArchive>(os, flags) {}
};
class MyClass
{
public:
private:
friend class boost::serialization::access;
double Value;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & Value;
}
};
int main()
{
MyClass myClass;
std::ofstream outputStream("test.txt");
//boost::archive::text_oarchive outputArchive(outputStream);
MyOArchive outputArchive(outputStream);
outputArchive << myClass;
outputStream.close();
return 0;
}
However, I am getting linker errors:
undefined reference to boost::archive::text_oarchive_impl<MyOArchive>::text_oarchive_impl(std::ostream&, unsigned int)
Can anyone explain what is going wrong here? I don't need to reimplement any of the functions of the archive, just attach this member MyData.
Ah. Spotted it.
You need to include the ipps for the basic implementations in exactly one TU that's linked into the end product.
#include <boost/archive/impl/basic_text_oarchive.ipp>
#include <boost/archive/impl/text_oarchive_impl.ipp>
Also, save_access lives in a different castle namespace:
friend class boost::archive::save_access;
Live On Coliru
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/impl/basic_text_oarchive.ipp>
#include <boost/archive/impl/text_oarchive_impl.ipp>
#include <fstream>
class MyOArchive : public boost::archive::text_oarchive_impl<MyOArchive> {
public:
bool MyData;
friend class boost::archive::detail::common_oarchive<MyOArchive>;
friend class basic_text_oarchive<MyOArchive>;
friend class boost::archive::save_access;
MyOArchive(std::ostream &os, unsigned int flags = 0) : boost::archive::text_oarchive_impl<MyOArchive>(os, flags) {}
};
class MyClass {
private:
friend class boost::serialization::access;
double Value;
template <class Archive> void serialize(Archive &ar, unsigned) { ar &Value; }
};
int main() {
MyClass myClass;
{
std::ofstream outputStream("test.txt");
MyOArchive outputArchive(outputStream);
outputArchive << myClass;
}
}
The output is
22 serialization::archive 13 0 0 6.95328877045326431e-310

how to serialize list of type shared_ptr pointer type using boost serialization

i'm trying to serialize class which has member variable of type like std::list> lss
#include <boost/serialization/optional.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/list.hpp>
struct SomeStruct
{
int x;
double y;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &at, const unsigned int version)
{
at & x;
at & y;
}
};
class BuildTest
{
std::list<boost::shared_ptr<SomeStruct *>> lss ;
std::string name;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &at, const unsigned int version)
{
at & lss; // is this sufficient to serialize lss ?
at & name;
}
}
i have added all required header files for boost serialization. There is similar question but with proper answer how do i serialize list variable of type <boost::shared_ptr<void *>>
You want
std::list<boost::shared_ptr<SomeStruct>> lss ;
Not std::list<boost::shared_ptr<SomeStruct*>>
See it Live On Coliru
#include <boost/serialization/optional.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/list.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/make_shared.hpp>
struct SomeStruct {
int x;
double y;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &at, const unsigned int version) {
at & x;
at & y;
}
};
class BuildTest {
public:
std::list<boost::shared_ptr<SomeStruct>> lss ;
std::string name;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &at, const unsigned int version) {
at & lss; // is this sufficient to serialize lss ?
at & name;
}
};
int main() {
BuildTest bt;
bt.name = "Let's try this";
bt.lss = { boost::make_shared<SomeStruct>(), boost::make_shared<SomeStruct>() };
boost::archive::text_oarchive oa(std::cout);
oa << bt;
}

Boost serilaization with shared pointer and templates

I'm new to C++ and how do i serialize the struct having shared pointer and template .
Below is sample code.
#pragma once
#include <boost/serialization/access.hpp>
#include <boost\serialization\string.hpp>
#include <boost\serialization\shared_ptr.hpp>
//Mydata.hpp file
namespace mydata
{
struct MyData
{
std::string name;
std::string type;
std::shared_ptr<MyInfo> myref;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int vs)
{
ar & name;
ar & type;
ar & myref;
}
}
}
now how do i implement in the corresponding Mydata.cpp file for shared pointer ?
That header includes support for boost::shared_ptr, so the following works:
#include <boost/serialization/access.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/smart_ptr/make_shared.hpp>
namespace mydata
{
struct MyInfo
{
std::string info = "extra info";
MyInfo(std::string info) : info(std::move(info)) {}
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int /*version*/)
{
ar & info;
}
};
struct MyData
{
std::string name;
std::string type;
boost::shared_ptr<MyInfo> myref;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive &ar, const unsigned int /*version*/)
{
ar & name;
ar & type;
ar & myref;
}
};
}
int main()
{
using namespace mydata;
MyData data { "this is a name", "this is a type", boost::make_shared<MyInfo>("this is info") };
boost::archive::text_oarchive oa(std::cout);
oa << data;
}
See it Live On Coliru