J'ai des macros qui vont soit élargir dans un nombre (dans mon exemple, les cas 2 et 4), ou rien (dans mon exemple, les cas 1 et 3). Le néant n'est pas souhaitable pour moi, j'ai donc besoin d'autres macros qui détecteront et remplacent le néant.
J'ai pu créer une macro, Je veux l'améliorer et créer une nouvelle macro, old_check code>, qui détecterait le cas et remplacerait avec un 0. (cas 1) p>
new_check code>, qui détectera le cas et le remplacera par une valeur par défaut. valeur. (Cas 3) P>
#define NEW_CHECK_HELPER(...) , ## __VA_ARGS__
#define NEW_CHECK(default, ...) (default NEW_CHECK_HELPER(__VA_ARGS__))
4 Réponses :
Votre méthode existante fonctionnera si vous vous débarrassez de la virgule de fuite dans le cas triple: La raison est que GCC fait une distinction entre aucun argument em> et un argument vide em> pour alors il y a l'étrangeté que , ## __ va_args __ code> - seulement s'il y a aucun argument em> ne supprime-t-il la virgule (unique) vide le garde. p>
old_check () code> est traité comme aucun argument em> plutôt qu'un argument vide em>, ce qui n'a pas encore beaucoup de sens. p> p>
Si vous avez vraiment besoin de prendre en charge l'argument "vide" dans le cas 3, vous pouvez essayer le non-portable:
case 3: 7 case 4: 5
Merci; Mon problème a besoin de gérer la virgule suivante. Malheureusement, la non-portabilité de la solution est une question. Mon environnement ne prend pas en charge __ va_opt __ code>, que j'ai testé avec mon enfant à la fois mon enfant et avec Ce .
Assez juste; J'ai ajouté une deuxième réponse qui utilise le de GCC, ## __ va_args __ code> syntaxe.
Utilisation de impressions : p> de GCC, ## __va_args __ code> Extension pour la suppression des virgules (que vous utilisez déjà pour
OLD_CHECK code>):
Après un moment, j'ai proposé une solution de plusieurs étapes alternative tout aussi portable que old_check code>. Il réutilise
premier_one code> d'avant, et utilise également une macro nargs
nargs code> pour compter le nombre d'arguments dans
__ va_args __ code>.
/* NEW_CHECK(default, maybe_blank) */
#define NEW_CHECK(...) M_(__VA_ARGS__)
/* delay expansion of M once to perform Q */
#define M_(D, ...) F(D, Q(__VA_ARGS__))
/* Q(maybe_blank): if __VA_ARGS__ is non-blank, __VA_ARGS__. Otherwise, SPACE */
#define Q(...) FIRST_ONE(dummy, ##__VA_ARGS__, SPACE)
/* SPACE just expands into two arguments so that we can differentiate between was-blank (2 args) and non-blank (1 arg) */
#define SPACE 0, 0
/* F(default, one-or-two-arguments) */
#define F(...) F_(__VA_ARGS__)
#define F_(...) F__(__VA_ARGS__)
/* delay expansion of F twice, for performing Q and SPACE */
#define F__(D, ...) H(NARGS(__VA_ARGS__), D, __VA_ARGS__)
/* H(1 or 2, default, maybe_blank) */
#define H(...) H_(__VA_ARGS__)
/* delay expansion once, for performing NARGS */
#define H_(N, D, ...) DO##N(D, __VA_ARGS__)
/* based on NARGS, pick correct result */
#define DO1(D, ...) __VA_ARGS__
#define DO2(D, ...) D
Mettre la macro dans la question.