Макрос со значением "заполнитель" - PullRequest
4 голосов
/ 21 мая 2011

Я работаю с библиотекой, которая включает в себя набор библиотек препроцессора. Одним из них является макрос в стиле FOR_EACH, который перебирает __VA_ARGS__ и вызывает предоставленный пользователем макрос для каждого аргумента. Предоставленный пользователем макрос называется как: SOME_MACRO(current_arg)

Однако проблема в том, что он работает только с предоставленными пользователем макросами, которые принимают аргумент single . Я пытаюсь сделать что-то особенное, которое включает как имя struct, так и каждое поле в структуре. Проблема в том, что для этого требуется два аргумента макроса.

Поскольку библиотека, с которой я работаю, принимает только унарный макрос, есть ли способ «привязать» дополнительный аргумент к моему макросу?

На данный момент я должен жестко закодировать имя структуры в моем макросе. Итак, если struct, с которым я работаю, называется Foo, я должен сказать:

#define MY_MACRO(FIELD) /* do something with &Foo::FIELD */

Есть ли какой-нибудь способ, которым я мог бы "привязать" второй аргумент STRUCT к макросу, возможно, с некоторой дополнительной косвенностью, чтобы, когда библиотека вызывала мой макрос, она могла расширяться как:

#define MY_MACRO(FIELD) /* do something with &STRUCT::FIELD */

1 Ответ

5 голосов
/ 21 мая 2011

Да. Вы можете использовать следующую технику.

#define MY_MACRO(FIELD) EXPAND FIELD
#define EXPAND(X, FIELD) X::FIELD()

Использование в приведенном ниже тестовом коде:

struct foo { static int f() { return 0; } };
struct STRUCT { static int f() { return 1; } };

#define MY_MACRO(FIELD) EXPAND FIELD
#define EXPAND(X, FIELD) X::FIELD()

int main ()
{
  int i = MY_MACRO((STRUCT,f)); // see here braces inside braces
}

Приведенный выше код расширен до,

int main ()
{
  int i = STRUCT::f();
}
...