Using Cereal to serialize templated polymorphic types in a library

c++, cereal, templates

Solution

Issue came down to the order of the included headers and where they were included, plus a small amount of RTFM carefully.

In base class header needed:

#include <cereal/types/polymorphic.hpp>
#include <cereal/archives/portable_binary.hpp>

plus any other types I want to serialize to.

Then in subclasses add `CEREAL_REGISTER_TYPE` for each supported type.

The key, as noted in the documentation, is that the type of archive is included BEFORE `CEREAL_REGISTER_TYPE`. They do not have to be in the same file as the class declaration. Just include headers before registering types.

Problem

I have a templated base class: ``` template<typename T> class A { public: T a; template<class Archive> void serialize(Archive & ar) { ar(a); } }; ``` and a templated class that derives from it: ``` template<typename T> class B : public A<T> { public: T b; template<class Archive> void serialize(Archive & ar) { ar(cereal::base_class<A<T>>(this)); ar(b); } }; ``` It is used in another serialized class: ``` template<typename T> class C { template<class Archive> void serialize(Archive & ar) { ar(collection); } std::vector<std::shared_ptr<A<T>>> collection; }; ``` This code and the code that uses it is compiled into a static lib From my understanding of the cereal docs I need to add ``` CEREAL_REGISTER_TYPE(A<double>) CEREAL_REGISTER_TYPE(A<float>) CEREAL_REGISTER_TYPE(B<double>) CEREAL_REGISTER_TYPE(B<float>) ``` etc for each type that will be used, in the header files for each class This compiles. But has a run time error of Trying to save an unregistered polymorphic type (B). Make sure your type is registered with CEREAL_REGISTER_TYPE and that the archive you are using was included (and registered with CEREAL_REGISTER_ARCHIVE) prior to calling CEREAL_REGISTER_TYPE. If your type is already registered and you still see this error, you may need to use CEREAL_REGISTER_DYNAMIC_INIT. From the docs I think I need to add `CEREAL_FORCE_DYNAMIC_INIT(libname)` in the headers and `CEREAL_REGISTER_DYNAMIC_INIT` in the CPP file, but there is no cpp file. Or a suitable CPP file to place this in. Adding `CEREAL_REGISTER_POLYMORPHIC_RELATION` makes no difference as expected as `B`'s serialization function is calling the base calss `A` with `cereal::base_class` Is there a way to use Cereal to serialize templated classes?

Original source