Я часто использую таблицы поиска const в моем коде, который состоит из идентификатора и строки. Но для удобства чтения было бы лучше использовать имена символов (именованные константы) вместо идентификатора.
Пример:
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
Использование имен символов также будет проверяться на наличие опечаток во время компиляции.
Но мне нравится определять имя символа, идентификатор и строку для элемента в одном месте, вместо определения значений в верхней части, а затем определения именованных констант в нижней части объявления класса, особенно если таблица довольно длинная. Например, я хотел бы написать что-то вроде:
mytable.init = { { col_rd, 10, "red" }, // define the symbol names and
{ col_bl, 20, "blue" }, // values at one place
{ col_gr, 30, "green" } };
Это возможно сделать с помощью шаблонов или в сочетании с макросами #define?
Однажды я видел эту технику в кэше Varnish, она использует макросы — но вы говорите, что с этим все в порядке 🙂
В 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")
Использование в 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;
}
Выход:
$ g++ main.cpp -std=c++11
$ ./a.out
red
blue
green
Идентификатор кажется мне бесполезным. Вы не можете сделать следующее?
struct LookupTable
{
enum ColorType
{
col_rd,
col_bl,
col_gr
}
std::map<ColorType, std::string> m;
};
Затем вы можете сделать что-то вроде:
LookupTable table;
table.m = {{LookupTable::col_rd, "red"},
{LookupTable::col_bl, "blue"},
{LookupTable::col_rd, "green"}};