2011-02-05 8 views
11

me gustaría hacer algo como lo siguiente:¿Cómo puedo generar una lista a través del preprocesador C (cpp)?

F_BEGIN 

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

F_END 

y tienen que generar los siguientes

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

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

Las funciones propias son fáciles. Lo que aparentemente no puedo hacer es realizar un seguimiento de todos los nombres hasta el final de la tabla de funciones.

Miré this question y this question pero no conseguí nada que funcionara para mí. Alguna idea?

Respuesta

14

La forma normal de hacer esto con el preprocesador es definir todas las funciones en una macro que tome otra macro como argumento, y luego usar otras macros para extraer lo que desee. Para su ejemplo:

#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) }; 
+0

El preprocesador C no permite que las macros definan otras macros, ni poseen ninguna forma de hacer recursiones o bucles, por lo que esta técnica (también descrita por ddyer) es la mejor que podrá hacer. – zwol

0

Boost es una biblioteca C++, pero su módulo preprocesador debería ser bueno para su uso en C. Ofrece algunos tipos de datos y funcionalidades sorprendentemente avanzados para su uso en el preprocesador. Podrías echarle un vistazo.

+0

me gustaría hacer esto simplemente con CPP. –

+0

Y [Boost :: Preprocessor] (http://www.boost.org/doc/libs/1_38_0/libs/preprocessor/) es un preprocesador C puro (así como el preprocesador C++). –

1

Esto es un tipo de abuso de CPP pero un tipo común de abuso. Puedo manejar situaciones como esta mediante la definición de macros ficticias

#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 

más tarde, cuando se quiere algo diferente hecho con la misma lista

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

FUNCTIONS 

#undef foo 

Es un poco feo y engorroso, pero funciona.

+1

Es menos feo si convierte 'foo' en un argumento para' FUNCTIONS' en lugar de ir PHP por todos lados. –

5

Si tiene un compilador que cumple con C99, el preprocesador tiene listas de argumentos de longitud variable. P99 tiene un preprocesador P99_FOR que puede hacer "desenrollar el código" como el que desea lograr. Para mantenerse cerca de su ejemplo

#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); 

ampliaría a la siguiente (no probado)

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