Skip to content

Instantly share code, notes, and snippets.

@vvrs
Last active September 22, 2021 02:34
Show Gist options
  • Save vvrs/023353fa1d4890fa666b50db7153fba9 to your computer and use it in GitHub Desktop.
Save vvrs/023353fa1d4890fa666b50db7153fba9 to your computer and use it in GitHub Desktop.
cereal with multi-level polymorphism
#include "derived_class_1.h"
#include <iostream>
void DerivedClassOne::sayType()
{
std::cout << "DerivedClassOne " << x <<std::endl;
std::cout << "Call say type from DerivedClassOne's children " <<std::endl;
sayType2();
}
#pragma once
#include "myclasses.h"
// A class derived from BaseClass
struct DerivedClassOne : public BaseClass
{
void sayType() override;
char x{'x'};
template<class Archive>
void serialize( Archive & ar )
{ ar( x ); }
private:
virtual void sayType2() = 0;
};
// Include any archives you plan on using with your type before you register it
// Note that this could be done in any other location so long as it was prior
// to this file being included
#include <cereal/archives/binary.hpp>
#include <cereal/archives/xml.hpp>
#include <cereal/archives/json.hpp>
// Register DerivedClassOne
CEREAL_REGISTER_TYPE(DerivedClassOne);
// Note that there is no need to register the base class, only derived classes
// However, since we did not use cereal::base_class, we need to clarify
// the relationship (more on this later)
CEREAL_REGISTER_POLYMORPHIC_RELATION(BaseClass, DerivedClassOne)
#include "derived_class_2.h"
#include <iostream>
void DerivedClassTwo::sayType2()
{
std::cout << "DerivedClassTwo " << z <<std::endl;
}
#pragma once
#include "derived_class_1.h"
// A class derived from BaseClass
struct DerivedClassTwo : public DerivedClassOne
{
void sayType2() override;
int z{2};
template<class Archive>
void serialize( Archive & ar )
{ ar( z ); }
};
CEREAL_REGISTER_TYPE(DerivedClassTwo);
CEREAL_REGISTER_POLYMORPHIC_RELATION(BaseClass, DerivedClassTwo)
#include "derived_class_3.h"
#include <iostream>
void DerivedClassThree::sayType2()
{
std::cout << "DerivedClassThree " << kkk <<std::endl;
}
#pragma once
#include "derived_class_1.h"
struct DerivedClassThree : public DerivedClassOne
{
void sayType2() override;
float kkk{3.14};
template<class Archive>
void serialize( Archive & ar )
{ ar( kkk ); }
};
CEREAL_REGISTER_TYPE(DerivedClassThree);
CEREAL_REGISTER_POLYMORPHIC_RELATION(BaseClass, DerivedClassThree)
// any archives included prior to 'myclasses.hpp'
// would also apply to the registration
#include "myclasses.h"
#include "derived_class_1.h"
#include "derived_class_2.h"
#include "derived_class_3.h"
#include <cereal/archives/xml.hpp>
#include <cereal/types/polymorphic.hpp>
#include <iostream>
#include <fstream>
int main()
{
{
std::ofstream os( "polymorphism_test.xml" );
cereal::XMLOutputArchive oarchive( os );
// Create instances of the derived classes, but only keep base class pointers
std::shared_ptr<BaseClass> ptr2 = std::make_shared<DerivedClassTwo>();
std::shared_ptr<BaseClass> ptr3 = std::make_shared<DerivedClassThree>();
oarchive(ptr2, ptr3);
}
{
std::ifstream is( "polymorphism_test.xml" );
cereal::XMLInputArchive iarchive( is );
// De-serialize the data as base class pointers, and watch as they are
// re-instantiated as derived classes
// std::shared_ptr<BaseClass> ptr1;
std::shared_ptr<BaseClass> ptr2;
std::shared_ptr<BaseClass> ptr3;
iarchive( /*ptr1,*/ ptr2, ptr3);
// Ta-da! This should output:
// ptr1->sayType(); // "DerivedClassOne"
ptr2->sayType(); // "EmbarrassingDerivedClass. Wait.. I mean DerivedClassTwo!"
ptr3->sayType(); // "EmbarrassingDerivedClass. Wait.. I mean DerivedClassTwo!"
}
return 0;
}
#pragma once
// Include the polymorphic serialization and registration mechanisms
#include <cereal/types/polymorphic.hpp>
// A pure virtual base class
struct BaseClass
{
virtual void sayType() = 0;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment