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