2010-02-19 54 views
4

有沒有辦法通過C++宏和模板

std::map<std::string, float> 

作爲參數傳遞給宏?

(問題是, 「」 用於由宏分裂

std::map<std::string 

float> 

作爲獨立參數。我想避免這種情況。

+0

我認爲他們聽說你第一次...... – 2010-02-19 08:38:23

+0

難道這就是爲C?還是C++? – AnT 2010-02-19 08:39:43

+3

只是好奇,我們可以看到有問題的宏嗎?可能有更好的方法來完成你使用它的任何任務。 – 2010-02-19 08:43:16

回答

2

一個不起眼的解決方法是「隱藏」另一個宏內的逗號

#define ARGUMENT std::map<std::string, float> 
YOUR_MACRO(ARGUMENT) 
#undef ARGUMENT 

但是,如果YOUR_MACRO本身需要將其另一個級別傳播到另一個宏,它將遇到同樣的問題。

+0

'typedef'克服了嵌套宏問題,但更具永久性。 – 2010-02-19 08:42:42

+0

我第二種'typedef'方法。每當有一個替代品不涉及一個宏並提供相同的易用性......你最好沒有一個宏。 – 2010-02-19 09:32:06

+0

哦,真是太酷了。如果可以的話,我會給你+10。謝謝! – 2013-02-08 07:40:37

6

不,沒有辦法做到這一點,缺少使用typedef。例如,BOOST_FOREACH遭受同樣的問題。

+0

+1使用typedef – James 2010-02-19 09:32:21

+0

有幾種方法,如果你需要進行一些預處理編程。儘管這可能會給用戶帶來一些負擔,這取決於你所追求的內容,並且需要對宏進行量身定製來處理它......查看我的答案。 – 2010-02-19 09:33:42

6

嘗試使用模板而不是宏。

斯科特邁爾斯:C++有效 項目2:不想consts,枚舉和內聯到#define語句

+1

'項目2'在這裏不適用:它沒有提到模板,只是常量......雖然我同意一般的觀點,但如果它總是可能的話......那將會很棒。 – 2010-02-19 09:14:54

+1

它是第2項的內聯。我在這裏提到模板,因爲宏不關心類型,這就是爲什麼你通常不能用普通函數替換它們。但是使用模板可以讓你做到這一點。我認爲邁爾使用最小/最大宏對模板進行演示。 – Totonga 2010-02-19 09:55:24

0

我有類似的東西在幾個月前,如果你使用宏的,並有包含參數的逗號(「」 ),你需要包裹於額外parenthasis即:

#define DEF(ret,conv,name,args) typedef ret (conv * name)(args) 

//usage 
DEF(void,__cdecl,Foo,(int a1, string a2)); 

這種方法可能與某些東西衝突/在某些情況下無效的,這樣的例子(它導致它成爲一個無效的C樣式轉換):

#define MY_VAR(type,name) type name 

//usage 
MY_VAR((std::map<std::string, float>),Map); 

雖然有一種解決此問題的方法,但它需要您的編譯器支持可變宏(GCC | MSVC):

#define _W(...) __VA_ARGS__ 
#define VAR(x,y) x y 

VAR(_W(std::map<std::string, float>),Map); 
+0

不要在宏定義中加上'args',它帶括號。 – 2010-02-19 09:30:53

+0

如果有人使用singluar參數,使用宏時可以省略父外部,這就是爲什麼args是parenthasized,剩下的時間什麼都不做,超過的paranthasis被刪除/忽略 – Necrolis 2010-02-19 12:30:58

+1

括號似乎不是忽略。第一個示例展開爲'(std :: map )Map;',它根本不編譯(在未聲明的標識符Map上是C風格的轉換)。 – UncleBens 2010-02-19 17:20:23

5

是的,有一種方法,它是間接的。

正如你所說,一個宏在其解釋中相當愚蠢。但它仍然認可括號。

實施例:BOOST_MPL_ASSERT((boost::is_same<int,int>))

它通過使用括號的另一電平,由此形成Tuple(從宏觀角度)。

如果您使用Boost.Preprocessor庫,您可以輕鬆地「解開」Tuple以免其內容受到損害。不幸的是,你應該知道前期一個元組的大小,所以你需要一個額外的參數

#define MY_MACRO(Size, TemplatedType, Name)\ 
    BOOST_PP_TUPLE_REM(Size)(TemplatedType) Name 

而且在行動:

MY_MACRO(2, (std::map<int,std::string>), idToName); 
    // expands to 'std::map<int,std::string> idToName' 
idToName[1] = "Smith"; 

所以,是的,它是可能的,但宏必須是明確定製來處理它。

+0

我還應該補充一點,它可能很麻煩,因爲用戶需要計算',':/ – 2010-02-19 09:36:29

0

是的,只要您能安排它,std::map<std::string, float>就是您的最終參數或唯一參數。只需使用__VA_ARGS__,例如:

#define MAKE_A_NEW_ONE_OF_THESE(a, ...) __VA_ARGS__ *a = new __VA_ARGS__ 

MAKE_A_NEW_ONE_OF_THESE(pMyMap, std::map<std::string, float>);