Imaginons que, pour une raison quelconque vous avez besoin d'écrire une macro: MACRO(X,Y)
. (Imaginons qu'il y a une bonne raison pour laquelle vous ne pouvez pas utiliser une fonction en ligne.) Vous voulez que cette macro pour émuler un appel à une fonction sans valeur de retour.
Exemple 1: Cela devrait fonctionner comme prévu.
if (x > y)
MACRO(x, y);
do_something();
Exemple 2: Cela ne devrait pas entraîner une erreur de compilation.
if (x > y)
MACRO(x, y);
else
MACRO(y - x, x - y);
Exemple 3: Ce ne devrait pas compiler.
do_something();
MACRO(x, y)
do_something();
Le naïf façon d'écrire la macro est comme ceci:
#define MACRO(X,Y) \
cout << "1st arg is:" << (X) << endl; \
cout << "2nd arg is:" << (Y) << endl; \
cout << "Sum is:" << ((X)+(Y)) << endl;
C'est une très mauvaise solution qui ne satisfait pas toutes les trois exemples, et je ne devrais pas besoin d'expliquer pourquoi.
Ignorer ce que la macro en fait, ce n'est pas le point.
Maintenant, la façon dont j'ai le plus souvent voir des macros écrites est de les enfermer dans des accolades, comme ceci:
#define MACRO(X,Y) \
{ \
cout << "1st arg is:" << (X) << endl; \
cout << "2nd arg is:" << (Y) << endl; \
cout << "Sum is:" << ((X)+(Y)) << endl; \
}
Cela résout l'exemple 1, parce que la macro est dans un bloc d'instructions. Mais l'exemple 2 est cassé parce que nous avons mis un point-virgule après l'appel à la macro. Cela rend le compilateur pense que le point-virgule est une déclaration faite par lui-même, ce qui signifie que le else ne correspond à aucune instruction si! Et enfin, l'exemple 3 compile OK, même si il n'y a pas de point-virgule, car un bloc de code n'a pas besoin d'un point-virgule.
Est-il possible d'écrire une macro pour qu'il passe toutes les trois exemples?
Note: je présente ma propre réponse dans le cadre de la accepté de partager une astuce, mais si quelqu'un a une meilleure solution, n'hésitez pas à poster ici, il peut obtenir plus de voix que ma méthode. :)