現在已經清楚地知道VC++ 10編譯器的bug是如何工作的,我可以根據this answer的後半部分自己想出一個這樣的宏。
#define EXPAND(x) x
#define FOR_EACH_1(what, x, ...) what(x)
#define FOR_EACH_2(what, x, ...)\
what(x);\
EXPAND(FOR_EACH_1(what, __VA_ARGS__))
#define FOR_EACH_3(what, x, ...)\
what(x);\
EXPAND(FOR_EACH_2(what, __VA_ARGS__))
#define FOR_EACH_4(what, x, ...)\
what(x);\
EXPAND(FOR_EACH_3(what, __VA_ARGS__))
#define FOR_EACH_5(what, x, ...)\
what(x);\
EXPAND(FOR_EACH_4(what, __VA_ARGS__))
#define FOR_EACH_6(what, x, ...)\
what(x);\
EXPAND(FOR_EACH_5(what, __VA_ARGS__))
#define FOR_EACH_7(what, x, ...)\
what(x);\
EXPAND(FOR_EACH_6(what, __VA_ARGS__))
#define FOR_EACH_8(what, x, ...)\
what(x);\
EXPAND(FOR_EACH_7(what, __VA_ARGS__))
#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N())
#define FOR_EACH_NARG_(...) EXPAND(FOR_EACH_ARG_N(__VA_ARGS__))
#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
#define FOR_EACH_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0
#define CONCATENATE(x,y) x##y
#define FOR_EACH_(N, what, ...) EXPAND(CONCATENATE(FOR_EACH_, N)(what, __VA_ARGS__))
#define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)
實例:
#define callMember(o, f) o.f();
#define callMember_o(f) callMember(o, f)
FOR_EACH(callMember_o, doSomething, doSomethingElse);
相同
o.doSomething(); o.doSomethingElse();
這個解決方案是在鏈接的回答相似,不同之處在於在FOR_EACH(what, x, ...)
當零長度可變參數的參數列表用一個元素調用會導致一個虛假逗號,使FOR_EACH_NARG計數2個參數而不是1個參數,並使用EXPAND
宏解決方法。
VC++ 10中的錯誤是,如果__VA_ARGS__
被傳遞給可變宏的定義內的宏,它會在替換到宏後計算,導致多個逗號分隔的參數被視爲一個。要解決此問題,必須延遲參數評估,直到__VA_ARGS__
被替換爲止,方法是將宏調用包裝爲EXPAND
,強制將宏調用評估爲字符串,用__VA_ARGS__
替代。只有在EXPAND
被替換爲被調用的宏之後,可變參數才被替換。
P.S.如果有人能提出一種方法來爲N
更大的值緊密生成FOR_EACH_N
宏,我將不勝感激。
提供的答案在哪裏?請鏈接到您提到的問題。 – liori
會這麼做,我很難再找到他們。同時,請在問題第一段末尾看到相關答案。 – Dylan