10
votes

CPP: éviter la macro expansion d'un paramètre de fonction macro

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 ++ =) xxx

log_error_simple () écrit la limitation du paramètre lib libération (nom de macro entouré de "")

Mais alors log_error é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 . Mais ce n'est pas ce dont j'ai besoin.

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? Il y a un astuce que j'utilise qui évite les expansions macro: xxx

(collé x et lib produit lib_other et cette valeur est utilisée pour appeler Log_error_simple , ce n'est pas macro expansé avant cet appel)

Il y a un moyen d'obtenir ce même comportement sans utiliser d'astuce?


0 commentaires

4 Réponses :


0
votes

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: xxx


3 commentaires

@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.



9
votes

Je fais: xxx pré>

qui imprime: p> xxx pré>

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


7 commentaires

Lorsque vous utilisez le préprocesseur de GCC (supprimer le #include 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 .


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 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 __ 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 __ ) 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/...



0
votes

Vous l'avez presque eu. Utilisez

#define LOG_ERROR(ptr, lib, str) LOG_ERROR_SIMPLE(ptr, ##lib, WHERE str)


7 commentaires

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) 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 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) ... cette fonction macro recevra toujours 2 au lieu du nom de la macro lib_other . 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 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 et est laissé tel quel).



4
votes

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.


2 commentaires

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.