Как я могу сгенерировать список через препроцессор C (cpp)? - PullRequest
11 голосов
/ 05 февраля 2011

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

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 };

Сами функции просты.Кажется, я не могу отслеживать все имена до конца для function_table.

Я посмотрел этот вопрос и этот вопрос но я не мог заставить что-либо работать на меня.Есть идеи?

Ответы [ 4 ]

14 голосов
/ 05 февраля 2011

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

#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) };
5 голосов
/ 05 февраля 2011

Если у вас есть компилятор 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 };
1 голос
/ 05 февраля 2011

Это своего рода злоупотребление 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

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

0 голосов
/ 05 февраля 2011

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

...