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