2011-02-07 5 views
5

Est-il possible de faire quelque chose comme ceci:macro dépendante macro

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

de sorte que lorsque j'utilise F, ce qu'il étend à dépend de la DOUBLE macro est définie? Je ne le pense pas, mais j'ai de l'espoir. Les extensions de GNU sont bien.

Modifier En réponse à quelques-unes des réponses, je suis vraiment en utilisant cela pour faire une génération de code, où le code est légèrement différent selon l'endroit où il se définit. En raison de l'ordre dans lequel certains fichiers sont inclus et où les macros pertinentes doivent être définies, le fait de les changer nécessite un peu d'affacturage. Je vais devoir le faire, mais je serais ravi si je n'avais pas besoin de me repousser de ce coin!

Répondre

8

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

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

puis vous pouvez utiliser une approche indirecte avec concaténation symbolique:

#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 traitement préalable:

DOUBLE_NOT_DEFINED 
DOUBLE_IS_DEFINED 

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

+0

C'est parfait. –

+0

Beau travail. Je détesterais le maintenir cependant. – AShelly

13

Quel est le problème avec

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

Pourquoi ne pas faire l'imbrication dans l'autre sens?

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

Non, la chose la plus proche que vous pouvez faire est de le mettre dans un fichier d'en-tête et #inclure ce fichier d'en-tête chaque fois que les définitions que vous se soucient de changement. Ceci est parfois appelé le modèle "X", car X est utilisé comme une macro qui change la définition.

Par exemple, un usage courant de ce modèle est de générer automatiquement les noms de chaîne de 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