多级NVI的虚拟模板解决方法

时间:2015-11-29 18:18:48

标签: c++ type-erasure non-virtual-interface

我正在尝试构建一个类,它将作为我想要在我正在进行的私有项目中序列化的任何类型的基类。

我试图通过提供'<<<<<<<<<<<<<<<<&#和'>>'。任何其他可以与课程一起使用的流只是一个奖励。

重要 :我可能只会使用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

我立即发现虚拟模板不被允许并且符合新术语(对我而言)&#34;键入擦除&#34;。

我在阅读本文后尝试使用类型擦除:On the Tension Between Object-Oriented and Generic Programming in C++ and What Type Erasure Can Do About It(包括&#34;超越提升::任何&#34;)...

未成功。

一些注意事项:

Serializable_save&amp; 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

我的下一次尝试是埋葬档案&#39; StreamWrapper类中的模板(类似于类型擦除但不完全相同),以消除对模板的直接需求,并传递编译器关于虚拟模板的禁止操作&#39;无限问题。

当然,这不起作用。因为我最终需要指定模板类型,这与我试图实现的完全相反。

如果重要的话我会使用C ++ 14(我的意思是11到14之间)。

我仍然认为Type Erasure就是答案。我只是不明白如何使用它。

所以,

  • 是否有可能实现我想要的行为? 如果是的话:
  • 我如何才能实现一个允许这个&#34;多级NVI&#34;虚拟模板非法时的行为?

修改 我认为this可能是一个解决方案,但我还不能正确测试它。

0 个答案:

没有答案