Ви не можете цього зробити, якщо USER визначено як рядок із лапки.
Але ви можете зробити це, якщо КОРИСТУВАЧ - це просто ДЖЕК, КОРОЛЕВА, Джокер або що завгодно.
Існує два прийоми:
- Зрощування токенів, коли ви поєднуєте ідентифікатор з іншим ідентифікатором, просто об'єднуючи їх символи. Це дозволяє порівнювати з JACK без необхідності
#define JACK
щось робити
- варіадичне розширення макросів, яке дозволяє обробляти макроси із змінною кількістю аргументів. Це дозволяє вам розширити конкретні ідентифікатори в різну кількість коми, що стане вашим порівнянням рядків.
Отже, почнемо з:
#define JACK_QUEEN_OTHER(u) EXPANSION1(ReSeRvEd_, u, 1, 2, 3)
Тепер, якщо я пишу JACK_QUEEN_OTHER(USER)
, а USER - JACK, препроцесор перетворює це наEXPANSION1(ReSeRvEd_, JACK, 1, 2, 3)
Крок другий - об’єднання:
#define EXPANSION1(a, b, c, d, e) EXPANSION2(a##b, c, d, e)
Зараз JACK_QUEEN_OTHER(USER)
стаєEXPANSION2(ReSeRvEd_JACK, 1, 2, 3)
Це дає можливість додати кілька коми, залежно від того, відповідає рядок чи ні:
#define ReSeRvEd_JACK x,x,x
#define ReSeRvEd_QUEEN x,x
Якщо USER - JACK, JACK_QUEEN_OTHER(USER)
стаєEXPANSION2(x,x,x, 1, 2, 3)
Якщо USER - КОРОЛЕВА, JACK_QUEEN_OTHER(USER)
стаєEXPANSION2(x,x, 1, 2, 3)
Якщо USER інший, JACK_QUEEN_OTHER(USER)
стаєEXPANSION2(ReSeRvEd_other, 1, 2, 3)
На даний момент сталося щось критичне: четвертий аргумент макросу EXPANSION2 - це 1, 2 або 3, залежно від того, первинним аргументом був переданий jack, queen або щось інше. Отже, все, що нам потрібно зробити, це вибрати його. З довготривалих причин нам знадобляться два макроси для останнього кроку; вони будуть EXPANSION2 та EXPANSION3, хоча один здається непотрібним.
Поєднавши все це, ми маємо ці 6 макросів:
#define JACK_QUEEN_OTHER(u) EXPANSION1(ReSeRvEd_, u, 1, 2, 3)
#define EXPANSION1(a, b, c, d, e) EXPANSION2(a##b, c, d, e)
#define EXPANSION2(a, b, c, d, ...) EXPANSION3(a, b, c, d)
#define EXPANSION3(a, b, c, d, ...) d
#define ReSeRvEd_JACK x,x,x
#define ReSeRvEd_QUEEN x,x
І ви можете використовувати їх так:
int main() {
#if JACK_QUEEN_OTHER(USER) == 1
printf("Hello, Jack!\n");
#endif
#if JACK_QUEEN_OTHER(USER) == 2
printf("Hello, Queen!\n");
#endif
#if JACK_QUEEN_OTHER(USER) == 3
printf("Hello, who are you?\n");
#endif
}
Обов’язкове посилання godbolt: https://godbolt.org/z/8WGa19