2010-09-08 19 views
2

我想創建將參數插入函數調用的宏。例如,我有下面聲明的功能Action()。動作需要輸入一個枚舉狀態號和一個格式化的字符串,該字符串具有可選的參數。如何通過#define函數將參數添加到格式化字符串函數調用

我想定義宏,以便代替調用Action(ActionState1, "someText %d", &arg)ActionState1的狀態參數,我可以叫State1("someText %d", &arg)來代替。這樣宏將堅持在ActionState1爲我的狀態參數。我正在考慮類似以下內容:

#define State1(formatedString, ...) Action(ActionState1, formatedString, ...) 
#define State2(formatedString, ...) Action(ActionState2, formatedString, ...) 
#define State3(formatedString, ...) Action(ActionState3, formatedString, ...) 

enum { 
    ActionState1, 
    ActionState2, 
    ActionState3 
} 

static void Action(State state, String formatedString, ...); 

有誰知道這是什麼格式嗎?

+0

只因爲你*可以*做到這一點,並不代表你*應該*。考慮將'enum'作爲第一個參數傳遞給'Action',或者將'Action'傳入多個函數。 – Seth 2010-09-08 00:38:04

+0

枚舉是Action的第一個參數,我剛剛沒有在我的例子中展示過(我現在已經更新了它)。 – 2010-09-08 01:14:10

回答

2

我相信__VA_ARGS__是你在找什麼:

#define State1(formattedString, ...) Action(1, (formattedString), __VA_ARGS__) 
. 
. 
. 

這是C99的功能,並Wikipedia claims,他們沒有任何正式的C++標準的一部分(我注意到這一點,因爲您使用C++標籤),但是一個相當流行的擴展。在this question有一些很好的討論。

+0

OP想要:_宏將堅持在狀態= 1位me_。我看不到'__VA_ARGS__'可以提供什麼幫助。恕我直言,橢圓不能被視爲代表一個可變的函數'行動'。但我可能是錯的。 – dirkgently 2010-09-08 00:39:24

+0

謝謝,這正是我想要的 – 2010-09-08 01:03:45

+0

我認爲'Action'需要是可變的,因爲OP的問題在示例中有一個格式字符串。 – 2010-09-08 01:05:04

2

否使用預處理器無法完成此操作。預處理程序允許您將實體串起來,但不能以相反的方式進行。對於你想要的,你需要將State1分成State1兩個部分(後者更重要)並繼續進行呼叫。

但是,更重要的問題是您爲什麼要這麼做?您幾乎不用通過這種轉換來保存任何輸入或獲得可讀性。

你可以利用附近的模板,雖然得到的東西:

template <size_t N> 
T State(string fmt, ...) { return Action(N, fmt, ...); } // assume T Action(size_t, ...); 

,並使用上述爲:

State<1>(fmtStr, ...); 
State<2>(fmtStr2, ...); 

但同樣,這裏有國際海事組織的幾乎沒有任何語法增益。

+0

我在我的例子中所遺漏的是,1,2,3由變得非常長的枚舉變量表示,有點像ClassA :: EnumA :: State1,在這種情況下使用像State (string fmt,...)與State1類型(字符串fmt,...)會有點麻煩,但是如果你有更好的建議,我全部耳朵:)謝謝你的輸入 – 2010-09-08 01:02:41

0

爲什麼你想創造這樣的事情?在C++中優先使用流操作符或使用可變參數的類似操作,因爲它可以提高類型安全性。

我不相信在C++預處理器宏中有什麼辦法可以做到你想要的。如果你有一個va_list版本的動作,你可能會得到類似以下的東西,但我似乎記得在...之前的參數必須是POD--不幸的是,快速搜索無法證實或否認這一點。

#include <cstdarg> 
inline void State1(String formatedString, ...) 
{ 
    va_list args; 
    va_start(args, formatedString); 
    Action(1, formatedString, args); 
    va_end(args); 
} 
+0

我已經有了Action中的va_list內容。我只需要傳遞它的狀態參數。你知道一個更好的方法來完成這個任務,而不需要爲每個國家的實例定義一個新的功能嗎?我這樣做是因爲我有7種不同的狀態 – 2010-09-08 01:18:33