Использование Cereal для сериализации шаблонных полиморфных типов в библиотеке

#c #templates #cereal

#c #шаблоны #cereal

Вопрос:

У меня есть шаблонный базовый класс:

 template<typename T>
class A {
    public:
    T a;

    template<class Archive>
    void serialize(Archive amp; ar) {
        ar(a);
    }
};
  

и шаблонный класс, который является производным от него:

 template<typename T>
class B : public A<T> {
    public:
    T b;

    template<class Archive>
    void serialize(Archive amp; ar) {
        ar(cereal::base_class<A<T>>(this));
        ar(b);
    }
};
  

Он используется в другом сериализованном классе:

 template<typename T>
class C {

    template<class Archive>
    void serialize(Archive amp; ar)
    {
        ar(collection);
    }

    std::vector<std::shared_ptr<A<T>>> collection;
};
  

Этот код и код, который его использует, скомпилирован в статическую библиотеку

Исходя из моего понимания документации cereal, мне нужно добавить

 CEREAL_REGISTER_TYPE(A<double>)
CEREAL_REGISTER_TYPE(A<float>)

CEREAL_REGISTER_TYPE(B<double>)
CEREAL_REGISTER_TYPE(B<float>)
  

и т.д. для каждого типа, который будет использоваться, в файлах заголовков для каждого класса

Это компилируется. Но имеет ошибку времени выполнения

Пытаюсь сохранить незарегистрированный полиморфный тип (B). Перед вызовом CEREAL_REGISTER_TYPE убедитесь, что ваш тип зарегистрирован в CEREAL_REGISTER_TYPE и что используемый вами архив был включен (и зарегистрирован в CEREAL_REGISTER_ARCHIVE). Если ваш тип уже зарегистрирован, и вы все еще видите эту ошибку, возможно, вам потребуется использовать CEREAL_REGISTER_DYNAMIC_INIT.

Из документов я думаю, что мне нужно добавить CEREAL_FORCE_DYNAMIC_INIT(libname) в заголовки и CEREAL_REGISTER_DYNAMIC_INIT в файл CPP, но файла cpp нет. Или подходящий CPP-файл для размещения этого.

Добавление CEREAL_REGISTER_POLYMORPHIC_RELATION не имеет никакого значения, как и ожидалось, поскольку B функция сериализации вызывает базовый calss A с cereal::base_class помощью Есть ли способ использовать Cereal для сериализации шаблонных классов?

Комментарии:

1. Извините, ошибка транскрипции, пропустил <T> .

2. Типы в ваших примерах не кажутся полиморфными … действительно ли они отражают ваш реальный код? Если да, то это странная ошибка

3. Вы следили за документацией ? Использовали ли вы CEREAL_REGISTER_POLYMORPHIC_RELATION (если это необходимо; я совершенно не знаком с cereal)? Я согласен с xaxxon, что опубликованный вами код не является полиморфным.

4. Согласно документам CEREAL_REGISTER_POLYMORPHIC_RELATION требуется только в том случае, если подкласс не вызывает базовый класс с помощью cereal::base_class. Что я и делаю.

5. Обновлено, чтобы показать полиморфное использование.

Ответ №1:

Проблема заключалась в порядке включенных заголовков и в том, куда они были включены, плюс небольшое количество тщательно обработанных RTFM.

Необходим заголовок базового класса:

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

плюс любые другие типы, которые я хочу сериализовать.

Затем в подклассах добавьте CEREAL_REGISTER_TYPE для каждого поддерживаемого типа.

Ключевым моментом, как отмечено в документации, является то, что тип архива включен ПЕРЕД CEREAL_REGISTER_TYPE . Они не обязательно должны находиться в том же файле, что и объявление класса. Просто включите заголовки перед регистрацией типов.