昔GCCのコード読んだときに、コードに、DEF_XX(TAG, "name") みたいなテーブルを作ってそれを読む箇所でDEF_XX マクロを定義して、Cのプリプロセッサだけでコンパイル時テーブルを作るみたいなテクニック
(https://github.com/gcc-mirror/gcc/blob/master/gcc/builtin-attrs.def とか)
を見て感動して、たまに使ってるのだけど、これは、DEF_XX という名前が名前空間で一個しか使えないという問題があって、駆使するとundefだらけで見辛いコードになりがち。
これを改善するために、最近は FOR_EACH マクロ手法(と心の中で呼んでいる)を使っている。
(例えば、 https://github.com/tanakamura/waifu2x-converter-cpp/blob/b798e36dc92d54c4794cde38ad9d1e7cf4c13002/src/CUDAlib.h#L96 このへんで使っている)
上の DEF_XX 手法だと、テーブルを
DEFINE_ENTRY(ENTRY_1, "entry 1", ATTR_FOO | ATTR_BAR) DEFINE_ENTRY(ENTRY_2, "entry 2", ATTR_FOO | ATTR_BAR) DEFINE_ENTRY(ENTRY_3, "entry 3", ATTR_FOO | ATTR_BAR)
と、書いていたのを、
#define FOR_EACH_ENTRY(F) \ F(ENTRY_1, "entry 1", ATTR_FOO | ATTR_BAR) \ F(ENTRY_2, "entry 2", ATTR_FOO | ATTR_BAR) \ F(ENTRY_3, "entry 3", ATTR_FOO | ATTR_BAR)
というように書きかえる。
そして、使う箇所は、DEF_XX手法だと、
const char *name_table[] = { #define DEFINE_ENTRY(sym, str, attr) str, #include "def_xx.def" #undef DEFIN_ENTRY };
と、書いていたのを、
#define EXTRACT_STR_FROM_ENTRY(sym, str, attr) str, const char *name_table[] = { FOR_EACH_ENTRY(EXTRACT_STR_FROM_ENTRY) };
というようにする。
テーブルエントリを定義するマクロ名が任意に付けられるので、undefが必要無くなるし、意味のある名前を付けられるようになる。