Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 用于多级NVI的虚拟模板解决方案_C++_Type Erasure_Non Virtual Interface - Fatal编程技术网

C++ 用于多级NVI的虚拟模板解决方案

C++ 用于多级NVI的虚拟模板解决方案,c++,type-erasure,non-virtual-interface,C++,Type Erasure,Non Virtual Interface,我正在尝试构建一个类,该类将作为我要在私有项目中序列化的任何类型的基类 我正试图通过为“”提供功能,使该类至少能够使用boost序列化存档和QDataStream。任何其他与类一起工作的流都只是一个奖励 重要:我可能只使用QDataStream。我把这门课更多地作为一个谜题/学习机会(这似乎是可行的),因此,即使是完全偏离这一形式的变通方法,我也会很感激,如果事情能够按照我希望的方式进行(当然,考虑到语言的限制,尽可能接近),在途中获得一些知识 正如我所想的那样,这门课应该是: #ifndef

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

我正试图通过为“”提供功能,使该类至少能够使用boost序列化存档和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
#如果可序列化#
#定义可序列化的
#包括
#包括
#包括
#包括
#包括
#包括
//#包括boost stl容器处理程序。。。
类可序列化:公共QObject
{
Q_对象
模板
虚拟空可序列化存储(存档和输出,常量quint32 p_版本=0)=0;
模板
虚拟void可序列化加载(存档和输入,常量quint32 p_版本=0)=0;
32个m_ID;
16 m_版本;
公众:
显式可序列化(QObject*parent=0):QObject(parent){}
BOOST_SERIALIZATION_SPLIT_MEMBER()
模板
无效保存(存档和输出,常量quint32 p_版本=0)
{
out m_ID>>m_版本;
可序列化的_加载(in,p_版本);
}
quint32 ID()常量;
void setID(const quint32&ID);
quint16 version()常量;
无效设置版本(常量和版本);
};
模板
存档和操作员>(存档和输入、可序列化和模块)
{
模块负载(in);
返回;
}
#endif//SERIALIZABLE_H
我立即发现虚拟模板是不允许的,并且符合新的术语(对我来说)“类型擦除”

读了这篇文章后,我尝试使用类型擦除:(直到并包括“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
\ifndef数据模块
#定义数据模块
#包括
类DataModule_I:可公开序列化
{
模板
虚拟无效数据模块保存(存档和输出)=0;
模板
虚拟无效数据模块加载(存档和输入)=0;
模板
虚拟void可序列化_保存(存档和输出)最终版本
{
//一些先决条件。
数据模块保存(输出);
//一些后置条件。
}
模板
虚拟void可序列化_加载(存档和加载)最终
{
//一些先决条件。
数据模块负载(in);
//一些后置条件。
}
公众:
显式数据模块_I(常量quint32 ID,QObject*parent=0);
};
#endif//DATAMODULE\u I\u H
我的下一个尝试是将“归档”模板埋在StreamWrapper类中(类似于类型擦除,但不完全如此),以消除对模板的直接需求,并解决编译器关于虚拟模板无限大的问题

当然,这是行不通的。因为我最终需要指定模板类型,这与我试图实现的正好相反

如果重要的话,我使用的是C++14(我的意思是介于11和14之间)

我仍然认为类型擦除是答案。我只是不知道怎么用它

所以

  • 有可能实现我想要的行为吗? 如果是:
  • 当虚拟模板非法时,如何实现允许这种“多级NVI”行为的类
编辑:
我认为这可能是一个解决方案,但我还无法对其进行适当的测试。

您可能需要了解boost多态性archives@n.m.谢谢你的指针:)还要探索boost序列化如何处理通过基类指针序列化的派生类(使用常规的非多态存档)。@n.m.你是在暗示我犯了一个错误吗?我知道boost序列化使用“base_object”,但我认为这样做更好。尽管我真的不确定——并试图弄清楚——我的方法是否会打破重复检查……更不用说流方向对于确保公共部分(从基类)序列化至关重要-除非我在每一个类中手动指定它们,否则我认为不能反向执行…您可能想看看boost多态性archives@n.m.感谢指针:)还探索boost序列化如何处理通过基类指针序列化的派生类(使用常规非多态存档)@n.m.你是在暗示我犯了一个错误吗?我知道boost序列化使用“base_object”,但我认为这样做更好。尽管我真的不确定——并试图弄清楚——我的方法是否会打破重复检查……更不用说,流方向对于确保公共部分(从基类)序列化是至关重要的——我相信,除非我在每个类中手动指定它们,否则不能反向执行。。。