Как я могу сгенерировать список через препроцессор C (cpp)?

Я хотел бы сделать что-то вроде следующего:

F_BEGIN

F(f1) {some code}
F(f2) {some code}
...
F(fn) {some code}

F_END

и сгенерировать следующую

int f1() {some code}
int f2() {some code}
...
int fn() {some code}

int (*function_table)(void)[] = { f1, f2, ..., fn };

Функции сами по себе легки. То, что я не могу сделать, это следить за всеми именами до конца для функции_table.

Я рассмотрел этот вопрос и этот вопрос, но я не мог заставить ничего работать для меня, Любые идеи?

Ответ 1

Обычный способ сделать это с препроцессором - определить все функции макроса, который принимает другой макрос в качестве аргумента, а затем использовать другие макросы для извлечения того, что вы хотите. Для вашего примера:

#define FUNCTION_TABLE(F) \
    F(f1, { some code }) \
    F(f2, { some code }) \
    F(f3, { some code }) \
:

    F(f99, { some code }) \
    F(f100, { some code })

#define DEFINE_FUNCTIONS(NAME, CODE)     int NAME() CODE
#define FUNCTION_NAME_LIST(NAME, CODE)   NAME,

FUNCTION_TABLE(DEFINE_FUNCTIONS)
int (*function_table)(void)[] = { FUNCTION_TABLE(FUNCTION_NAME_LIST) };

Ответ 2

Если у вас есть компилятор C99, препроцессор имеет списки аргументов переменной длины. P99 имеет препроцессор P99_FOR, который может выполнять "разворачивание кода", как тот, который вы хотите достичь. Чтобы оставаться рядом с вашим примером

#define MYFUNC(DUMMY, FN, I) int FN(void) { return I; } 
#define GENFUNCS(...)                                          \
P99_FOR(, P99_NARG(__VA_ARGS__), P00_IGN, MYFUNC, __VA_ARGS__) \
int (*function_table)(void)[] = { __VA_ARGS__ }

GENFUNCS(toto, hui, gogo);

будет расширяться до следующего (непроверенного)

int toto(void) { return 0; } 
int hui(void) { return 1; }
int gogo(void) { return 2; }
int (*function_table)(void)[] = { toto, hui, gogo };

Ответ 3

Это своего рода злоупотребление CPP, но обычный тип злоупотреблений. Я занимаюсь ситуациями как это, определяя фиктивные макросы

#define FUNCTIONS \
 foo(a,b,c,d) \
 foo(a,b,c,d) \
 foo(a,b,c,d)

now, 

#define foo(a,b,c,d) \
 a+b ;

FUNCTIONS

#undef foo

позже, когда вам нужно что-то другое, сделанное с тем же списком

#define foo(a,b,c,d) \
 a: c+d ;

FUNCTIONS

#undef foo

Это немного уродливое и громоздкое, но оно работает.

Ответ 4

Boost - это библиотека С++, но модуль Preprocessor все равно будет хорош для использования в C. Он предлагает некоторые удивительно расширенные типы данных и функциональные возможности для использования в препроцессоре. Вы можете проверить это.