Eu tenho duas macros FOO2
e FOO3
:
#define FOO2(x,y) ...
#define FOO3(x,y,z) ...
Quero definir uma nova macro da FOO
seguinte maneira:
#define FOO(x,y) FOO2(x,y)
#define FOO(x,y,z) FOO3(x,y,z)
Mas isso não funciona porque as macros não sobrecarregam o número de argumentos.
Sem modificar FOO2
e FOO3
, existe alguma maneira de definir uma macro FOO
(usando __VA_ARGS__
ou não) para obter o mesmo efeito de despacho FOO(x,y)
para FOO2
e FOO(x,y,z)
para FOO3
?
c
macros
c-preprocessor
Andrew Tomazos
fonte
fonte
Respostas:
Simples como:
Então, se você possui essas macros:
Se você quer um quarto:
Naturalmente, se você definir
FOO2
,FOO3
eFOO4
, a saída será substituída pelas das macros definidas.fonte
EXPAND
link mencionado no @ Étienne, você basicamente o invocaGET_MACRO
assim#define FOO(...) EXPAND(GET_MACRO(__VA_ARGS__, FOO3, FOO2, FOO1)(__VA_ARGS__))
e ele deve se expandir para o número certo de argumentos no msvc.ISO C++11 requires at least one argument for the "..." in a variadic macro
. Para corrigir isso, adicione um argumento não utilizado (ou mesmo uma vírgula) após o último parâmetro na definição de FOO (...):#define FOO(...) GET_MACRO(__VA_ARGS__, FOO3, FOO2, UNUSED)(__VA_ARGS__)
( Veja em Coliru ).Para adicionar à resposta do netcoder , você PODE de fato fazer isso com uma macro de 0 argumentos, com a ajuda da
##__VA_ARGS__
extensão GCC :fonte
#define FOO0 _Pragma("error FOO0 not allowed")
?FOO0
não funciona no qt + mingw32, chamadaFOO0
irá chamar oFOO1
-std=c99
ou-std=c11
. Você precisa usar-std=gnu99
ou em-std=gnu11
vez disso_0, ##__VA_ARGS__
por_0 __VA_OPT__(,) __VA_ARGS__
é a nova maneira de fazer isso.Aqui está uma solução mais geral:
Defina suas funções:
Agora você pode usar
FOO
com 2, 3 e 4 argumentos:Limitações
Ideias
Use-o para argumentos padrão:
Use-o para funções com possível número infinito de argumentos:
PS:
__NARG__
é copiado de Laurent Deniau & Roland Illig aqui: https://groups.google.com/group/comp.std.c/browse_thread/thread/77ee8c8f92e4a3fb/346fc464319b1ee5?pli=1fonte
__NARG_I_
parece completamente desnecessária e supérflua. Apenas adiciona uma etapa extra e confusão. Eu recomendo excluí-la inteiramente e apenas definir__NARG__
em vez como:#define __NARG__(...) __ARG_N(__VA_ARGS__,__RSEQ_N())
._VFUNC_
: apenas exclua-o. Em seguida, defina_VFUNC
como: em#define _VFUNC(name, n) name##n
vez de#define _VFUNC(name, n) _VFUNC_(name, n)
.Eu mesmo estava pesquisando isso e me deparei com isso aqui . O autor adicionou suporte a argumentos padrão para funções C via macros.
Vou tentar resumir brevemente o artigo. Basicamente, você precisa definir uma macro que possa contar argumentos. Essa macro retornará 2, 1, 0 ou qualquer intervalo de argumentos que ela possa suportar. Por exemplo:
Com isso, você precisa criar outra macro que utilize um número variável de argumentos, conte os argumentos e chame a macro apropriada. Peguei sua macro de exemplo e a combinei com o exemplo do artigo. Eu tenho a função de chamada FOO1 a () e a função de chamada FOO2 a com o argumento b (obviamente, estou assumindo C ++ aqui, mas você pode alterar a macro para o que for).
Então se você tem
O pré-processador expande isso para
Eu definitivamente leria o artigo que vinculei. É muito informativo e ele menciona que o NARG2 não funcionará em argumentos vazios. Ele segue isso aqui .
fonte
Aqui está uma versão mais compacta da resposta acima . Com exemplo.
Corre:
Observe que ter os dois
_OVR
e_OVR_EXPAND
pode parecer redundante, mas é necessário que o pré-processador expanda a_COUNT_ARGS(__VA_ARGS__)
peça, que de outra forma é tratada como uma sequência.fonte
Talvez você possa usar essa macro para contar o número de argumentos .
fonte
Aqui está um resumo da resposta de Evgeni Sergeev. Este também suporta zero sobrecarga de argumentos !
Eu testei isso com GCC e MinGW. Ele deve funcionar com versões antigas e novas do C ++. Observe que eu não garantiria isso para o MSVC ... Mas, com alguns ajustes, estou confiante de que poderia ser feito para trabalhar com isso também.
Também formatei isso para ser colado em um arquivo de cabeçalho (que chamei macroutil.h). Se você fizer isso, poderá incluir apenas esse cabeçalho o que precisar do recurso, e não olhar para a maldade envolvida na implementação.
fonte
Isso parece funcionar bem no GCC, Clang e MSVC. É uma versão limpa de algumas das respostas aqui
fonte
#define func0() foo
? A versão atual não lida com esse caso, infelizmente.