2016-07-05 54 views
1

我正在嘗試創建一個將迭代所定義的術語列表的宏,並且每個宏都可能調用另一個宏,可能還會有其他參數列表。以下是我有:可變參數宏中的無效參數計數

#define ITERATE_OVER_TERMS(MACRO, ...) \ 
MACRO(Term1, __VA_ARGS__) \ 
MACRO(Term2, __VA_ARGS__) \ 
MACRO(Term3, __VA_ARGS__) \ 
... and so on 

然而,當我試圖與Visual Studio 2015使用它,我得到一個錯誤

warning C4003: not enough actual parameters for macro 'BODY' 

其中BODY是因爲通過宏的名稱MACRO的說法。雖然在技術上是一個警告,但它表明擴展方面出了問題。

在試圖縮小錯誤,我我的例子歸納爲以下:

#include <iostream> 

#define ITERATE(MACRO, ...) \ 
MACRO(1, __VA_ARGS__) MACRO(2, __VA_ARGS__) 

#define BODY(IterationArg, Arg1, Arg2) \ 
std::cout << IterationArg << Arg1 << Arg2 << std::endl; 

int main() { 
    ITERATE(BODY, 8, 9) 
    return 0; 
} 

它給我的錯誤,如上所示,雖然我預期它成功地編譯和產生輸出

189 
289 

它似乎用g ++編譯,但不是Visual Studio。 我錯過了什麼?有沒有一些解決這個問題的方法?

+0

Visual Studio 2015仍然部分支持C99預處理器。來源:https://msdn.microsoft.com/en-us/library/hh567368.aspx – KABoissonneault

+0

@KABoissonneault他們似乎很長時間支持可變宏(https://msdn.microsoft.com/en-us/library /ms177415.aspx)已經有VS2005的版本。 – CygnusX1

+0

他們支持可變宏,但說實話我從來沒有見過一個宏作爲宏觀參數傳遞。 Visual Studio可能期望你在'main'主體內部評估'BODY'。 – KABoissonneault

回答

2

問題是Visual Studio在傳入後續宏之後擴展爲__VA_ARGS__,而不是之前。這已經引起了過去的問題爲好,例如這裏 - Why does this variadic argument count macro fail with VC++?

在你的情況,考慮在代碼的簡單變化:

#include <iostream> 

#define ITERATE(MACRO, ...) \ 
MACRO(1, __VA_ARGS__) MACRO(2, __VA_ARGS__) 

#define BODY(IterationArg, Arg1, Arg2) \ 
std::cout << #Arg1 << std::endl; 

int main() { 
    ITERATE(BODY, 8, 9) 
    return 0; 
} 

的爭論#Arg1被字符串化,向我們展示它的內容在輸出中:

8, 9 
8, 9 

不是我們所期望的,是吧?

一種解決方案是相同的鏈接的問題:強制擴張通過一個虛設EXPAND宏:

#define EXPAND(x) x 

#define ITERATE(MACRO, ...) \ 
EXPAND(MACRO(1, __VA_ARGS__)) EXPAND(MACRO(2, __VA_ARGS__)) 

這給你都在VS和gcc所期望的結果。