Виртуальный шаблонный обходной путь для многоуровневого NVI

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

Я пытаюсь заставить класс работать, по крайней мере, с улучшенными архивами сериализации и 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 является ответом. Я просто не понимаю, как его использовать.

Так,

  • Можно ли добиться желаемого поведения?
    Если да:
  • Как я могу получить класс, который разрешит такое поведение «Multilevel NVI», когда виртуальные шаблоны недопустимы?

РЕДАКТИРОВАТЬ:
Я думаю этот может быть решением, но я пока не могу правильно его проверить.

1

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]