2016-03-01 44 views
0

我已經爲Visual Studio和鐺定義這些宏,他們都編譯罰款如何使GCC將'arg,## __ VA_ARGS__'減少爲'arg'以將其用作單個宏參數?

#if defined(_MSC_VER) 
# define _declare_func(...) PP_CAT(PP_CAT(_declare_func_, PP_NARG(__VA_ARGS__)),(__VA_ARGS__)) 
# define declare_func(...) _declare_func PP_LEFT_PAREN notused,##__VA_ARGS__ PP_RIGHT_PAREN 
#else // clang version 
# define _declare_func(...) PP_CAT(_declare_func_, PP_NARG(__VA_ARGS__))(__VA_ARGS__) 
# define declare_func(...) _declare_func (notused,##__VA_ARGS__) 
#endif 

#define _declare_func_1(notused)    void my_function() 
#define _declare_func_2(notused, scope)  void scope::my_function() 

class MyClass 
{ 
    declare_func(); 
}; 

declare_func(MyClass) { } 

PP_CAT是一個典型的多級CONCAT宏觀

PP_NARG計數的宏參數

PP_LEFT_PAREN和PP_RIGHT_PAREN數量減少到'('和')'

有什麼辦法可以用GCC來實現這個嗎? (我嘗試了兩個宏版本和GCC 5.2,兩者都無法編譯,因爲逗號似乎在宏分辨率期間傳播並且僅在預處理結束時被移除,使得PP_NARG總是減少到'2'而不是'1')

謝謝!

回答

1

doc

其次,放置一個逗號和一個可變參數之間時,「##」令牌膏操作者具有特殊的含義。如果你寫

#define eprintf(format, ...) fprintf (stderr, format, ##__VA_ARGS__) 

和可變參數被冷落使用EPRINTF宏時,則逗號之前的「##」將被刪除。如果您通過空參數,則不會發生這種情況,如果前面的'##'之前的標記不是逗號,也不會發生這種情況。

eprintf ("success!\n") 
     ==> fprintf(stderr, "success!\n"); 

以上的說明是不明確的關於其中唯一的宏參數是一個可變參數的參數的情況下,因爲它是沒有意義的,試圖區分完全沒有參數是否是一個空的參數或缺少論據。 在這種情況下,C99標準清楚地表明逗號必須保持爲,但是現有的GCC擴展用於吞下逗號。因此CPP在符合特定C標準時保留逗號,否則將其刪除。

所以對於

#define declare_func(...) _declare_func (notused,##__VA_ARGS__) 

逗號留在C標準,你可以使用-std=gnu99-std=gnu++11下降逗號,有你的工作的宏。

Demo

要使用-std=c++11讓您的宏的作品,你有這麼給力至少有一個參數。

+0

你救了我的一天!萬分感謝 !做了這項工作..我確實使用-std = C++ 11而不是std = gnu ++ 11。 – Juicebox