Ce que j'aimerais faire (à des fins de journalisation) est quelque chose comme ceci:
Ce code a été écrit pour montrer mon problème, le code actuel est complexe et oui, j'ai de bonnes raisons d'utiliser des macros même sur C ++ =) p> P> P> Mais alors Fondamentalement ma question est la suivante: Comment éviter l'expansion macro d'un paramètre de fonction macro lorsque vous appelez une autre fonction macro? P> P> P > Il y a un astuce que j'utilise qui évite les expansions macro: p> (collé x et lib produit Il y a un moyen d'obtenir ce même comportement sans utiliser d'astuce? P> P> log_error_simple () code> écrit la limitation du paramètre lib libération (nom de macro entouré de "") p>
log_error code> écrit la limitation de la macro déjà expansée ("2"). Ceci est attendu, puisque Lib a obtenu son expansion avant d'agrandir et d'appeler
log_error_simple code>. Mais ce n'est pas ce dont j'ai besoin. P>
lib_other code> et cette valeur est utilisée pour appeler
Log_error_simple code>, ce n'est pas macro expansé avant cet appel) P>
4 Réponses :
Je ne pense pas que vous puissiez. Cependant, ce que vous pourriez faire, cependant, ajoutez une couche de macro pour elle à l'abeille à sa place:
@kts ooh, whaddya sait. Je pense à quelque chose et les boffins à Boost sont waaaaaay devant moi.
Ni Enveloppe ou _Identity fonctionne .. car (au moins en CPP), il appelle log_error_simple avec Wrap () comme paramètre, et non comme "ce qui est à l'intérieur du nom mais non étendu"
Erk. Dans ce cas, je pense que vous foist log_error (PTR, Lib, Wrap (STR)) sur vos utilisateurs ou écrivez log_error sans vous référer à log_error_simple.
Je fais: qui imprime: p> fonctionne avec msvc2005 mais pas avec gcc / g ++ strong>. p> Modifier: pour le faire fonctionner avec GCC / G ++, vous pouvez abuser des macros VARIADIC: P>
FOO
BAR
FOOBAR
Lorsque vous utilisez le préprocesseur de GCC (supprimer le #include code> qui n'existe pas), je reçois le bon programme sur stdout, mais un message d'erreur sur STDERR. T.C: 11: 1: Erreur: coller "," et "bar" ne donne pas de jeton de prétraitement valide
Eh bien, "ne fonctionne pas" est un peu fort. J'ai obtenu un programme compilable sur stdout lorsque j'ai couru gcc -e t.c code>.
Oui, le collage est un moyen de ne pas étendre "ce qui est à l'intérieur de la lib" en place et le laisser atteindre log_simple. Mon exemple précédent collé lib avec un paramètre vide, le vôtre collé lib avec la virgule gauche (ce qui n'est bien sûr pas totalement "juste"). Je me demande si je pouvais coller liber avec "un paramètre spécial et caché" pour obtenir les mêmes résultats que d'utiliser un paramètre supplémentaire dans la macro, libérez-vous de vider à cette fin.
Oui c'est un bon tour! Malheureusement, j'utilise déjà des macros variadiques sur log et log_simple. Je ne l'ai pas spécifié pour la simplicité, ma faute. C'est pourquoi je ne comptant pas sur VA_ARGS B> comme source de pâte rien de manière plus élégante.
J'ai essayé plus aujourd'hui sans beaucoup de chance, puis-nous décider que vous ne pouvez pas éviter l'expansion dans le cas général?
Gregory, afaik le seul moyen pour un nom de macro à l'intérieur d'un paramètre de fonction de macro pour survivre plus de 1 niveau d'appels de fonction macro imbriqués pour obtenir #param -> "Macro_name" dans le 2e appel ou supérieur est l'astuce que nous avons découverte (soit par colle Param avec __ va_args __ code> ou avec un autre vide) peut-être qu'il n'y a pas de solution à part de cette astuce .. Peut-être devrions-nous suggérer que les développeurs du RPC doivent mettre en place un "paramètre de macro de valeur vide" (appelons-le
__Empty __ code>) de pouvoir passer un paramètre de macro à d'autres fonctions macro, sans expansion en utilisant le truc. Je pense que ça va être utile s'ils le font
Obtenir de travailler avec GCC / SLIG, etc. Voir Stackoverflow.com/Questtions/11610111/...
Vous l'avez presque eu. Utilisez
#define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, ##lib, WHERE str)
Je pense que l'OP veut éviter la citation de l'argument d'où la question. Si "lib_other" était bien avec lui, je pense qu'il aurait demandé au premier endroit
Coller lib avec une virgule donne cette erreur: coller "," et "lib_other" ne donne pas de jeton de prétraitement valide. Existe-t-il un personnage "neutre" ou un paramètre vide masqué que je pourrais utiliser pour coller liber avec "quelque chose de vide" et sans erreurs?
Désolé. J'ai mal compris vos besoins. Boost_pp_empty est une macro qui ne se développe à rien. Vous pouvez également essayer / ** / (c'est un commentaire de style C vide dans la case le tuera)
Pourriez-vous peut-être fournir la sortie souhaitée de votre macro? Compte tenu de log_error (ceci, lib_other, "une erreur) quel est le code que vous voulez généré?
@kts, c'est plus sur le côté macro même, la façon dont il fonctionne et macro-élargit des choses, pas la génération de code C. Je veux juste stringifier lib_other pour obtenir "lib_other" .. Bien sûr, lib_other doit être transmis comme un paramètre et survivre 2 niveaux d'appels de fonction macro, quelque chose de pas trivial à atteindre.
@Conejoroy boost_pp_identity (lib_other) code> suffit? Il se développe à un jeton qui, quand appelé avec () renvoie l'argument initial.
@kts, non, à l'intérieur d'une fonction macro déjà appelée à partir de la source, lib_other code> obtient son expansion (du nom de macro à 2) avant qu'une deuxième fonction macro imbriquée soit appelée, c'est
boost_pp_identity ( 2) code> ... cette fonction macro recevra toujours 2 au lieu du nom de la macro
lib_other code>. c'est le problème "de la fonction macro de 2 niveau" Problème i Medoned, sur la 2e Fonction imbriquée Call
lib_other code> est toujours remplacé par 2, il n'y a pas de solution de contournement triviale pour éviter cela, je sais juste un tour (coller le Paramètre avec un autre vide, le résultat est
lib_other code> et est laissé tel quel).
Si vous n'avez pas besoin des alias libérés étendus (c'est-à-dire «1» et '2') dans vos macros CPP, vous pouvez également utiliser une énumération au lieu de valeurs définies. P>
Bien que j'aurais aimé trouver la solution à mon problème d'expansion macro, vous m'avez fait repenser l'un de ses éléments. J'ai changé mes constantes de macro enums, leur nom ne reçoit pas de macro expansé (puisqu'ils ne sont pas une macro) et maintenant le problème n'est pas résolu, mais c'est parti =)
Maintenant, je veux toujours le résoudre, mais aussi loin dans mon programme, grâce à votre suggestion, je n'ai pas besoin de.