I often use const lookup tables in my code, which consists of an id and a string. But for readability it would be better to use symbol names (named constants) instead of the id. Example:
class LookupTable
{
map<int,string> m { {10,"red"}, {20,"blue"}, {30,"green"} };
enum { col_rd = 10, col_bl = 20, col_gr = 30 };
};
LookupTable tab;
cout << tab.m[10]; // "red", using the id
cout << tab.m[col_bl] // "blue", using a symbol
cout << tab.m[11]; // Typo! Compiler does not check this
cout << tab.m[col_xy]; // Typo! Compiler will complain
Using symbol names will also be checked for typos at compile time.
But I like to define the symbol name, the id and the string for a element in one place, instead of defining the values in the upper part and then defining the named constants in the lower part of the class declaration, especially if the table is quite long. For example I would like to write something like:
mytable.init = { { col_rd, 10, "red" }, // define the symbol names and
{ col_bl, 20, "blue" }, // values at one place
{ col_gr, 30, "green" } };
Is this possible to do by templates or in combination with #define macros?
I once saw this technique used in the Varnish cache, it uses macros - but you say you are ok with that :)
In color_tags.hpp
:
// Define the color tags
COLOR_TAG(col_rd, 10, "red")
COLOR_TAG(col_bl, 20, "blue")
COLOR_TAG(col_gr, 30, "green")
Usage in main.cpp
:
#include <map>
#include <string>
#include <iostream>
/// Enumeration of different color codes, we use a bit of
/// macro uglyness to makes this easy
enum class color_type
{
#define COLOR_TAG(id,value, msg) id = value,
#include "color_tags.hpp"
#undef COLOR_TAG
terminate_tag
};
int main()
{
std::map<color_type, std::string> m =
{
#define COLOR_TAG(id, value, msg) {color_type::id, msg},
#include "color_tags.hpp"
#undef COLOR_TAG
{color_type::terminate_tag, "undefined"}
};
std::cout << m[color_type::col_rd] << std::endl;
std::cout << m[color_type::col_bl] << std::endl;
std::cout << m[color_type::col_gr] << std::endl;
return 0;
}
Output:
$ g++ main.cpp -std=c++11
$ ./a.out
red
blue
green