Talvez sobrecargas de função, parâmetros padrão, modelos de variáveis ou possivelmente o idioma do parâmetro nomeado sejam o que você está procurando
smoothware de
Por favor, atualize sua resposta selecionada para as mais votadas com soluções reais, não aquela que diz respeito às votações humildesNo you can't
Albert Renshaw
Respostas:
156
Aqui está uma maneira de fazer isso. Ele usa a lista de argumentos duas vezes, primeiro para formar o nome da macro auxiliar e, em seguida, para passar os argumentos para essa macro auxiliar. Ele usa um truque padrão para contar o número de argumentos para uma macro.
Isso é muito legal, mas não acho que funcionaria se eu apenas fizesse PRINT_STRING. Nesse caso, não haveria uma impressão padrão (e esse é realmente o caso que desejo utilizar). Ainda +1 para muito legal.
Cenoc
2
funciona para mim no gcc (e é muito inteligente!) :-) mas não funciona para mim no Visual Studio :-(
Tim Gradwell
3
@TimGradwell - é devido a um bug no compilador MSVC que eles reconheceram, mas não corrigiram em quase uma década. No entanto, soluções alternativas estão disponíveis .
BeeOnRope de
Inteligente, mas não funciona para argumentos macro variáveis opcionais por causa da coisa de 'empurrar' que você está fazendo em `GET_4th_ARG '.
searchengine27
isso é PRINT_STRING_MACRO_CHOOSERmesmo necessário? Posso substituir seu corpo interno diretamente e chamar essa coisa toda de (__VA_ARGS__)?
Herrgott
85
Com grande respeito a Derek Ledbetter por sua resposta - e com desculpas por reavivar uma velha questão.
Compreender o que estava fazendo e pegar em outro lugar a capacidade de preceder o __VA_ARGS__com ##me permitiu chegar a uma variação ...
// The multiple macros that you would need anyway [as per: Crazy Eddie]#define XXX_0()<code for no arguments>#define XXX_1(A)<code for one argument>#define XXX_2(A,B)<code for two arguments>#define XXX_3(A,B,C)<code for three arguments>#define XXX_4(A,B,C,D)<code for four arguments>// The interim macro that simply strips the excess and ends up with the required macro#define XXX_X(x,A,B,C,D,FUNC,...) FUNC
// The macro that the programmer uses #define XXX(...) XXX_X(,##__VA_ARGS__,\
XXX_4(__VA_ARGS__),\
XXX_3(__VA_ARGS__),\
XXX_2(__VA_ARGS__),\
XXX_1(__VA_ARGS__),\
XXX_0(__VA_ARGS__)\
)
Para não especialistas como eu, que encontram a resposta, mas não conseguem ver como funciona, examinarei o processamento real, começando com o código a seguir ...
XXX();
XXX(1);
XXX(1,2);
XXX(1,2,3);
XXX(1,2,3,4);
XXX(1,2,3,4,5);// Not actually valid, but included to show the process
Você poderia obter um erro de compilação claro se convertesse o argumento selecionado, que deveria ser um nome MACRO, em string usando # (o sinal de libra) e comparasse seus primeiros n caracteres com o prefixo esperado e, se não houver correspondência, imprima um informativo erro.
AturSams
1
Nossa, não sei se isso funciona, mas é pelo menos muito criativo!
Expiação limitada de
4
por que o primeiro argumento está sempre vazio? por que não podemos simplesmente omiti-lo: XXX_X(,##__VA_ARGS__,` ... XXX_X (, XXX_4 (), XXX_3 (), XXX_2 (), XXX_1 (), XXX_0 ()); `
rahman
2
O primeiro argumento vazio (vírgula) é importante. ## __ VA_ARGS__ se for precedido por uma vírgula - remove a vírgula se ## __ VA_ARGS__ se expandir para nada. Você pode ver isso no exemplo "Torna-se ..." já que a primeira linha (sem argumentos) tem apenas 6 parâmetros, mas o resto obtém 7. Este truque garante que a situação sem argumentos funcione
David Sorkovsky
@Eric - é devido a um bug nos compiladores da Microsoft, mas você pode ver esta questão para soluções alternativas.
BeeOnRope de
31
As macros C ++ não mudaram de C. Uma vez que C não tinha sobrecarga e argumentos padrão para funções, certamente não os tinha para macros. Portanto, para responder à sua pergunta: não, esses recursos não existem para macros. Sua única opção é definir várias macros com nomes diferentes (ou não usar macros).
Como nota: em C ++, geralmente é considerado uma boa prática afastar-se das macros o máximo possível. Se você precisa de recursos como este, há uma boa chance de estar usando macros em excesso.
Observe que a razão pela qual é impossível "sobrecarregar" macros é porque elas não têm nenhum tipo inerente. As macros são simplesmente expandidas.
mk12 de
2
Embora eu use macros o mínimo possível, descobri que a depuração via saída de rastreamento fica um pouco mais fácil com coisas como __FILE__e __LINE__e tal ...
Compilação condicional e depuração / registro é o domínio onde as macros são realmente úteis e legítimas. Todo programador sério sabe disso. O que é uma boa prática é deixar de usar macros para definir constantes e fazer algumas coisas malucas de codificação de nível C para criar modelos de contêiner. Eu gostaria que C ++ adicionasse mais recursos às macros também. Eles são ortogonais aos modelos. O melhor, é claro, seriam os codelets que me permitem adicionar geradores ao compilador para linguagem específica de domínio (aspectos).
Lothar
1
Também acho que essa não é uma boa resposta, porque uma macro é algo completamente diferente de qualquer opção de linguagem C ++, porque ela será tratada ANTES do compilador. Portanto, você pode fazer outras coisas, e nenhum compilador ou vinculador deve otimizar o código, porque talvez não seja para otimizar.
alabamajack
26
Com o maior respeito a Derek Ledbetter , David Sorkovsky , Syphorlate por suas respostas, junto com o método engenhoso para detectar macro argumentos vazios por Jens Gustedt em
finalmente, saio com algo que incorpora todos os truques, para que a solução
Usa apenas macros C99 padrão para atingir sobrecarga de função, nenhuma extensão GCC / CLANG / MSVC envolvida (ou seja, deglutição de vírgula pela expressão específica , ##__VA_ARGS__para GCC / CLANG e deglutição implícita por ##__VA_ARGS__para MSVC). Então fique à vontade para passar pelo que falta--std=c99 para o seu compilador se desejar =)
Funciona com nenhum argumento , bem como um número ilimitado de argumentos , se você expandir ainda mais para atender às suas necessidades
Funciona razoavelmente em várias plataformas , pelo menos testado para
GNU / Linux + GCC (GCC 4.9.2 no CentOS 7.0 x86_64)
GNU / Linux + CLANG / LLVM , (CLANG / LLVM 3.5.0 no CentOS 7.0 x86_64)
OS X + Xcode , (XCode 6.1.1 no OS X Yosemite 10.10.1)
Windows + Visual Studio , (Visual Studio 2013 Atualização 4 no Windows 7 SP1 de 64 bits)
Para os preguiçosos, basta pular para o último deste post para copiar a fonte. Abaixo está a explicação detalhada, o que esperançosamente ajuda e inspira todas as pessoas que procuram o__VA_ARGS__ soluções como eu. =)
É assim que funciona. Primeiro defina a "função" visível ao usuário sobrecarregado, I nomeou-o create, e a definição da função reais relacionados realCreate, e as definições de macros com diferente número de argumentos CREATE_2, CREATE_1, CREATE_0, como mostrado abaixo:
A MACRO_CHOOSER(__VA_ARGS__)parte em última análise resolve para os nomes de definição de macro e a segunda (__VA_ARGS__)parte compreende suas listas de parâmetros. Assim, a chamada de um usuário para create(10)resolve para CREATE_1(10), a CREATE_1parte vem MACRO_CHOOSER(__VA_ARGS__)e o(10) parte vem do segundo (__VA_ARGS__).
O MACRO_CHOOSERusa o truque de que, se __VA_ARGS__estiver vazio, a seguinte expressão será concatenada em uma chamada de macro válida pelo pré-processador:
NO_ARG_EXPANDER __VA_ARGS__ ()// simply shrinks to NO_ARG_EXPANDER()
Engenhosamente, podemos definir esta chamada de macro resultante como
#define NO_ARG_EXPANDER(),,CREATE_0
Observe as duas vírgulas, elas serão explicadas em breve. A próxima macro útil é
Como o nome da macro sugere, devemos contar o número de argumentos posteriormente. Aí vem outro truque: o pré-processador só faz uma simples substituição de texto. Ele infere o número de argumentos de uma chamada de macro apenas a partir do número de vírgulas que vê entre parênteses. Os "argumentos" reais separados por vírgulas não precisam ter sintaxe válida. Eles podem ser qualquer texto. Ou seja, no exemplo acima, NO_ARG_EXPANDER 10 ()é contado como 1 argumento para a chamada do meio. NO_ARG_EXPANDER 20e 20 ()são contados como 2 argumentos para a chamada inferior, respectivamente.
Se usarmos as seguintes macros auxiliares para expandi-los ainda mais
A fuga ,depois CREATE_1é uma forma de contornar GCC / CLANG, suprimindo um erro (falsos positivos) dizendo que ISO C99 requires rest arguments to be usedquando passar -pedanticpara o seu compilador. O FUNC_RECOMPOSERé uma solução alternativa para o MSVC ou não pode contar o número de argumentos (ou seja, vírgulas) entre parênteses de chamadas de macro corretamente. Os resultados são posteriormente resolvidos para
Como você deve ter percebido, a última e única etapa de que precisamos é empregar um truque de contagem de argumentos padrão para finalmente escolher os nomes de versão de macro desejados:
#define FUNC_CHOOSER(_f1, _f2, _f3,...) _f3
que resolve os resultados para
CREATE_0();
CREATE_1(10);
CREATE_2(20,20);
e certamente nos dá as chamadas de função reais desejadas:
Embora complicado, feio, sobrecarregando o desenvolvedor de API, surge uma solução para sobrecarregar e definir parâmetros opcionais de funções C / C ++ para nós, loucos. O uso das APIs sobrecarregadas que estão chegando se tornou muito agradável e agradável. =)
Se houver qualquer outra simplificação possível dessa abordagem, por favor, me avise em
@Phylliida ideone.com/jD0Hm5 - de zero a cinco argumentos suportados.
xx
9
Para qualquer pessoa que pesquise com dificuldade alguma solução VA_NARGS que funcione com Visual C ++. A macro a seguir funcionou perfeitamente para mim (também com parâmetros zero!) No visual c ++ express 2010:
#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,N,...) N
#define VA_NUM_ARGS_IMPL_(tuple) VA_NUM_ARGS_IMPL tuple
#define VA_NARGS(...)bool(#__VA_ARGS__)?(VA_NUM_ARGS_IMPL_((__VA_ARGS__,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1))):0
Se você quiser uma macro com parâmetros opcionais, pode fazer:
Estou recebendounresolved external symbol _bool referenced in function _main
Avidan Borisov
sim, isso pode acontecer em alguns casos. você precisa estar ciente de que bool (#__ VA_ARGS__)? é diferente das outras macros, pois está sendo avaliada em tempo de execução. dependendo do seu caso, você pode omitir essa parte do código.
Syphorlate
2
Na verdade, acabei com pastebin.com/H3T75dcn, que funciona perfeitamente (0 argumentos também).
Avidan Borisov
Obrigado pelo link, e sim você pode fazer isso usando sizeof também, mas para mim isso não funcionou em alguns casos, mas o princípio é o mesmo (avaliação booleana).
Syphorlate
Você poderia dar alguns exemplos onde ele falha?
Avidan Borisov
7
gcc/ g++suporta macros varargs, mas não acho que seja padrão, então use-o por sua própria conta e risco.
Eles são padrão no C99 e estão sendo adicionados ao C ++ 0x também.
greyfade de
5
#include<stdio.h>#define PP_NARG(...) \
PP_NARG_(__VA_ARGS__,PP_RSEQ_N())#define PP_NARG_(...) \
PP_ARG_N(__VA_ARGS__)#define PP_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63,N,...) N
#define PP_RSEQ_N() \
63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0#define PP_CONCAT(a,b) PP_CONCAT_(a,b)#define PP_CONCAT_(a,b) a ## b#define THINK(...) PP_CONCAT(THINK_, PP_NARG(__VA_ARGS__))(__VA_ARGS__)#define THINK_0() THINK_1("sector zz9 plural z alpha")#define THINK_1(location) THINK_2(location,42)#define THINK_2(location,answer) THINK_3(location, answer,"deep thought")#define THINK_3(location,answer,computer) \
printf ("The answer is %d. This was calculated by %s, and a computer to figure out what this"" actually means will be build in %s\n",(answer),(computer),(location))int
main (int argc,char*argv[]){
THINK ();/* On compilers other than GCC you have to call with least one non-default argument */}
há um erro no seu código. por favor faça :%s/MY_MACRO_/THINK_/g:)
João Portela
também não funcionou com nenhum argumento usando g ++i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664)
João Portela
1
Argumentos zero não existem para macros variadiac, uma vez que o token vazio é um marcador válido.
Paul Fultz II
3
Não é exatamente para isso que o pré-processador foi projetado.
Dito isso, se você quiser entrar na área de um desafio sério de programação de macro com um mínimo de legibilidade, você deve dar uma olhada na biblioteca de pré-processador Boost . Afinal, não seria C ++ se não houvesse três níveis de programação totalmente compatíveis com Turing (pré-processador, metaprogramação de modelo e nível básico C ++)!
Como um grande fã de monstros macro horríveis, eu queria expandir a resposta de Jason Deng e torná-la realmente utilizável. (Para o bem ou para o mal.) O original não é muito agradável de usar porque você precisa modificar a grande sopa de letrinhas toda vez que quiser fazer uma nova macro e é ainda pior se você precisar de diferentes quantidades de argumentos.
Então fiz uma versão com estes recursos:
0 caso de argumento funciona
1 a 16 argumentos sem nenhuma modificação na parte confusa
Fácil de escrever mais funções macro
Testado em gcc 10, clang 9, Visual Studio 2017
Atualmente, acabei de criar no máximo 16 argumentos, mas se precisar de mais (realmente agora? Você está ficando bobo ...), pode editar FUNC_CHOOSER e CHOOSE_FROM_ARG_COUNT e adicionar algumas vírgulas a NO_ARG_EXPANDER.
Consulte a excelente resposta de Jason Deng para obter mais detalhes sobre a implementação, mas apenas colocarei o código aqui:
#include<stdio.h>void realCreate(int x,int y){
printf("(%d, %d)\n", x, y);}// This part you put in some library header:#define FUNC_CHOOSER(_f0, _f1, _f2, _f3, _f4, _f5, _f6, _f7, _f8, _f9, _f10, _f11, _f12, _f13, _f14, _f15, _f16,...) _f16
#define FUNC_RECOMPOSER(argsWithParentheses) FUNC_CHOOSER argsWithParentheses
#define CHOOSE_FROM_ARG_COUNT(F,...) FUNC_RECOMPOSER((__VA_ARGS__, \
F##_16, F##_15, F##_14, F##_13, F##_12, F##_11, F##_10, F##_9, F##_8,\
F##_7, F##_6, F##_5, F##_4, F##_3, F##_2, F##_1, ))#define NO_ARG_EXPANDER(FUNC),,,,,,,,,,,,,,,,FUNC ## _0#define MACRO_CHOOSER(FUNC,...) CHOOSE_FROM_ARG_COUNT(FUNC, NO_ARG_EXPANDER __VA_ARGS__ (FUNC))#define MULTI_MACRO(FUNC,...) MACRO_CHOOSER(FUNC, __VA_ARGS__)(__VA_ARGS__)// When you need to make a macro with default arguments, use this:#define create(...) MULTI_MACRO(CREATE, __VA_ARGS__)#define CREATE_0() CREATE_1(0)#define CREATE_1(x) CREATE_2(x,0)#define CREATE_2(x, y) \
do{ \
/* put whatever code you want in the last macro */ \
realCreate(x, y); \
}while(0)int main(){
create();
create(10);
create(20,20);//create(30, 30, 30); // Compilation errorreturn0;}
Dependendo do que você precisa, você pode fazer isso com var args com macros. Agora, parâmetros opcionais ou sobrecarga de macro, não existe tal coisa.
Nenhum dos exemplos acima (de Derek Ledbetter, David Sorkovsky e Joe D) para contar argumentos com macros funcionou para mim usando o Microsoft VCC 10. O __VA_ARGS__argumento é sempre considerado como um único argumento (token-izing com ##ou não), então a mudança de argumento na qual esses exemplos se baseiam não funciona.
Portanto, uma resposta curta, como afirmado por muitos outros acima: não, você não pode sobrecarregar macros ou usar argumentos opcionais nelas.
Você pode, mas apenas em C99 ou C ++ 11 (devido a ter __VA_ARGS__). VC2010 é C89 / C ++ 03 (com alguns bits de C ++ 11 começando a aparecer, mas não aquele ainda).
No you can't
Respostas:
Aqui está uma maneira de fazer isso. Ele usa a lista de argumentos duas vezes, primeiro para formar o nome da macro auxiliar e, em seguida, para passar os argumentos para essa macro auxiliar. Ele usa um truque padrão para contar o número de argumentos para uma macro.
Isso torna mais fácil para o chamador da macro, mas não para o gravador.
fonte
PRINT_STRING_MACRO_CHOOSER
mesmo necessário? Posso substituir seu corpo interno diretamente e chamar essa coisa toda de(__VA_ARGS__)
?Com grande respeito a Derek Ledbetter por sua resposta - e com desculpas por reavivar uma velha questão.
Compreender o que estava fazendo e pegar em outro lugar a capacidade de preceder o
__VA_ARGS__
com##
me permitiu chegar a uma variação ...Para não especialistas como eu, que encontram a resposta, mas não conseguem ver como funciona, examinarei o processamento real, começando com o código a seguir ...
Torna-se...
Que se torna apenas o sexto argumento ...
PS: Remova o #define para XXX_0 para obter um erro de compilação [ie: se uma opção sem argumento não for permitida].
PPS: Seria bom que as situações inválidas (por exemplo: 5) fossem algo que fornecesse um erro de compilação mais claro para o programador!
PPPS: Não sou especialista, por isso fico muito feliz em ouvir comentários (bons, ruins ou outros)!
fonte
XXX_X(,##__VA_ARGS__,` ...
XXX_X (, XXX_4 (), XXX_3 (), XXX_2 (), XXX_1 (), XXX_0 ()); `As macros C ++ não mudaram de C. Uma vez que C não tinha sobrecarga e argumentos padrão para funções, certamente não os tinha para macros. Portanto, para responder à sua pergunta: não, esses recursos não existem para macros. Sua única opção é definir várias macros com nomes diferentes (ou não usar macros).
Como nota: em C ++, geralmente é considerado uma boa prática afastar-se das macros o máximo possível. Se você precisa de recursos como este, há uma boa chance de estar usando macros em excesso.
fonte
__FILE__
e__LINE__
e tal ...Com o maior respeito a Derek Ledbetter , David Sorkovsky , Syphorlate por suas respostas, junto com o método engenhoso para detectar macro argumentos vazios por Jens Gustedt em
https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
finalmente, saio com algo que incorpora todos os truques, para que a solução
, ##__VA_ARGS__
para GCC / CLANG e deglutição implícita por##__VA_ARGS__
para MSVC). Então fique à vontade para passar pelo que falta--std=c99
para o seu compilador se desejar =)Funciona razoavelmente em várias plataformas , pelo menos testado para
Para os preguiçosos, basta pular para o último deste post para copiar a fonte. Abaixo está a explicação detalhada, o que esperançosamente ajuda e inspira todas as pessoas que procuram o
__VA_ARGS__
soluções como eu. =)É assim que funciona. Primeiro defina a "função" visível ao usuário sobrecarregado, I nomeou-o
create
, e a definição da função reais relacionadosrealCreate
, e as definições de macros com diferente número de argumentosCREATE_2
,CREATE_1
,CREATE_0
, como mostrado abaixo:A
MACRO_CHOOSER(__VA_ARGS__)
parte em última análise resolve para os nomes de definição de macro e a segunda(__VA_ARGS__)
parte compreende suas listas de parâmetros. Assim, a chamada de um usuário paracreate(10)
resolve paraCREATE_1(10)
, aCREATE_1
parte vemMACRO_CHOOSER(__VA_ARGS__)
e o(10)
parte vem do segundo(__VA_ARGS__)
.O
MACRO_CHOOSER
usa o truque de que, se__VA_ARGS__
estiver vazio, a seguinte expressão será concatenada em uma chamada de macro válida pelo pré-processador:Engenhosamente, podemos definir esta chamada de macro resultante como
Observe as duas vírgulas, elas serão explicadas em breve. A próxima macro útil é
então as chamadas de
são realmente expandidos para
Como o nome da macro sugere, devemos contar o número de argumentos posteriormente. Aí vem outro truque: o pré-processador só faz uma simples substituição de texto. Ele infere o número de argumentos de uma chamada de macro apenas a partir do número de vírgulas que vê entre parênteses. Os "argumentos" reais separados por vírgulas não precisam ter sintaxe válida. Eles podem ser qualquer texto. Ou seja, no exemplo acima,
NO_ARG_EXPANDER 10 ()
é contado como 1 argumento para a chamada do meio.NO_ARG_EXPANDER 20
e20 ()
são contados como 2 argumentos para a chamada inferior, respectivamente.Se usarmos as seguintes macros auxiliares para expandi-los ainda mais
A fuga
,
depoisCREATE_1
é uma forma de contornar GCC / CLANG, suprimindo um erro (falsos positivos) dizendo queISO C99 requires rest arguments to be used
quando passar-pedantic
para o seu compilador. OFUNC_RECOMPOSER
é uma solução alternativa para o MSVC ou não pode contar o número de argumentos (ou seja, vírgulas) entre parênteses de chamadas de macro corretamente. Os resultados são posteriormente resolvidos paraComo você deve ter percebido, a última e única etapa de que precisamos é empregar um truque de contagem de argumentos padrão para finalmente escolher os nomes de versão de macro desejados:
que resolve os resultados para
e certamente nos dá as chamadas de função reais desejadas:
Juntando tudo, com algum rearranjo de declarações para melhor legibilidade, toda a fonte do exemplo de 2 argumentos está aqui:
Embora complicado, feio, sobrecarregando o desenvolvedor de API, surge uma solução para sobrecarregar e definir parâmetros opcionais de funções C / C ++ para nós, loucos. O uso das APIs sobrecarregadas que estão chegando se tornou muito agradável e agradável. =)
Se houver qualquer outra simplificação possível dessa abordagem, por favor, me avise em
https://github.com/jason-deng/C99FunctionOverload
Mais uma vez, um agradecimento especial a todas as pessoas brilhantes que me inspiraram e levaram a concretizar este trabalho! =)
fonte
Para qualquer pessoa que pesquise com dificuldade alguma solução VA_NARGS que funcione com Visual C ++. A macro a seguir funcionou perfeitamente para mim (também com parâmetros zero!) No visual c ++ express 2010:
Se você quiser uma macro com parâmetros opcionais, pode fazer:
Isso funcionou para mim também em vc. Mas não funciona para parâmetros zero.
fonte
unresolved external symbol _bool referenced in function _main
gcc
/g++
suporta macros varargs, mas não acho que seja padrão, então use-o por sua própria conta e risco.fonte
AVISO LEGAL: Principalmente inofensivo.
fonte
:%s/MY_MACRO_/THINK_/g
:)i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664)
Não é exatamente para isso que o pré-processador foi projetado.
Dito isso, se você quiser entrar na área de um desafio sério de programação de macro com um mínimo de legibilidade, você deve dar uma olhada na biblioteca de pré-processador Boost . Afinal, não seria C ++ se não houvesse três níveis de programação totalmente compatíveis com Turing (pré-processador, metaprogramação de modelo e nível básico C ++)!
fonte
Você sabe no momento da chamada quantos args vai passar, então não há realmente necessidade de sobrecarga.
fonte
Versão mais concisa do código de Derek Ledbetter:
fonte
Como um grande fã de monstros macro horríveis, eu queria expandir a resposta de Jason Deng e torná-la realmente utilizável. (Para o bem ou para o mal.) O original não é muito agradável de usar porque você precisa modificar a grande sopa de letrinhas toda vez que quiser fazer uma nova macro e é ainda pior se você precisar de diferentes quantidades de argumentos.
Então fiz uma versão com estes recursos:
Atualmente, acabei de criar no máximo 16 argumentos, mas se precisar de mais (realmente agora? Você está ficando bobo ...), pode editar FUNC_CHOOSER e CHOOSE_FROM_ARG_COUNT e adicionar algumas vírgulas a NO_ARG_EXPANDER.
Consulte a excelente resposta de Jason Deng para obter mais detalhes sobre a implementação, mas apenas colocarei o código aqui:
fonte
Você pode usar
BOOST_PP_OVERLOAD
de umboost
biblioteca.Exemplo do documento de reforço oficial :
fonte
Dependendo do que você precisa, você pode fazer isso com var args com macros. Agora, parâmetros opcionais ou sobrecarga de macro, não existe tal coisa.
fonte
Nenhum dos exemplos acima (de Derek Ledbetter, David Sorkovsky e Joe D) para contar argumentos com macros funcionou para mim usando o Microsoft VCC 10. O
__VA_ARGS__
argumento é sempre considerado como um único argumento (token-izing com##
ou não), então a mudança de argumento na qual esses exemplos se baseiam não funciona.Portanto, uma resposta curta, como afirmado por muitos outros acima: não, você não pode sobrecarregar macros ou usar argumentos opcionais nelas.
fonte