Non-Intrusive Polymorphic Serialization Example w/Macros
The full code for this magistrate example can be found here: examples/checkpoint_example_polymorphic_macro_nonintrusive.cc
Example source code:
#include <checkpoint/checkpoint.h> #include "checkpoint/dispatch/dispatch_virtual.h" // \brief Namespace containing types which will be serialized namespace checkpoint { namespace nonintrusive { namespace examples { // \struct Abstract base class struct MyBase { MyBase() { printf("MyBase cons\n"); } explicit MyBase(::checkpoint::SERIALIZE_CONSTRUCT_TAG) { printf("MyBase recons\n"); } virtual ~MyBase() = default; // Add serializing macro magistrate_virtual_serialize_root() int val_ = 0; virtual void test() = 0; }; struct MyObj : public MyBase { explicit MyObj(int val) : MyBase() { printf("MyObj cons\n"); val_ = val;} explicit MyObj(::checkpoint::SERIALIZE_CONSTRUCT_TAG) {} // Add macro for serialization magistrate_virtual_serialize_derived_from(MyBase) void test() override { printf("test MyObj 10 == %d ?\n", val_); assert(val_ == 10); } }; struct MyObj2 : public MyBase { explicit MyObj2(int val) { printf("MyObj2 cons\n"); val_=val; } explicit MyObj2(::checkpoint::SERIALIZE_CONSTRUCT_TAG) {} // Add macro for serialization magistrate_virtual_serialize_derived_from(MyBase) void test() override { printf("test MyObj2 20 == %d ?\n", val_); assert(val_ == 20); } }; struct MyObj3 : public MyBase { int a=0, b=0, c=0; explicit MyObj3(int val) { printf("MyObj3 cons\n"); a= 10; b=20; c=100; val_=val;} explicit MyObj3(::checkpoint::SERIALIZE_CONSTRUCT_TAG) {} // Add macro for serialization magistrate_virtual_serialize_derived_from(MyBase) void test() override { printf("val_ 30 a 10 b 20 c 100 = %d %d %d %d\n", val_, a, b, c); assert(val_ == 30); assert(a==10); assert(b==20); assert(c==100); } }; struct ExampleVector { std::vector<std::unique_ptr<MyBase>> vec; }; void test() { ExampleVector v; v.vec.push_back(std::make_unique<MyObj3>(30)); v.vec.push_back(std::make_unique<MyObj2>(20)); v.vec.push_back(std::make_unique<MyObj>(10)); auto ret = checkpoint::serialize(v); { // Display information about serialization result auto const& buf = ret->getBuffer(); auto const& buf_size = ret->getSize(); printf("ptr=%p, size=%ld\n*****\n\n", static_cast<void*>(buf), buf_size); } auto t = checkpoint::deserialize<ExampleVector>(ret->getBuffer()); for (auto&& elm : t->vec) { elm->test(); } } }}} // end namespace checkpoint::nonintrusive::examples // \brief In Non-Intrusive way, serialize function needs to be placed in the namespace // of the type which will be serialized. namespace checkpoint { namespace nonintrusive { namespace examples { template <typename S> void serialize(S& s, MyBase& obj) { s | obj.val_; printf("MyBase: serialize val %d\n", obj.val_); } template <typename SerializerT> void serialize(SerializerT&, MyObj&) { printf("MyObj: serialize\n"); } template <typename SerializerT> void serialize(SerializerT&, MyObj2&) { printf("MyObj2: serialize\n"); } template <typename SerializerT> void serialize(SerializerT& s, MyObj3& obj) { s | obj.a; s | obj.b; s | obj.c; printf("MyObj3: serialize a b c %d %d %d\n", obj.a, obj.b, obj.c); } template <typename SerializerT> void serialize(SerializerT& s, ExampleVector& obj) { s | obj.vec; } }}} // end namespace checkpoint::nonintrusive::examples int main(int, char**) { using namespace magistrate::nonintrusive::examples; test(); return 0; }