How to handle different templates in a similar way?

92 Views Asked by At

I have been dealing with a problem for several days and still have no proper solution. Imagine I have several (number can vary) instruments. Each instrument produces data of different type. For each instrument I have a structure (I show very simplistic approximations here):

struct TInstrument1 {
    int Variable1;
    int Variable2;
}

struct TInstrument2 {
    int Variable3;
} 

I am trying to create kind of a database to look through the available data. The way I do this is as follows:

First, I have a class which does filemapping. I am programming on Windows so I use CreateFile, CreateFileMapping,MapViewOdFile functions inside the MapFile function:

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();

};

This class is then use in TMapVector structure (i give a simplified version):

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();

};

The idea is that for instance TMapVector<Instrument1> creates/opens a database file corresponding to Instrument1 and contains a objects of the type Instrument1.

Now the problem I have is that I do not know how many types of instruments a user has. At the moment there are 3 but the code should be easily extendable to more instrument types. At the moment I handle it as follows. I have a class TFileInfo with both instrument types, but only one of them is filled. This allows me to further use std::vector<TFileInfo>. The problem with this approach is that I have to use switch statements every time I need to do something with instruments:

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());
    }
}

Just imagine if I need to add another 10-100 instruments and of course I have not just the size() function but many more. Is there a simpler way to implement this? I was thinking about interfaces but (1) if I understand it right virtual functions are not usable with templates and (2) I do the same operations with the data, only the type is different. I would highly appreciate an advice.

1

There are 1 best solutions below

5
MSalters On

The root cause is that you can't do introspection on a struct.

It may be better to use class TInstrument1 : public std::tuple<int, int>. This will give you access to the whole machinery of <tuple>.

Having said that, this might be a challenge for you. Code like unsigned int * Num; and int size(); suggests that you're a beginning coder. The better advice in that situation might be to use a standard database instead.