J'ai deux macros FOO2
et FOO3
:
#define FOO2(x,y) ...
#define FOO3(x,y,z) ...
Je souhaite définir une nouvelle macro FOO
comme suit:
#define FOO(x,y) FOO2(x,y)
#define FOO(x,y,z) FOO3(x,y,z)
Mais cela ne fonctionne pas car les macros ne surchargent pas sur le nombre d'arguments.
Sans modifier FOO2
et FOO3
, existe-t-il un moyen de définir une macro FOO
(en utilisant __VA_ARGS__
ou autrement) pour obtenir le même effet de distribution FOO(x,y)
vers FOO2
et FOO(x,y,z)
vers FOO3
?
c
macros
c-preprocessor
Andrew Tomazos
la source
la source
Réponses:
Simple comme:
Donc, si vous avez ces macros:
Si vous en voulez un quatrième:
Naturellement, si vous définissez
FOO2
,FOO3
etFOO4
, la sortie sera remplacée par celles des macros définies.la source
EXPAND
lien mentionné dans @ Étienne, vous l'invoquez essentiellementGET_MACRO
comme tel#define FOO(...) EXPAND(GET_MACRO(__VA_ARGS__, FOO3, FOO2, FOO1)(__VA_ARGS__))
et il devrait s'étendre au bon nombre d'arguments dans msvc.ISO C++11 requires at least one argument for the "..." in a variadic macro
. Pour résoudre ce problème, ajoutez un argument inutilisé (ou même juste une virgule) après le dernier paramètre dans la définition de FOO (...):#define FOO(...) GET_MACRO(__VA_ARGS__, FOO3, FOO2, UNUSED)(__VA_ARGS__)
( Voir qu'il s'exécute sur Coliru ).Pour ajouter à la réponse de netcoder , vous POUVEZ en fait le faire avec une macro à 0 argument, à l'aide de l'
##__VA_ARGS__
extension GCC :la source
#define FOO0 _Pragma("error FOO0 not allowed")
?FOO0
ne fonctionne pas dans qt + mingw32, l'appelFOO0
invoquera leFOO1
-std=c99
ou-std=c11
. Vous devez utiliser-std=gnu99
ou à la-std=gnu11
place_0, ##__VA_ARGS__
par_0 __VA_OPT__(,) __VA_ARGS__
est la nouvelle façon de procéder.Voici une solution plus générale:
Définissez vos fonctions:
Vous pouvez maintenant utiliser
FOO
avec 2, 3 et 4 arguments:Limites
Idées
Utilisez-le pour les arguments par défaut:
Utilisez-le pour les fonctions avec un nombre infini d'arguments possible:
PS:
__NARG__
est copié de Laurent Deniau & Roland Illig ici: https://groups.google.com/group/comp.std.c/browse_thread/thread/77ee8c8f92e4a3fb/346fc464319b1ee5?pli=1la source
__NARG_I_
semble totalement inutile et superflue. Cela ajoute juste une étape supplémentaire et de la confusion. Je recommande de le supprimer entièrement et simplement définir la__NARG__
place que:#define __NARG__(...) __ARG_N(__VA_ARGS__,__RSEQ_N())
._VFUNC_
: supprimez-le simplement. Ensuite, définissez_VFUNC
comme:#define _VFUNC(name, n) name##n
au lieu de#define _VFUNC(name, n) _VFUNC_(name, n)
.J'étais en train de faire des recherches moi-même, et je suis tombé dessus ici . L'auteur a ajouté la prise en charge des arguments par défaut pour les fonctions C via des macros.
Je vais essayer de résumer brièvement l'article. Fondamentalement, vous devez définir une macro qui peut compter les arguments. Cette macro renverra 2, 1, 0 ou toute plage d'arguments qu'elle peut prendre en charge. Par exemple:
Avec cela, vous devez créer une autre macro qui prend un nombre variable d'arguments, compte les arguments et appelle la macro appropriée. J'ai pris votre exemple de macro et l'ai combiné avec l'exemple de l'article. J'ai la fonction d'appel FOO1 a () et la fonction d'appel FOO2 a avec l'argument b (évidemment, je suppose C ++ ici, mais vous pouvez changer la macro en n'importe quoi).
Donc si vous avez
Le préprocesseur étend cela à
Je lirais certainement l'article que j'ai lié. C'est très instructif et il mentionne que NARG2 ne fonctionnera pas sur des arguments vides. Il suit ceci ici .
la source
Voici une version plus compacte de la réponse ci-dessus . Avec l'exemple.
Courir:
Notez qu'avoir les deux
_OVR
et_OVR_EXPAND
peut sembler redondant, mais il est nécessaire que le préprocesseur développe la_COUNT_ARGS(__VA_ARGS__)
partie, qui est sinon traitée comme une chaîne.la source
Vous pouvez peut-être utiliser cette macro pour compter le nombre d'arguments .
la source
Voici un spin-off de la réponse d'Evgeni Sergeev. Celui-ci prend également en charge les surcharges d'argument nulles !
J'ai testé cela avec GCC et MinGW. Il devrait fonctionner avec les anciennes et les nouvelles versions de C ++. Notez que je ne le garantirais pas pour MSVC ... Mais avec quelques ajustements, je suis convaincu que cela pourrait aussi fonctionner avec cela.
Je l'ai également formaté pour être collé dans un fichier d'en-tête (que j'ai appelé macroutil.h). Si vous faites cela, vous pouvez simplement inclure cet en-tête tout ce dont vous avez besoin, et ne pas regarder la méchanceté impliquée dans l'implémentation.
la source
Cela semble fonctionner correctement sur GCC, Clang et MSVC. C'est une version nettoyée de certaines des réponses ici
la source
#define func0() foo
? La version actuelle ne gère malheureusement pas ce cas.