macro dépendante de la macro

Est-il possible de faire quelque chose comme ça:

#define F(x) \ #ifdef DOUBLE \ 2*x \ #else \ x \ #endif 

de sorte que, lorsque j’utilise F , l’agrandissement dépend de la définition de la macro DOUBLE ? Je ne pense pas, mais j’ai de l’espoir. Les extensions de GNU sont bien.

Edit En réponse à certaines des réponses, je l’utilise vraiment pour faire de la génération de code, où le code est légèrement différent en fonction du lieu où il est défini. En raison de l’ordre dans lequel certains fichiers sont inclus et où les macros pertinentes doivent être définies, le basculement de cette manière nécessite un peu de factorisation. Je vais peut-être devoir le faire, mais je serais ravi si je ne devais pas me peindre de ce coin!

Si nous pouvons limiter le problème, vous pouvez le faire. Plus précisément, si vous pouvez garantir que DOUBLE est soit

  • non défini comme une macro, ou
  • est défini comme une macro qui se développe en une séquence de jetons vide (par exemple #define DOUBLE ),

alors vous pouvez utiliser une approche indirecte avec concaténation de jetons:

 #define F_IMPL_(x) DOUBLE_IS_DEFINED #define F_IMPL_DOUBLE(x) DOUBLE_NOT_DEFINED #define F_1(x, m) F_2(x, m) #define F_2(x, m) F_IMPL_ ## m ( x ) #define F(x) F_1(x, DOUBLE) 

Exemple d’utilisation:

 F(t) #define DOUBLE F(t) 

Résultat après prétraitement:

 DOUBLE_NOT_DEFINED DOUBLE_IS_DEFINED 

Cette approche fonctionnera également si DOUBLE (s’il est défini) est défini comme une macro qui se développe en un seul jeton connu, si ce jeton peut faire partie d’un identifiant (par exemple, TRUE ou 1 ). Pour gérer cela, il vous suffit de renommer la macro F_IMPL_{TOKEN} en F_IMPL_{TOKEN} (par exemple, F_IMPL_TRUE ou F_IMPL_1 ).

Quel est le problème avec

 #ifdef DOUBLE #define F(x) (2 * (x)) #else #define F(x) (x) #endif 

Pourquoi ne pas faire la nidification dans l’autre sens?

 #ifdef DOUBLE #define F(x) (2*(x)) #else #define F(x) (x) #endif 

Non. La chose la plus proche que vous puissiez faire est de placer cela dans un fichier d’en-tête et #include ce fichier d’en-tête chaque fois que les définitions qui vous intéressent changent. Ceci est parfois appelé le motif “X”, parce que X est utilisé comme une macro qui modifie la définition.

Par exemple, une utilisation courante de ce modèle est de générer automatiquement les noms de chaîne des valeurs enum:

 // File myenum_values.h // NOTE: _no_ header guards so we can include this file multiple times X(Apple) X(Orange) X(banana) // File myenum.h enum Fruit { #define X(x) x, #include "myenum_values.h" } const char *FruitNames[] = { #undef X #define X(x) #x, #include "myenum_values.h" }; // We now have an array of fruit names without having to define the enum twice