Tengo dos macros FOO2
y FOO3
:
#define FOO2(x,y) ...
#define FOO3(x,y,z) ...
Quiero definir una nueva macro de la FOO
siguiente 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 FOO2
y 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
,FOO3
yFOO4
, la salida será reemplazada por las de las macros definidas.fuente
EXPAND
mencionado en el enlace de @Etienne, básicamente lo invocasGET_MACRO
así#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")
?FOO0
no funciona en qt + mingw32, la llamadaFOO0
invocará elFOO1
-std=c99
o-std=c11
. Necesitas usar-std=gnu99
o en su-std=gnu11
lugar_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
FOO
con 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_VFUNC
como: en#define _VFUNC(name, n) name##n
lugar 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
_OVR
y_OVR_EXPAND
puede 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.