【问题标题】:How to handle different templates in a similar way?如何以类似的方式处理不同的模板?
【发布时间】:2020-12-17 04:28:56
【问题描述】:

我已经处理了几天的问题,但仍然没有适当的解决方案。想象一下,我有几种(数量可能不同)乐器。每个仪器产生不同类型的数据。对于每种乐器,我都有一个结构(我在这里展示了非常简单的近似值):

struct TInstrument1 {
    int Variable1;
    int Variable2;
}

struct TInstrument2 {
    int Variable3;
} 

我正在尝试创建一种数据库来查看可用数据。我这样做的方法如下:

首先,我有一个做文件映射的类。我在 Windows 上编程,所以我在 MapFile 函数中使用 CreateFileCreateFileMappingMapViewOdFile 函数:

template <class SType> class TFileMapping {

    HANDLE    hFile;
    HANDLE    hFileMap;

    SType  *  MapView;

    TFileMapping();
    ~TFileMapping();

    void MapFile(String FileName,DWORD FileAccessType,DWORD FileSharing,DWORD MappingAccessType,DWORD MapViewAccessType,DWORD FlagsAndAttributes,DWORD CreationDisposition,size_t ByteNum);
    void UnMapFile();

};

然后在TMapVector结构中使用这个类(我给出一个简化版本):

template <class SType> struct TMMapVector : public TFileMapping<SType> {

    String MappedFileName;

    unsigned int   * AssignedLen;
    unsigned int   * Num;
    SType          * Data;

    TMMapVector();
    ~TMMapVector();

    void   MapVector(String FileName);
    void   AppendItem(SType * Val);
    
    int    size();

};

这个想法是,例如TMapVector&lt;Instrument1&gt; 创建/打开一个与Instrument1 对应的数据库文件,并包含一个Instrument1 类型的对象。

现在我的问题是我不知道用户拥有多少种仪器。目前有 3 个,但代码应该很容易扩展到更多的仪器类型。目前我处理如下。我有一个课程TFileInfo 有两种乐器类型,但只有一个被填满。这让我可以进一步使用std::vector&lt;TFileInfo&gt;。这种方法的问题在于,每次我需要使用仪器做某事时,我都必须使用 switch 语句:

struct TFileInfo {

    TMMapVector<TInstrument1>  Instrument1;
    TMMapVector<TInstrument2>  Instrument2;

};

struct TDataBase {
    std::vector<TFileInfo> FileInfo;
    std::vector<char>      InstrumentType;
    
    int GetNumberOfItemsInArchive(int ArchIdx);
}

int TDataBase::GetNumberOfItemsInArchive(int ArchIdx) {
    switch InstrumentType[ArchIdx] {
        case 1:
            return(FileInfo[ArchIdx].Instrument1.size());
        case 2:
            return(FileInfo[ArchIdx].Instrument2.size());
    }
}

想象一下,如果我需要再添加 10-100 种乐器,当然我不仅有 size() 函数,还有更多。有没有更简单的方法来实现这个?我在考虑接口,但是(1)如果我理解正确的虚函数不能与模板一起使用,(2)我对数据执行相同的操作,只是类型不同。非常感谢您的建议。

【问题讨论】:

  • Now the problem I have is that I do not know how my types of instruments a user has这是否意味着您不知道仪器的数量或您不知道仪器类型的数量?我怀疑你在那句话的某处有一个类型:)
  • @Exagon 抱歉不够精确。我不知道有多少仪器,用户应该能够添加/删除仪器。关于类型,目前我已经实现了一定数量的工具。但是将来客户可能会要求添加更多的仪器类型,因此代码必须易于扩展。这就是我说的类型的数量不知道的意思。
  • __fastcall 看起来很可疑。它不能在那里,因为&amp;TFileMapping::MapFile 被用作 Windows 函数的回调。 Windows 根本不理解指向成员函数的指针,所以__fastcall 毫无意义。
  • @Alexander Sure you can,但你不能让它成为Base 接口的一部分。 virtual 函数不能是函数模板,但 virtual 函数可以是 class 模板的一部分。
  • @Alexander 不,您需要添加序列化支持以某种方式保存/恢复您的实例树。也许您可以为它使用现有的库,或者为它编写自己的支持类。 type#hash_or_address#instance_data 可能会被写入文件,当恢复时,您需要将 hash_or_address 映射到新实例重新连接指针树的任何地方。我还没想好。可能有陷阱:-)

标签: c++ templates vector file-mapping


【解决方案1】:

根本原因是您无法对struct 进行自省。

使用class TInstrument1 : public std::tuple&lt;int, int&gt; 可能会更好。这将使您可以访问&lt;tuple&gt; 的整个机器。

话虽如此,这对您来说可能是一个挑战。 unsigned int * Num; int size(); 之类的代码表明您是初学者。在这种情况下,更好的建议可能是改用标准数据库。

【讨论】:

  • 谢谢你的回答,对了,我不是专业的程序员,我只是在学习。是否可以将元组类型的对象存储到映射文件中?据我所知,它不适用于向量。
  • @Alexander:考虑到你如何表达这个问题,我会回答“不”。原因是它确实适用于向量,但不适用于std::vector&lt;T, std::allocator&lt;T&gt;&gt;。您需要为映射内存使用适当的内存分配器。 std::tuple 也理解内存分配器。有关现有方法,请参阅 stackoverflow.com/questions/24901114/…
  • 我想我明白你的意思了,谢谢。因此,可以通过创建适当的分配器使向量/元组与文件映射一起使用。但它认为这是一个有点不同的话题。我的主要问题是如何避免使用TFileInfo 和与之相关的 switch 语句?
  • @Alexander:老实说,我仍在努力准确地理解您想要实现的目标。乐器部分,我明白了。但是你接着说一个用户可能拥有三种不同类型的仪器,但每个TMMapVector 只能持有一种类型。我的直觉反应是转储 TMMapVector 模板,以及之后的所有内容。但我从你的风格推测你可能对std::shared_ptr 也不熟悉。总的来说,我的问题是适合该问题的建议并没有计算出适合您经验的建议。
  • 您可以为std::getstd::tuple_sizestd::tuple_element提供特化,而不是从std::tuple继承
猜你喜欢
  • 2012-12-22
  • 2019-01-15
  • 2020-08-26
  • 2011-12-14
  • 2023-03-26
  • 2022-01-19
  • 1970-01-01
  • 2018-10-02
  • 1970-01-01
相关资源
最近更新 更多