#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
. Они не обязательно должны находиться в том же файле, что и объявление класса. Просто включите заголовки перед регистрацией типов.