Comment écrire des macros c / c ++ #define sûres et conviviales

J’ai réfléchi à la façon dont les macros peuvent être écrites pour être sûres, lisibles et intuitives. Leur utilisation correcte doit être comprise par leur apparence et, si elle est utilisée de manière incorrecte, le compilateur doit vous l’indiquer, sans vous laisser introduire un bogue obscur.

Lors de l’écriture de macros de plusieurs lignes, je me trouve généralement à les construire comme ceci pour remplir les critères souhaités:

#define macro(x) do{ \ ... some code line ; \ ... some code line ; \ }while(0) 

De cette façon, vous pouvez tous les deux …

 if (a) { macro(a); } 

et…

 if (a) macro(a); else { ... } 

Une fonctionnalité intéressante de ceci est que si vous les utilisez mal, vous obtiendrez une erreur du compilateur. Cela ne comstackra pas par exemple:

 if (a) macro(a) else b(); 

Cependant, j’ai vu des développeurs SW lire ce type de construction de macro et s’y laisser perplexe. Pouvez-vous penser à d’autres manières d’écrire des macros qui ne décevront pas l’utilisateur d’une autre manière qu’elles ne font rien d’autre que prévu et qui sont tout à fait compréhensibles lors de la navigation dans un nouveau morceau de code?

De plus, pouvez-vous trouver des problèmes avec la méthode do {} while (0)? Par exemple, vous pourriez vous attendre à ce que la macro se comporte d’une certaine manière et ce n’est pas le cas.

La raison pour laquelle je ne suis pas complètement convaincue que la méthode do {} while (0) est une bonne pratique est que les macros elles-mêmes ont un aspect un peu bizarre et en expliquent à quiconque (au moins certains) qui n’a pas vu la construction auparavant.

Modifier:

Voici un exemple de l’un des liens dans les commentaires (merci!) Que j’aime bien. C’est assez lisible je pense:

 #define MYMACRO(a,b) \ if (xyzzy) asdf(); \ else (void)0 

Est-il possible de le casser?

Une approche courante lorsque vous souhaitez que votre macro ne fasse rien et que vous modifiez ce comportement avec le préprocesseur consiste à utiliser l’opération void(0) .

 #if SOMETHINGS #define macro(x) do{ \ ... some code line ; \ ... some code line ; \ }while(0) #else #define macro(x) ((void)(0)) #endif 

De cette façon, vous ne couperez pas la compilation lorsque vous annulerez des opérations de macro