I would like to use the cereal
library from this github page to load xml
into objects.
Up to this point everything is fine.
But in my application, it is a bit more complex: the object that needs to be loaded/filled by the xml
file, have to be accessed through polymorphic pointer.
Therefore, if a use a raw pointer, the cereal
lib refuse to take it, and ask for a smart pointer.
But, when I give a smart pointer to the generic load cereal
function (ie void serialize( Archive & ar )
related to cereal::XMLInputArchive::operator()
), it tries to load into the whole pointer itself rather than the pointing object.
Here is an MWE:
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <map>
#include <memory>
#include <cereal/archives/xml.hpp>
#include <cereal/types/memory.hpp>
#include <cereal/types/polymorphic.hpp>
using namespace std;
class SuperParentClass
{
public:
virtual std::string get_nameClass() =0;
virtual int run() = 0;
void serialize() ;
};
class ClassRectangle : public SuperParentClass
{
public:
std::string get_nameClass(){return "Rectangle";};
double length=0.;
double width=0.;
template <class Archive>
void serialize( Archive & ar )
{
ar( CEREAL_NVP( length ) );
ar( CEREAL_NVP( width ) );
}
int run()
{
std::cout << "I am a Rectangle with length "<<length<<" and width "<<width << std::endl;
return 0;
}
};
CEREAL_REGISTER_TYPE(ClassRectangle)
CEREAL_REGISTER_POLYMORPHIC_RELATION(SuperParentClass, ClassRectangle)
int main(void)
{
// Beginning of main.
cout << "(Start)" << endl;
// Loading from file Part.
{
cout << "Load " << endl;
std::ifstream is("input.xml");
cereal::XMLInputArchive arr(is);
ClassRectangle Rec;
arr( Rec ); // or // arr( cereal::make_nvp("Rectangle", Rec) );
Rec.run();
// Now, a bit more complex but closer to my application, because I need a polymorphic pointer !
std::unique_ptr<SuperParentClass> UPSPC(new ClassRectangle());
arr( cereal::make_nvp("Rectangle", UPSPC ) ); // ask for a polymorphic_id, it does not apply the right function
// arr( cereal::make_nvp("Rectangle", UPSPC.get() ) ); // exempt a smart pointer not a raw pointer
// arr( cereal::make_nvp("Rectangle", &UPSPC ) ); // exempt a smart pointer not a raw pointer
// arr( cereal::make_nvp("Rectangle", std::move(UPSPC) ) ); // ask for a polymorphic_id, it does not apply the right function
// arr( cereal::make_nvp("Rectangle", *UPSPC.get() ) ); // does not compile.
// arr( UPSPC ); // create an Segmentation Error, because cereal is looking for a polymorphic_id I guess.
UPSPC->run();
}
// End of the main.
cout << "(End) " << endl;
return 0;
}
// EoF
with input.xml
:
<?xml version="1.0" encoding="utf-8"?>
<cereal>
<Rectangle>
<length>2</length>
<width>11</width>
</Rectangle>
<Rectangle>
<length>12</length>
<width>10</width>
</Rectangle>
</cereal>
and the signature of make_nvp
from cereal.hpp
:
template <class T> inline
NameValuePair<T> make_nvp( std::string const & name, T && value )
{
return {name.c_str(), std::forward<T>(value)};
}
The exact error message of the above MWE is :
terminate called after throwing an instance of 'cereal::Exception'
what(): XML Parsing failed - provided NVP (polymorphic_id) not found
Abandon
So my question is: how can I pass the object, from a unique_ptr
, into the cereal
function by value ?
Or is there another way to work around this ?