Using Cereal to serialize templated polymorphic types in a library

时间:2016-10-20 12:47:05

标签: c++ templates cereal

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?

1 个答案:

答案 0 :(得分:2)

问题归结为所包含标题的顺序及其包含的位置,以及少量的RTFM。

在需要的基类标题中:

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

加上我想要序列化的任何其他类型。

然后在子类中为每个支持的类型添加CEREAL_REGISTER_TYPE

如文档中所述,密钥是归档类型 BEFORE CEREAL_REGISTER_TYPE。它们不必与类声明位于同一文件中。只需在注册类型之前包含标题。