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