with macro example define __va_args__ c functional-programming c-preprocessor

example - Programación funcional en C con generadores de macro "Función de orden superior"



gcc macros (3)

Presta atención con atención porque esta es una gran pregunta ;-)

Deseo utilizar funciones de plantilla para acciones de recopilación genéricas (como búsqueda, foreach, etc.) en C mientras mantengo la comprobación del tipo estático del compilador. Es bastante sencillo cuando usa devoluciones de llamada simples como en este ejemplo:

#define MAKE_FOREACH(TYPE)/ void foreach_##TYPE (TYPE[n] array, int n, void(*f)(TYPE)) {/ for(int i = 0; i < n; i++) {/ f(array[i]);/ }/ }

para que pueda hacer cosas como:

MAKE_FOREACH(int) MAKE_FOREACH(float) void intcallback(int x){ printf("got %d/n", x); } void floatcallback(float x){ printf("got %f/n", x); } int main(){ int[5] iarray = {1,2,3,4,5}; float[5] farray = {1.0,2.0,3.0,4.0,5.0}; foreach_int(iarray, 5, intcallback); foreach_float(farray, 5, floatcallback); }

Si quisiera implementar devoluciones de llamada con tipos de devolución, por ejemplo para hacer una función de "mapa", podría hacer lo siguiente:

#define MAKE_MAP(TYPE, RTYPE)/ RTYPE* map_##TYPE (TYPE[n] array, int n, RTYPE(*f)(TYPE)) {/ RTYPE* result = (RTYPE*)malloc(sizeof(RTYPE)*n);/ for(int i = 0; i < n; i++) {/ result[i]=f(array[i]);/ }/ }

Hasta aquí todo bien. El problema viene ahora, cuando quiero que mis funciones de devolución de llamada acepten cualquier cantidad de argumentos escritos.

La idea es algo así como:

#define MAKE_MAP(TYPE, RTYPE, ...)/ RTYPE* map_##TYPE (TYPE[n] array, int n, RTYPE(*f)(TYPE, __VA_ARGS__), __VA_ARGS__) /*this would work for the declaration (because just the types would be enough) but the parameter names are missing :-s*/ / {/ RTYPE* result = (RTYPE*)malloc(sizeof(RTYPE)*n);/ for(int i = 0; i < n; i++) {/ result[i]=f(array[i], /*here the names of the parameters, in order*/);/ }/ }

entonces, como pueden ver, podría declarar una función de mapa como:

MAKE_MAP(int, float, char)

dando:

float* map_int(int[n] array, int n, float(*f)(int, char), char);

pero no puedo imaginar cómo implementar el parámetro que pasa con el preprocesador. Aquí es donde pido su ayuda, ideas y sugerencias.

(Por cierto, no me diga que use una función variadica como plantilla y pase un argumento va_list a la devolución de llamada, porque todo esto fue debido a la verificación de tipo :-p)


Para información, el código fuente de GCC 4.6 implementa trucos similares para vectores. Mire en su archivo gcc/vec.h


Si está en Linux / BSD Unix, eche un vistazo a la queue(3) y compruebe en /usr/include/sys/queue.h - ya se ha hecho antes :)