Метапрограммирование препроцессора C: заменить макрос не в списке аргументов

Этот вопрос касается «метапрограммирования препроцессора C», то есть таких вещей, как это, это, это, это и т. Д.

Я пишу нетривиальную метапрограмму препроцессора C, которая, в частности, должна рекурсивно "вызывать" макросы (используя стандартнуюDEFER/EVALтрюки), и эти макросы должны будут объявить переменные:

      #define F(x, y)        \
do {                   \
    int var;           \
                       \
    /* ... */          \
                       \
    DEFER(F)()(var, y) \
} while (0)

Однако это создает переменную, затеняющую переменные во внешних областях, что является проблемой, если мне нужно передатьvarсебя как один из параметров (т. е. рекурсивный «вызов», необходимый для доступа к var в предыдущей области видимости). Решение, которое я нашел, состояло в том, чтобы объединить символ, такой как_на каждом уровне рекурсии:

      #define CAT(x, y) CAT_IMPL(x, y)
#define CAT_IMPL(x, y) x##y

#define F(x, y, l)                               \
do {                                             \
    int CAT(var, l);                             \
                                                 \
    /* Code that uses CAT(var, l) extensively */ \
                                                 \
    DEFER(F)()(CAT(var, l), y, CAT(l, _));       \
} while (0)

Итак, если предположить, что первоначальный «вызов»F()имеет формуF(x, y, _), затемvar_будет объявлено; на первом уровне рекурсии,var__будет объявлено; В секунду,var___, и так далее.

Это работает, но код замусорен вхождениямиCAT(var, l)делая его еще более нечитаемым, чем такой код обычно уже есть. Я ищу наиболее компактный синтаксис, чтобы сделать код немного менее нечитаемым, т.е. что-то вродеV(var), без необходимости расшифровывать, lчасть явно.

Однако у меня возникли проблемы с написанием макроса, чтобы это работало (при условии, что это вообще возможно).

Вот MRE, который даже не является действительной программой C, но продемонстрирует то, что я ищу, если запустить только препроцессор, т.е. используяgcc -E:

      #define CAT(x, y) CAT_IMPL(x, y)
#define CAT_IMPL(x, y) x##y

#define F1(x, l) CAT(x, l)

#define CATL(x) CAT(x, l)

#define F2(x, l) CATL(x)

F1(var, _)
F2(var, _)

Результат предварительной обработки этого (удаление мусора в начале):

      var_
varl

То, что я хотел бы, это версияCATL()с одним параметром макроса (т.е. без явной передачи в качестве параметра), но все еще "захваченным"l, чтобы вместо этого получить следующий вывод:

      var_
var_

0 ответов

Другие вопросы по тегам