程式碼生成
通過編寫重複程式碼,X-Macros 可用於程式碼生成:迭代列表以執行某些任務,或宣告一組常量,物件或函式。
這裡我們使用 X-macros 宣告一個包含 4 個命令的列舉和一個名稱為字串的對映
然後我們可以列印列舉的字串值。
/* All our commands */
#define COMMANDS(OP) OP(Open) OP(Close) OP(Save) OP(Quit)
/* generate the enum Commands: {cmdOpen, cmdClose, cmdSave, cmdQuit, }; */
#define ENUM_NAME(name) cmd##name,
enum Commands {
COMMANDS(ENUM_NAME)
};
#undef ENUM_NAME
/* generate the string table */
#define COMMAND_OP(name) #name,
const char* const commandNames[] = {
COMMANDS(COMMAND_OP)
};
#undef COMMAND_OP
/* the following prints "Quit\n": */
printf("%s\n", commandNames[cmdQuit]());
類似地,我們可以生成一個跳轉表來通過列舉值呼叫函式
這要求所有函式具有相同的簽名。如果它們不帶引數並返回一個 int,我們會把它放在帶列舉定義的標頭檔案中:
/* declare all functions as extern */
#define EXTERN_FUNC(name) extern int doCmd##name(void);
COMMANDS(EXTERN_FUNC)
#undef EXTERN_FUNC
/* declare the function pointer type and the jump table */
typedef int (*CommandFunc)(void);
extern CommandFunc commandJumpTable[];
假設上面的部分包含在標題中,以下所有內容都可以在不同的編譯單元中:
/* generate the jump table */
#define FUNC_NAME(name) doCmd##name,
CommandFunc commandJumpTable[] = {
COMMANDS(FUNC_NAME)
};
#undef FUNC_NAME
/* call the save command like this: */
int result = commandJumpTable[cmdSave]();
/* somewhere else, we need the implementations of the commands */
int doCmdOpen(void) {/* code performing open command */}
int doCmdClose(void) {/* code performing close command */}
int doCmdSave(void) {/* code performing save command */}
int doCmdQuit(void) {/* code performing quit command */}
在實際程式碼中使用的該技術的示例是用於 Chromium 中的 GPU 命令排程 。