Я пытаюсь создать класс, который будет действовать как базовый класс для любого типа, который я хочу сериализовать в частном проекте, который я делаю.
Я пытаюсь заставить класс работать, по крайней мере, с улучшенными архивами сериализации и QDataStream, предоставляя функциональность для<<‘и’ >> ‘. Любой другой поток, который будет работать с классом, является просто бонусом.
Важный: Я, вероятно, буду использовать только QDataStream. Я строю этот класс больше как загадку / возможность учиться (что, кажется, работает), поэтому, хотя я был бы признателен даже за обходные пути, которые полностью отклоняются от этой формы, мне бы очень понравилось, если бы все могло работать так, как я хотел (как можно ближе к возможному, учитывая ограничения языка, конечно). ), получая некоторые знания на пути.
Класс как я думал это было бы:
#ifndef SERIALIZABLE_H
#define SERIALIZABLE_H
#include <QObject>
#include <QDataStream>
#include <boost/serialization/access.hpp>
#include <boost/serialization/version.hpp>
#include <boost/serialization/base_object.hpp>
#include <boost/serialization/split_member.hpp>
// #include boost stl containers handlers...
class Serializable : public QObject
{
Q_OBJECT
template <typename Archive>
virtual void Serializable_save( Archive &out, const quint32 p_version = 0 ) = 0;
template <typename Archive>
virtual void Serializable_load( Archive &in, const quint32 p_version = 0 ) = 0;
quint32 m_ID;
quint16 m_version;
public:
explicit Serializable( QObject *parent = 0 ) : QObject( parent ) {}
BOOST_SERIALIZATION_SPLIT_MEMBER()
template <typename Archive>
void save( Archive &out, const quint32 p_version = 0 )
{
out << m_ID << m_version;
Serializable_save( out, p_version );
}
template <typename Archive>
void load( Archive &in, const quint32 p_version = 0 )
{
in >> m_ID >> m_version;
Serializable_load( in, p_version );
}
quint32 ID() const;
void setID( const quint32 &ID );
quint16 version() const;
void setVersion( const quint16 &version );
};
template <typename Archive>
Archive &operator << ( Archive &out, const Serializable &module )
{
module.save( out );
return out;
}
template <typename Archive>
Archive &operator >> ( Archive &in, Serializable &module )
{
module.load( in );
return in;
}
#endif // SERIALIZABLE_H
Я сразу обнаружил, что виртуальные шаблоны не разрешены, и встретил новый термин (для меня) «стирание типов».
Я попытался использовать стирание типа после прочтения этой статьи: О напряженности между объектно-ориентированным и общим программированием в C ++
и какой тип Erasure может с этим поделать (вплоть до «Beyond boost :: any») …
Неудачно.
Несколько заметок:
Serializable_save & Serializable_load являются частью соглашения об именах, которое идет вниз по наследству и допускает многоуровневый NVI.
(Многоуровневый NVI — это просто имя, которое я дал для концепции завершения виртуальной функции, унаследованной от базового класса, и предоставления новой виртуальной функции для наследников. Возможность набора действий, которые всегда выполняются на протяжении всей цепочки наследования)
Это означает, что наследующий класс, который не является конечным классом, будет выглядеть так:
#ifndef DATAMODULE_I_H
#define DATAMODULE_I_H
#include <StorageGateway/serializable.h>
class DataModule_I : public Serializable
{
template <typename Archive>
virtual void DataModule_I_save( Archive &out ) = 0;
template <typename Archive>
virtual void DataModule_I_load( Archive &in ) = 0;
template <typename Archive>
virtual void Serializable_save( Archive &out ) final
{
// Some preconditions.
DataModule_I_save( out );
// Some postconditions.
}
template <typename Archive>
virtual void Serializable_load( Archive &in ) final
{
// Some preconditions.
DataModule_I_load( in );
// Some postconditions.
}
public:
explicit DataModule_I( const quint32 ID, QObject *parent = 0 );
};
#endif // DATAMODULE_I_H
Моя следующая попытка заключалась в том, чтобы похоронить шаблоны «Архив» внутри класса StreamWrapper (аналогично стиранию типов, но не совсем так), чтобы исключить насущную необходимость в шаблоне и пропустить бесконечную проблему компилятора в отношении виртуальных шаблонов.
Конечно, это не сработало. В итоге мне пришлось указать типы шаблонов, что в точности противоположно тому, чего я пытался достичь.
Я использую C ++ 14, если это имеет значение (между 11 и 14, я имею в виду).
Я все еще предполагаю, что Тип Erasure является ответом. Я просто не понимаю, как его использовать.
Так,
РЕДАКТИРОВАТЬ:
Я думаю этот может быть решением, но я пока не могу правильно его проверить.
Задача ещё не решена.
Других решений пока нет …