2011-02-07 95 views
5

是否有可能做这样的事情:宏观依赖宏观

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

这样,当我使用F,它扩展到取决于是否在宏DOUBLE定义?我不这么认为,但我很有希望。 GNU扩展很好。

编辑 为了回应一些答案,我真的用它来做一些代码生成,其中代码根据定义的位置稍有不同。由于包含某些文件的顺序以及需要定义相关宏的位置,因此要切换它需要一些分解。我可能必须这样做,但如果我不必从这个角落解脱我自己就会感到兴奋!

回答

8

如果我们能够约束问题,你可以做到这一点。具体地,如果可以保证DOUBLE要么

  • 不定义为宏,或
  • 被定义为扩展到空令牌序列(例如#define DOUBLE)一个宏,

然后你可以用一种间接的方式与令牌串联:

#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) 

用例:

预处理后3210
F(t) 
#define DOUBLE 
F(t) 

结果:

DOUBLE_NOT_DEFINED 
DOUBLE_IS_DEFINED 

如果DOUBLE(如果它被定义)被定义为扩展到单一已知令牌的宏这种方法也将工作,如果该标记可形成的部分标识符(例如,TRUE1)。为了解决这个问题,你只需要将F_IMPL_宏重命名为F_IMPL_{TOKEN}(例如,F_IMPL_TRUEF_IMPL_1)。

+0

这很完美。 – 2011-02-08 00:45:20

13

这有什么错

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

为什么不这样做的其他方式的嵌套?

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

号你可以做的最接近的事是把在一个头文件,每一个定义你所关心的变化时说#包含头文件。这有时称为“X”模式,因为X被用作改变定义的宏。

例如,该模式的一个常见的用法是自动生成枚举值的字符串名称:

// 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