Tengo dos macros FOO2y FOO3:
#define FOO2(x,y) ...
#define FOO3(x,y,z) ...
Quiero definir una nueva macro de la FOOsiguiente manera:
#define FOO(x,y) FOO2(x,y)
#define FOO(x,y,z) FOO3(x,y,z)
Pero esto no funciona porque las macros no se sobrecargan en la cantidad de argumentos.
Sin modificar FOO2y FOO3, ¿hay alguna forma de definir una macro FOO(usando __VA_ARGS__o de otra manera) para obtener el mismo efecto de despachar FOO(x,y)a FOO2, y FOO(x,y,z)a FOO3?
c
macros
c-preprocessor
Andrew Tomazos
fuente
fuente

Respuestas:
Simple como:
Entonces, si tienes estas macros:
Si quieres un cuarto:
Naturalmente, si define
FOO2,FOO3yFOO4, la salida será reemplazada por las de las macros definidas.fuente
EXPANDmencionado en el enlace de @Etienne, básicamente lo invocasGET_MACROasí#define FOO(...) EXPAND(GET_MACRO(__VA_ARGS__, FOO3, FOO2, FOO1)(__VA_ARGS__))y debería expandirse al número correcto de argumentos en msvc.ISO C++11 requires at least one argument for the "..." in a variadic macro. Para solucionar esto, agregue un argumento no utilizado (o incluso una coma) después del último parámetro en la definición de FOO (...):#define FOO(...) GET_MACRO(__VA_ARGS__, FOO3, FOO2, UNUSED)(__VA_ARGS__)( Vea cómo se ejecuta en Coliru ).Para agregar a la respuesta de netcoder , PUEDE hacer esto con una macro de 0 argumentos, con la ayuda de la
##__VA_ARGS__extensión GCC :fuente
#define FOO0 _Pragma("error FOO0 not allowed")?FOO0no funciona en qt + mingw32, la llamadaFOO0invocará elFOO1-std=c99o-std=c11. Necesitas usar-std=gnu99o en su-std=gnu11lugar_0, ##__VA_ARGS__con_0 __VA_OPT__(,) __VA_ARGS__es la nueva forma de hacer esto.Aquí hay una solución más general:
Define tus funciones:
Ahora puede usar
FOOcon 2, 3 y 4 argumentos:Limitaciones
Ideas
Úselo para argumentos predeterminados:
Úselo para funciones con un número infinito posible de argumentos:
PD:
__NARG__se copia de Laurent Deniau y Roland Illig aquí: https://groups.google.com/group/comp.std.c/browse_thread/thread/77ee8c8f92e4a3fb/346fc464319b1ee5?pli=1fuente
__NARG_I_parece completamente innecesaria y superflua. Simplemente agrega un paso adicional y confusión. Recomiendo eliminarlo por completo y simplemente definir__NARG__en cambio, como:#define __NARG__(...) __ARG_N(__VA_ARGS__,__RSEQ_N())._VFUNC_: simplemente elimínelo. Luego, defina_VFUNCcomo: en#define _VFUNC(name, n) name##nlugar de#define _VFUNC(name, n) _VFUNC_(name, n).Estaba investigando esto yo mismo, y me encontré con esto aquí . El autor agregó soporte de argumento predeterminado para funciones C a través de macros.
Trataré de resumir brevemente el artículo. Básicamente, debe definir una macro que pueda contar argumentos. Esta macro devolverá 2, 1, 0 o cualquier rango de argumentos que pueda soportar. P.ej:
Con esto, debe crear otra macro que tome un número variable de argumentos, cuente los argumentos y llame a la macro apropiada. Tomé tu macro de ejemplo y la combiné con el ejemplo del artículo. Tengo la función de llamada FOO1 a () y la función de llamada FOO2 a con el argumento b (obviamente, supongo que C ++ aquí, pero puede cambiar la macro a lo que sea).
Entonces si tienes
El preprocesador lo expande a
Definitivamente leería el artículo que vinculé. Es muy informativo y menciona que NARG2 no funcionará en argumentos vacíos. Él sigue esto hasta aquí .
fuente
Aquí hay una versión más compacta de la respuesta anterior . Con ejemplo.
Correr:
Tenga en cuenta que tener ambos
_OVRy_OVR_EXPANDpuede parecer redundante, pero es necesario que el preprocesador expanda la_COUNT_ARGS(__VA_ARGS__)parte, que de lo contrario se trata como una cadena.fuente
Tal vez pueda usar esta macro para contar la cantidad de argumentos .
fuente
Aquí hay un spin off de la respuesta de Evgeni Sergeev. ¡Este también admite sobrecargas de argumento cero !
Probé esto con GCC y MinGW. Debería funcionar con versiones antiguas y nuevas de C ++. Tenga en cuenta que no lo garantizaría para MSVC ... Pero con algunos ajustes, estoy seguro de que también podría funcionar.
También formateé esto para pegarlo en un archivo de encabezado (que llamé macroutil.h). Si hace eso, puede incluir este encabezado según lo que necesite la función, y no mirar la maldad involucrada en la implementación.
fuente
Esto parece funcionar bien en GCC, Clang y MSVC. Es una versión limpia de algunas de las respuestas aquí.
fuente
#define func0() foo? La versión actual no maneja este caso desafortunadamente.