2013-01-02 190 views
4

是否有可能擁有2個具有相同名稱但參數不同的宏?像這樣:具有不同參數的相同名稱的宏

#define FI(value) do {l<<value; Doit(l); } while(0) 
#define FI(value, level) do {l<<value ; Doit(l,level); } while(0) 
+8

是的,它被稱爲「內聯函數」。 – Puppy

+0

@DeMgG有些人不喜歡聽到它,但有些情況下我們需要宏。像循環的語法糖一樣。參見[BOOST_FOREACH](http://www.boost.org/doc/libs/1_52_0/doc/html/foreach.html)。當然,你的論點對這個例子來說非常有用。 – leemes

+0

@leemes C++ 11的基於範圍的for-loop取代'BOOST_FOREACH' :) – fredoverflow

回答

5

這是不可能的。
符號名稱不能重新定義。與函數不同,宏不能重載。想象一下,邏輯宏是純粹的文本替換,那麼如何替換同一個實體的兩個不同的東西呢?

的替代性和更好的解決方案:
可以達到同樣的結果寫inline function。它爲您提供類型的額外優勢,可以檢查並避免宏的渾濁副作用。

+0

一個定義規則與預處理器宏無關。而且,如果您之前使用過#undef,則可以重新定義宏。 –

+0

@TadeuszKopec:你是對的。在預處理時對宏進行評估,並且實現ODR的編譯器從不會看到任何宏。 –

0

這是你真的應該用內聯函數的情況。知道任何關於您所使用的類型,一個可能的實現可能是這樣的:

template<typename T> 
inline void fi(T & l, const T & value) { 
    l << value; 
    Doit(l); 
} 

template<typename T> 
inline void fi(T & l, const T & value, const T & level) { 
    l << value; 
    Doit(l, level); 
} 

如果你遇到,你必須堅持宏的情況下,你必須努力,解決此限制,他們不能超載,至少不是每個標準。爲了「重載」它們,我們只需在宏名稱中寫入參數的數量,這是一種常見的方式(實際上,即使OpenGL庫使用此方法來「重載」C函數)。

#define FI1(value) do {l<<value; Doit(l); } while(0) 
#define FI2(value, level) do {l<<value ; Doit(l,level); } while(0) 
1

這會奏效。

#define FI(value, ...) FI_(value, ##__VA_ARGS__, 2, 1) 
#define FI_(value, level, n, ...) FI##n(value, level) 
#define FI1(value, ...) do {l << value; Doit(l);} while (0) 
#define FI2(value, level) do {l << value; Doit(l, level);} while (0) 
相關問題