There are some caveats to it. The Enum id cant be sparse. and the UNKNOWN entry needs to be second last before the MAX entry marker.
#include <iostream>
template<int LAST, typename R, typename T>
R lookup(T* table, R T::*member, int key)
{
if (key < LAST) return table[key].*member;
return table[LAST].*member;
}
template<int LAST, typename R, typename T>
int locate(T* table, R T::*member, R target)
{
int k = 0;
while (k < LAST)
{
if (table[k].*member == target)
return k;
k++;
}
return LAST;
}
template<int LAST, typename T>
int locate(T* table, const char* T::*member, const char* target)
{
int k = 0;
while (k < LAST)
{
if (std::string(table[k].*member) == std::string(target))
return k;
k++;
}
return LAST;
}
class TableTrait
{
public:
enum Key
{
ITEM1,
ITEM2,
ITEM3,
ITEM4,
ITEM5,
UNKNOWN, //Must be second last
MAX //Must be last
};
private:
struct TableEntry
{
Key key;
int attribA;
bool attribB;
const char* attribC;
};
static TableEntry lookup_table[MAX];
int key_;
public:
TableTrait(int key) :
key_(lookup<UNKNOWN>(lookup_table, &TableEntry::key, key))
{}
TableTrait(const char* rev_key) :
key_(locate<UNKNOWN>(lookup_table, &TableEntry::attribC, rev_key))
{}
bool valid() { return key_ != UNKNOWN; }
Key key() { return static_cast<Key>(key_); }
int attribA() { return lookup<UNKNOWN>(lookup_table, &TableEntry::attribA, key_); }
bool attribB() { return lookup<UNKNOWN>(lookup_table, &TableEntry::attribB, key_); }
const char* attribC() { return lookup<UNKNOWN>(lookup_table, &TableEntry::attribC, key_); }
};
TableTrait::TableEntry TableTrait::lookup_table[TableTrait::MAX] =
{
{ ITEM1, 3, false, "ITEM1" },
{ ITEM2, 2, true, "ITEM2" },
{ ITEM3, 6, false, "ITEM3" },
{ ITEM4, 5, true, "ITEM4" },
{ ITEM5, 8, false, "ITEM5" },
{ UNKNOWN, 0, false, "UNKNOWN" }
};
int main()
{
std::cout << "lookup: " << TableTrait(TableTrait::ITEM1).attribC() << "\n";
std::cout << "lookup: " << TableTrait(TableTrait::ITEM2).attribB() << "\n";
std::cout << "locate: " << TableTrait("ITEM3" ).attribA() << "\n";
std::cout << "locate: " << TableTrait("ITEM2" ).key() << "\n";
std::cout << "locate: " << TableTrait("Blah" ).attribC() << "\n";
}
No comments:
Post a Comment