Peut-être que vous recherchez des surcharges de fonctions, des paramètres par défaut, des modèles variadiques ou peut-être l'idiome de paramètre nommé
smoothware
Veuillez mettre à jour votre réponse sélectionnée en fonction des réponses les plus votées avec des solutions réelles, et non des réponses les plus modestesNo you can't
Albert Renshaw
Réponses:
158
Voici une façon de le faire. Il utilise la liste d'arguments deux fois, d'abord pour former le nom de la macro d'assistance, puis pour transmettre les arguments à cette macro d'assistance. Il utilise une astuce standard pour compter le nombre d'arguments d'une macro.
C'est plutôt cool, mais je ne pense pas que cela fonctionnerait si je faisais juste PRINT_STRING. Dans ce cas, il n'y aurait pas d'impression par défaut (et c'est en fait le cas que je veux utiliser). Toujours +1 pour vraiment cool.
Cenoc
2
fonctionne pour moi dans gcc (et c'est très intelligent!) :-) mais ne fonctionne pas pour moi dans Visual Studio :-(
Tim Gradwell
3
@TimGradwell - c'est dû à un bogue dans le compilateur MSVC qu'ils ont reconnu mais n'ont pas corrigé depuis près d'une décennie. Cependant, des solutions de contournement sont disponibles .
BeeOnRope
Intelligent, mais ne fonctionne pas pour les arguments macro variadiques optionnels à cause de la chose 'push out' que vous avez en cours dans `GET_4th_ARG '.
searchengine27
est-ce PRINT_STRING_MACRO_CHOOSERmême nécessaire? Puis-je remplacer directement par son corps intérieur et appeler tout cela avec (__VA_ARGS__)?
Herrgott
85
Avec beaucoup de respect à Derek Ledbetter pour sa réponse - et avec mes excuses pour avoir relancé une vieille question.
Comprendre ce qu'il faisait et reprendre ailleurs sur la capacité de précéder le __VA_ARGS__avec ##m'a permis de proposer une variation ...
// 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__)\)
Pour les non-experts comme moi qui tombent sur la réponse, mais ne peuvent pas vraiment voir comment cela fonctionne, je vais passer en revue le traitement réel, en commençant par le code suivant ...
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
Vous pouvez obtenir une erreur de compilation claire si vous convertissez l'argument sélectionné qui est supposé être un nom MACRO en chaîne en utilisant # (le signe dièse) et comparez ses n premiers caractères avec le préfixe attendu et s'il n'y a pas de correspondance, imprimez un message informatif Erreur.
AturSams
1
Wow, je ne sais pas si cela fonctionne, mais c'est au moins très créatif!
Expiation limitée le
4
pourquoi le premier argument est-il toujours vide? pourquoi ne pouvons-nous simplement l'omettre: XXX_X(,##__VA_ARGS__,` ... XXX_X (, XXX_4 (), XXX_3 (), XXX_2 (), XXX_1 (), XXX_0 ()); `
rahman
2
Le premier argument vide (virgule) est important. ## __ VA_ARGS__ s'il est précédé d'une virgule - il supprime la virgule si ## __ VA_ARGS__ se développe en rien. Vous pouvez le voir dans l'exemple "Devient ..." car la première ligne (sans arguments) n'a que 6 paramètres mais le reste en obtient 7. Cette astuce garantit que la situation sans arguments fonctionne
David Sorkovsky
@Eric - c'est dû à un bogue dans les compilateurs Microsoft, mais vous pouvez voir cette question pour des solutions de contournement.
BeeOnRope
31
Les macros C ++ n'ont pas changé depuis C. Comme C n'avait pas de surcharge et d'arguments par défaut pour les fonctions, il n'en avait certainement pas pour les macros. Donc pour répondre à votre question: non, ces fonctionnalités n'existent pas pour les macros. Votre seule option est de définir plusieurs macros avec des noms différents (ou de ne pas utiliser de macros du tout).
Remarque: en C ++, il est généralement considéré comme une bonne pratique de s'éloigner le plus possible des macros. Si vous avez besoin de fonctionnalités comme celle-ci, il y a de fortes chances que vous abusiez des macros.
Notez que la raison pour laquelle il est impossible de "surcharger" les macros est qu'elles n'ont aucun type inhérent. Les macros sont simplement développées.
mk12
2
Bien que j'utilise le moins de macros possible, j'ai trouvé que le débogage via la sortie de trace devient un peu plus facile avec des choses comme __FILE__et __LINE__et autres ...
La compilation conditionnelle et le débogage / journalisation sont le domaine où les macros sont vraiment pratiques et légitimes. Tout programmeur sérieux le sait. Ce qui est une bonne pratique, c'est d'éviter d'utiliser des macros pour définir des constantes et de faire du codage de niveau C fou pour créer des modèles de conteneurs. Je souhaite que C ++ ajoute également plus de fonctionnalités aux macros. Ils sont orthogonaux aux modèles. Le mieux serait bien sûr les codelets qui me permettent d'ajouter des générateurs dans le compilateur pour le langage spécifique au domaine (aspects).
Lothar
1
Je pense également que ce n'est pas une bonne réponse, car une macro est quelque chose de complètement différent de toute option de langage C ++, car elle sera gérée AVANT le compilateur. Vous pouvez donc faire autre chose, et aucun compilateur ou éditeur de liens ne doit optimiser le code, car ce n'est peut-être pas à optimiser.
alabamajack
26
Avec le plus grand respect à Derek Ledbetter , David Sorkovsky , Syphorlate pour leurs réponses, ainsi que la méthode ingénieuse pour détecter les macro-arguments vides de Jens Gustedt à
enfin je viens avec quelque chose qui incorpore toutes les astuces, de sorte que la solution
Utilise uniquement des macros C99 standard pour réaliser une surcharge de fonction, aucune extension GCC / CLANG / MSVC impliquée (c'est-à-dire, une virgule avalée par l'expression spécifique , ##__VA_ARGS__pour GCC / CLANG et une avalée implicite par ##__VA_ARGS__pour MSVC). Alors n'hésitez pas à transmettre le manquant --std=c99à votre compilateur si vous le souhaitez =)
Fonctionne pour zéro argument , ainsi qu'un nombre illimité d'arguments , si vous l'étendez davantage pour répondre à vos besoins
Fonctionne raisonnablement multiplateforme , au moins testé pour
GNU / Linux + GCC (GCC 4.9.2 sur CentOS 7.0 x86_64)
GNU / Linux + CLANG / LLVM , (CLANG / LLVM 3.5.0 sur CentOS 7.0 x86_64)
OS X + Xcode , (XCode 6.1.1 sur OS X Yosemite 10.10.1)
Windows + Visual Studio , (Visual Studio 2013 Update 4 sur Windows 7 SP1 64 bits)
Pour les paresseux, passez simplement au tout dernier de cet article pour copier la source. Vous trouverez ci-dessous l'explication détaillée qui, espérons-le, aide et inspire toutes les personnes à la recherche de __VA_ARGS__solutions générales comme moi. =)
Voici comment ça se passe. Tout d' abord définir la « fonction » surcharge utilisateur visible, je l' ai appelé create, et la définition de la fonction réelle liée realCreate, et les définitions de macros avec nombre différent d'arguments CREATE_2, CREATE_1, CREATE_0comme indiqué ci - dessous:
La MACRO_CHOOSER(__VA_ARGS__)partie résout finalement les noms de définition de macro, et la deuxième (__VA_ARGS__)partie comprend leurs listes de paramètres. Ainsi, l'appel d'un utilisateur à se create(10)résout à CREATE_1(10), la CREATE_1pièce vient de MACRO_CHOOSER(__VA_ARGS__), et la (10)pièce vient de la seconde (__VA_ARGS__).
Le MACRO_CHOOSERutilise l'astuce que, si elle __VA_ARGS__est vide, l'expression suivante est concaténée en un appel de macro valide par le préprocesseur:
NO_ARG_EXPANDER __VA_ARGS__ ()// simply shrinks to NO_ARG_EXPANDER()
Ingénieusement, nous pouvons définir cet appel de macro résultant comme
#define NO_ARG_EXPANDER(),,CREATE_0
Notez les deux virgules, elles sont expliquées bientôt. La prochaine macro utile est
Comme le nom de la macro l'indique, nous devons compter le nombre d'arguments plus tard. Voici une autre astuce: le préprocesseur ne fait qu'un simple remplacement de texte. Il déduit le nombre d'arguments d'un appel de macro simplement à partir du nombre de virgules qu'il voit à l'intérieur des parenthèses. Les "arguments" réels séparés par des virgules n'ont pas besoin d'être de syntaxe valide. Ils peuvent être n'importe quel texte. C'est-à-dire que, dans l'exemple ci-dessus, NO_ARG_EXPANDER 10 ()est compté comme 1 argument pour l'appel du milieu. NO_ARG_EXPANDER 20et 20 ()sont comptés comme 2 arguments pour l'appel du bas respectivement.
Si nous utilisons les macros d'assistance suivantes pour les développer davantage
La fin ,après CREATE_1est une solution de contournement pour GCC / CLANG, supprimant une erreur (faux positif) indiquant cela ISO C99 requires rest arguments to be usedlors du passage -pedanticà votre compilateur. Il FUNC_RECOMPOSERs'agit d'une solution de contournement pour MSVC, ou il ne peut pas compter correctement le nombre d'arguments (c'est-à-dire, des virgules) entre les parenthèses des appels de macro. Les résultats sont en outre résolus à
Comme vous l'avez peut-être vu, la dernière étape dont nous avons besoin est d'utiliser une astuce de comptage d'arguments standard pour enfin choisir les noms de version de macro voulus:
#define FUNC_CHOOSER(_f1, _f2, _f3,...) _f3
qui résout les résultats à
CREATE_0();
CREATE_1(10);
CREATE_2(20,20);
et nous donne certainement les appels de fonction souhaités et réels:
Bien que compliqué, laid, pesant sur le développeur d'API, il existe une solution pour surcharger et définir les paramètres optionnels des fonctions C / C ++ pour nous les fous. L'utilisation des API surchargées sortantes devient très agréable et agréable. =)
S'il y a une autre simplification possible de cette approche, veuillez me le faire savoir à
@Phylliida ideone.com/jD0Hm5 - zéro à cinq arguments pris en charge.
xx
9
Pour quiconque recherche péniblement une solution VA_NARGS qui fonctionne avec Visual C ++. La macro suivante a fonctionné pour moi parfaitement (également avec zéro paramètre!) Dans Visual C ++ Express 2010:
Je reçoisunresolved external symbol _bool referenced in function _main
Avidan Borisov
oui cela peut arriver dans certains cas. vous devez être conscient que bool (#__ VA_ARGS__)? est différente des autres macros car elle est en cours d'évaluation au moment de l'exécution. selon votre cas, vous pouvez toutefois omettre cette partie du code.
Syphorlate
2
En fait, je me suis retrouvé avec pastebin.com/H3T75dcn qui fonctionne parfaitement (0 argument aussi).
Avidan Borisov
Merci pour le lien, et oui vous pouvez le faire en utilisant aussi sizeof mais pour moi cela n'a pas fonctionné dans certains cas mais le principe est le même (évaluation booléenne).
Syphorlate
Pourriez-vous donner des exemples où cela échoue?
Avidan Borisov
7
gcc/ g++prend en charge les macros varargs mais je ne pense pas que ce soit standard, alors utilisez-le à vos risques et périls.
Ils sont standard dans C99 et ils sont également ajoutés à C ++ 0x.
greyfade
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 */}
il y a une erreur dans votre code. s'il vous plaît faire :%s/MY_MACRO_/THINK_/g:)
João Portela
également, cela ne fonctionnait pas avec zéro argument en utilisant g ++i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664)
João Portela
1
Aucun argument n'existe pour les macros variadiaques, car le jeton vide est un espace réservé valide.
Paul Fultz II
3
Ce n'est pas vraiment ce pour quoi le préprocesseur est conçu.
Cela dit, si vous voulez entrer dans le domaine de la programmation de macros sérieusement difficile avec un minimum de lisibilité, vous devriez jeter un coup d'œil à la bibliothèque de préprocesseurs Boost . Après tout, ce ne serait pas C ++ s'il n'y avait pas trois niveaux de programmation totalement compatibles avec Turing (préprocesseur, métaprogrammation de modèles et C ++ de niveau de base)!
En tant que grand fan d'horribles monstres macro, je voulais développer la réponse de Jason Deng et la rendre réellement utilisable. (Pour le meilleur ou pour le pire.) L'original n'est pas très agréable à utiliser car vous devez modifier la grande soupe à l'alphabet à chaque fois que vous voulez faire une nouvelle macro et c'est encore pire si vous avez besoin d'un nombre d'arguments différent.
J'ai donc fait une version avec ces fonctionnalités:
0 argument cas fonctionne
1 à 16 arguments sans aucune modification de la partie désordonnée
Facile à écrire plus de fonctions macro
Testé dans gcc 10, clang 9, Visual Studio 2017
Actuellement, je viens de faire un maximum de 16 arguments, mais si vous avez besoin de plus (vraiment maintenant? Vous devenez simplement idiot ...) vous pouvez modifier FUNC_CHOOSER et CHOOSE_FROM_ARG_COUNT, puis ajouter des virgules à NO_ARG_EXPANDER.
Veuillez consulter l'excellente réponse de Jason Deng pour plus de détails sur l'implémentation, mais je vais simplement mettre le code ici:
#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;}
Selon ce dont vous avez besoin, vous pouvez le faire avec var args avec des macros. Maintenant, les paramètres optionnels ou la surcharge de macro, il n'y a rien de tel.
Aucun des exemples ci-dessus (de Derek Ledbetter, David Sorkovsky et Joe D) pour compter les arguments avec des macros n'a fonctionné pour moi en utilisant Microsoft VCC 10. L' __VA_ARGS__argument est toujours considéré comme un argument unique (le token-izing avec ##ou pas), donc le changement d'argument dans lequel ces exemples reposent ne fonctionne pas.
Donc, réponse courte, comme indiqué par beaucoup d'autres ci-dessus: non, vous ne pouvez pas surcharger les macros ou utiliser des arguments optionnels dessus.
Vous pouvez, mais uniquement en C99 ou C ++ 11 (en raison de la présence de __VA_ARGS__). VC2010 est C89 / C ++ 03 (avec quelques bits de C ++ 11 qui commencent à apparaître, mais pas encore celui-là).
No you can't
Réponses:
Voici une façon de le faire. Il utilise la liste d'arguments deux fois, d'abord pour former le nom de la macro d'assistance, puis pour transmettre les arguments à cette macro d'assistance. Il utilise une astuce standard pour compter le nombre d'arguments d'une macro.
Cela facilite la tâche à l'appelant de la macro, mais pas à l'écrivain.
la source
PRINT_STRING_MACRO_CHOOSER
même nécessaire? Puis-je remplacer directement par son corps intérieur et appeler tout cela avec(__VA_ARGS__)
?Avec beaucoup de respect à Derek Ledbetter pour sa réponse - et avec mes excuses pour avoir relancé une vieille question.
Comprendre ce qu'il faisait et reprendre ailleurs sur la capacité de précéder le
__VA_ARGS__
avec##
m'a permis de proposer une variation ...Pour les non-experts comme moi qui tombent sur la réponse, mais ne peuvent pas vraiment voir comment cela fonctionne, je vais passer en revue le traitement réel, en commençant par le code suivant ...
Devient...
Ce qui devient juste le sixième argument ...
PS: Supprimez le #define pour XXX_0 pour obtenir une erreur de compilation [par exemple: si une option sans argument n'est pas autorisée].
PPS: Ce serait bien que les situations invalides (par exemple: 5) soient quelque chose qui donne une erreur de compilation plus claire au programmeur!
PPPS: Je ne suis pas un expert, donc je suis très heureux d'entendre des commentaires (bons, mauvais ou autres)!
la source
XXX_X(,##__VA_ARGS__,` ...
XXX_X (, XXX_4 (), XXX_3 (), XXX_2 (), XXX_1 (), XXX_0 ()); `Les macros C ++ n'ont pas changé depuis C. Comme C n'avait pas de surcharge et d'arguments par défaut pour les fonctions, il n'en avait certainement pas pour les macros. Donc pour répondre à votre question: non, ces fonctionnalités n'existent pas pour les macros. Votre seule option est de définir plusieurs macros avec des noms différents (ou de ne pas utiliser de macros du tout).
Remarque: en C ++, il est généralement considéré comme une bonne pratique de s'éloigner le plus possible des macros. Si vous avez besoin de fonctionnalités comme celle-ci, il y a de fortes chances que vous abusiez des macros.
la source
__FILE__
et__LINE__
et autres ...Avec le plus grand respect à Derek Ledbetter , David Sorkovsky , Syphorlate pour leurs réponses, ainsi que la méthode ingénieuse pour détecter les macro-arguments vides de Jens Gustedt à
https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/
enfin je viens avec quelque chose qui incorpore toutes les astuces, de sorte que la solution
, ##__VA_ARGS__
pour GCC / CLANG et une avalée implicite par##__VA_ARGS__
pour MSVC). Alors n'hésitez pas à transmettre le manquant--std=c99
à votre compilateur si vous le souhaitez =)Fonctionne raisonnablement multiplateforme , au moins testé pour
Pour les paresseux, passez simplement au tout dernier de cet article pour copier la source. Vous trouverez ci-dessous l'explication détaillée qui, espérons-le, aide et inspire toutes les personnes à la recherche de
__VA_ARGS__
solutions générales comme moi. =)Voici comment ça se passe. Tout d' abord définir la « fonction » surcharge utilisateur visible, je l' ai appelé
create
, et la définition de la fonction réelle liéerealCreate
, et les définitions de macros avec nombre différent d'argumentsCREATE_2
,CREATE_1
,CREATE_0
comme indiqué ci - dessous:La
MACRO_CHOOSER(__VA_ARGS__)
partie résout finalement les noms de définition de macro, et la deuxième(__VA_ARGS__)
partie comprend leurs listes de paramètres. Ainsi, l'appel d'un utilisateur à secreate(10)
résout àCREATE_1(10)
, laCREATE_1
pièce vient deMACRO_CHOOSER(__VA_ARGS__)
, et la(10)
pièce vient de la seconde(__VA_ARGS__)
.Le
MACRO_CHOOSER
utilise l'astuce que, si elle__VA_ARGS__
est vide, l'expression suivante est concaténée en un appel de macro valide par le préprocesseur:Ingénieusement, nous pouvons définir cet appel de macro résultant comme
Notez les deux virgules, elles sont expliquées bientôt. La prochaine macro utile est
donc les appels de
sont en fait étendus à
Comme le nom de la macro l'indique, nous devons compter le nombre d'arguments plus tard. Voici une autre astuce: le préprocesseur ne fait qu'un simple remplacement de texte. Il déduit le nombre d'arguments d'un appel de macro simplement à partir du nombre de virgules qu'il voit à l'intérieur des parenthèses. Les "arguments" réels séparés par des virgules n'ont pas besoin d'être de syntaxe valide. Ils peuvent être n'importe quel texte. C'est-à-dire que, dans l'exemple ci-dessus,
NO_ARG_EXPANDER 10 ()
est compté comme 1 argument pour l'appel du milieu.NO_ARG_EXPANDER 20
et20 ()
sont comptés comme 2 arguments pour l'appel du bas respectivement.Si nous utilisons les macros d'assistance suivantes pour les développer davantage
La fin
,
aprèsCREATE_1
est une solution de contournement pour GCC / CLANG, supprimant une erreur (faux positif) indiquant celaISO C99 requires rest arguments to be used
lors du passage-pedantic
à votre compilateur. IlFUNC_RECOMPOSER
s'agit d'une solution de contournement pour MSVC, ou il ne peut pas compter correctement le nombre d'arguments (c'est-à-dire, des virgules) entre les parenthèses des appels de macro. Les résultats sont en outre résolus àComme vous l'avez peut-être vu, la dernière étape dont nous avons besoin est d'utiliser une astuce de comptage d'arguments standard pour enfin choisir les noms de version de macro voulus:
qui résout les résultats à
et nous donne certainement les appels de fonction souhaités et réels:
En réunissant le tout, avec un réarrangement des instructions pour une meilleure lisibilité, toute la source de l'exemple à 2 arguments est ici:
Bien que compliqué, laid, pesant sur le développeur d'API, il existe une solution pour surcharger et définir les paramètres optionnels des fonctions C / C ++ pour nous les fous. L'utilisation des API surchargées sortantes devient très agréable et agréable. =)
S'il y a une autre simplification possible de cette approche, veuillez me le faire savoir à
https://github.com/jason-deng/C99FunctionOverload
Encore une fois un merci spécial à toutes les personnes brillantes qui m'ont inspiré et conduit à réaliser ce travail! =)
la source
Pour quiconque recherche péniblement une solution VA_NARGS qui fonctionne avec Visual C ++. La macro suivante a fonctionné pour moi parfaitement (également avec zéro paramètre!) Dans Visual C ++ Express 2010:
Si vous voulez une macro avec des paramètres facultatifs, vous pouvez faire:
Cela a fonctionné pour moi aussi en vc. Mais cela ne fonctionne pas pour zéro paramètre.
la source
unresolved external symbol _bool referenced in function _main
gcc
/g++
prend en charge les macros varargs mais je ne pense pas que ce soit standard, alors utilisez-le à vos risques et périls.la source
AVERTISSEMENT: Surtout inoffensif.
la source
:%s/MY_MACRO_/THINK_/g
:)i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664)
Ce n'est pas vraiment ce pour quoi le préprocesseur est conçu.
Cela dit, si vous voulez entrer dans le domaine de la programmation de macros sérieusement difficile avec un minimum de lisibilité, vous devriez jeter un coup d'œil à la bibliothèque de préprocesseurs Boost . Après tout, ce ne serait pas C ++ s'il n'y avait pas trois niveaux de programmation totalement compatibles avec Turing (préprocesseur, métaprogrammation de modèles et C ++ de niveau de base)!
la source
Vous savez au moment de l'appel combien d'arguments vous allez transmettre, donc il n'y a vraiment pas besoin de surcharge.
la source
Version plus concise du code de Derek Ledbetter:
la source
En tant que grand fan d'horribles monstres macro, je voulais développer la réponse de Jason Deng et la rendre réellement utilisable. (Pour le meilleur ou pour le pire.) L'original n'est pas très agréable à utiliser car vous devez modifier la grande soupe à l'alphabet à chaque fois que vous voulez faire une nouvelle macro et c'est encore pire si vous avez besoin d'un nombre d'arguments différent.
J'ai donc fait une version avec ces fonctionnalités:
Actuellement, je viens de faire un maximum de 16 arguments, mais si vous avez besoin de plus (vraiment maintenant? Vous devenez simplement idiot ...) vous pouvez modifier FUNC_CHOOSER et CHOOSE_FROM_ARG_COUNT, puis ajouter des virgules à NO_ARG_EXPANDER.
Veuillez consulter l'excellente réponse de Jason Deng pour plus de détails sur l'implémentation, mais je vais simplement mettre le code ici:
la source
Vous pouvez utiliser à
BOOST_PP_OVERLOAD
partir d'uneboost
bibliothèque.Exemple de la documentation officielle de boost :
la source
Selon ce dont vous avez besoin, vous pouvez le faire avec var args avec des macros. Maintenant, les paramètres optionnels ou la surcharge de macro, il n'y a rien de tel.
la source
Aucun des exemples ci-dessus (de Derek Ledbetter, David Sorkovsky et Joe D) pour compter les arguments avec des macros n'a fonctionné pour moi en utilisant Microsoft VCC 10. L'
__VA_ARGS__
argument est toujours considéré comme un argument unique (le token-izing avec##
ou pas), donc le changement d'argument dans lequel ces exemples reposent ne fonctionne pas.Donc, réponse courte, comme indiqué par beaucoup d'autres ci-dessus: non, vous ne pouvez pas surcharger les macros ou utiliser des arguments optionnels dessus.
la source