Home > Blockchain >  Create variants of templated class with different initialization
Create variants of templated class with different initialization

Time:12-21

I am creating multiple different types of encoders where the main difference is the different data structures used to initialize the class. My header is something like this

struct tagTypeInfo {
        uint16_t start;
        uint16_t last;
        uint16_t count;
        std::string name;
        rdwrT rdwr;
};

template <typename T>
class encodedTag
{
public:
    encodedTag(vector<tagTypeInfo> tagInfo_) : tagInfo(tagInfo_)
    {
        int start = 0;
        for(auto & tag : tagInfo)
        {
            tag.start = start;
            tag.last = start   tag.count - 1;
            start = start   tag.count;
        }
    }

    uint16_t encode(uint16_t tag, T tagType)
    {
        assert(tag<tagInfo[tagType].count)
        return( tagInfo[tagType].start   tag );
    }
    std::tuple<uint16_t, T> decode(uint16_t encodedTag)
    {
        int type = 0;
        uint16_t tag;
        // simple linear search as there are only a few entries
        for (auto it = begin(tagInfo); it != end(tagInfo); it  )
        {
            if (encodedTag >= it->start && encodedTag < it->last )
            {
                // tag is in the range
                return {encodedTag - it->start , (T)type};
            }
            type  ;
        }
        assert(false);    
        return {0,(T)0};
    }
    std::string getName(T tagType) {return(tagInfo[tagType].name);}
    rdwrT getRdwr(T tagType) {return(tagInfo[tagType].rdwr);}
private:
    std::vector<tagTypeInfo> tagInfo;
};

extern std::vector<tagTypeInfo> rdTag;
extern std::vector<tagTypeInfo> wrTag;

//using rdTagEncode = encodedTag<rdTagT>(rdTag) <-- error

The cpp file contains:

std::vector<tagTypeInfo> rdTag {
        {0, 0, NUM_HOSTRDTAG,        "HostRdTag",    RDWR_RD},
        {0, 0, NUM_SYSRDTAG,         "SysRdTag",     RDWR_RD},
        {0, 0, NUM_GCRDTAG,          "GCRdTag",      RDWR_RD}
    };

std::vector<tagTypeInfo> wrTag {
        {0, 0, NUM_HOSTWRTAG,        "HostWrTag",    RDWR_WR},
        {0, 0, NUM_SYSWRTAG,         "SysWrTag",     RDWR_WR},
        {0, 0, NUM_GCWRTAG,          "GCWrTag",      RDWR_WR}
    };

My goal is to be able to just declare an encoder in the code elsewhere with rdTagEncode myEncode; However I cant seem to figure out the right syntax to do this. Any suggestions?

CodePudding user response:

Using a derived class was the best solution. Thanks for the suggestion @appleapple

class encodedRdTag : public encodedTag<rdTagTypeT>
{
    public:
    encodedRdTag() : encodedTag({
        {0, 0, NUM_HOSTRDTAG,        "HostRdTag",    RDWR_RD},
        {0, 0, NUM_SYSRDTAG,         "SysRdTag",     RDWR_RD},
        {0, 0, NUM_GCRDTAG,          "GCRdTag",      RDWR_RD}
    }) {};
};

class encodedWrTag : public encodedTag<wrTagTypeT>
{
    public:
    encodedWrTag() : encodedTag({
        {0, 0, NUM_HOSTRDTAG,        "HostRdTag",    RDWR_RD},
        {0, 0, NUM_SYSRDTAG,         "SysRdTag",     RDWR_RD},
        {0, 0, NUM_GCRDTAG,          "GCRdTag",      RDWR_RD}
    }) {};
};

CodePudding user response:

For completeness, here is the "dispatch based on type" method which I mentioned in comment above.


NOTE: this code doesn't work in original question as the rdTag and wrTag are same type thus independent of the class template T, but according to your own answer this may be actually what happends.


#include <vector>

struct tagTypeInfo{};

struct rdTagTypeT{};
struct wrTagTypeT{};

template<typename T>
std::vector<tagTypeInfo> get_default_info() = delete; // invalid default
template<>
std::vector<tagTypeInfo> get_default_info<rdTagTypeT>(); // return wrTag
template<>
std::vector<tagTypeInfo> get_default_info<wrTagTypeT>(); // return wdTag

template <typename T>
struct encodedTag
{
    encodedTag():encodedTag(get_default_info<T>()){}
    encodedTag(std::vector<tagTypeInfo> tagInfo) : tagInfo(tagInfo){};
    std::vector<tagTypeInfo> tagInfo;
};

using encodedRdTag = encodedTag<rdTagTypeT>;
using encodedWrTag = encodedTag<rdTagTypeT>;

void foo(){
    encodedRdTag rd;
    encodedWrTag rw;
}
  • Related