2011-02-07 98 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