Je veux écrire une macro qui crache du code en fonction de la valeur booléenne de son paramètre. Disons que DEF_CONST(true)
devrait être développé en const
et DEF_CONST(false)
devrait être développé en rien.
De toute évidence, ce qui suit ne fonctionne pas car nous ne pouvons pas utiliser un autre préprocesseur dans #defines:
#define DEF_CONST(b_const) \
#if (b_const) \
const \
#endif
Vous pouvez simuler des conditions en utilisant concaténation de jetons de macro comme suit:
#define DEF_CONST(b_const) DEF_CONST_##b_const
#define DEF_CONST_true const
#define DEF_CONST_false
Ensuite,
/* OK */
DEF_CONST(true) int x; /* expands to const int x */
DEF_CONST(false) int y; /* expands to int y */
/* NOT OK */
bool bSomeBool = true; // technically not C :)
DEF_CONST(bSomeBool) int z; /* error: preprocessor does not know the value
of bSomeBool */
En outre, en permettant de passer des paramètres de macro à DEF_CONST lui-même (comme indiqué correctement par GMan et d'autres):
#define DEF_CONST2(b_const) DEF_CONST_##b_const
#define DEF_CONST(b_const) DEF_CONST2(b_const)
#define DEF_CONST_true const
#define DEF_CONST_false
#define b true
#define c false
/* OK */
DEF_CONST(b) int x; /* expands to const int x */
DEF_CONST(c) int y; /* expands to int y */
DEF_CONST(true) int z; /* expands to const int z */
Vous pouvez également considérer le plus simple (bien que potentiellement moins flexible):
#if b_const
# define DEF_CONST const
#else /*b_const*/
# define DEF_CONST
#endif /*b_const*/
Le faire comme une macro paramétrisée est un peu étrange.
Pourquoi ne pas simplement faire quelque chose comme ça:
#ifdef USE_CONST
#define MYCONST const
#else
#define MYCONST
#endif
Ensuite, vous pouvez écrire du code comme ceci:
MYCONST int x = 1;
MYCONST char* foo = "bar";
et si vous compilez avec USE_CONST
défini (par exemple, généralement quelque chose -DUSE_CONST
dans les options du makefile ou du compilateur) alors il utilisera les consts, sinon il ne le fera pas.
Edit: En fait, je vois que Vlad a couvert cette option à la fin de sa réponse, alors +1 pour lui :)