程式碼生成

通過編寫重複程式碼,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 命令排程