MSVC 中的可變參數巨集擴展
MSVC 中的可變參數巨集機制與GCC 中的行為不同,導致用多個參數。考慮以下巨集:
<code class="cpp">#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N #define VA_NARGS(...) VA_NARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1) #define FULLY_EXPANDED(count, ...) \ MAC ## count (__VA_ARGS__) #define SEMI_EXPANDED(count, ...) FULLY_EXPANDED(count, __VA_ARGS__) #define EXPAND_THESE(...) SEMI_EXPANDED(VA_NARGS(__VA_ARGS__), __VA_ARGS__) #define ACTUAL_MACRO(x) parent->GetProperty<x>(); #define MAC1(a) ACTUAL_MACRO(a) #define MAC2(a,b) MAC1(a) ACTUAL_MACRO(b) #define MAC3(a,b,c) MAC2(a,b) ACTUAL_MACRO(c) #define MAC4(a,b,c,d) MAC3(a,b,c) ACTUAL_MACRO(d) #define MAC5(a,b,c,d,e) MAC4(a,b,c,d) ACTUAL_MACRO(e)</code>
在GCC 中,此巨集將擴展為:
<code class="cpp">struct MyStructure { void Foo() { parent->GetProperty<Property1>(); parent->GetProperty<Property2>(); parent->GetProperty<Property3>(); parent->GetProperty<Property4>(); } Base * parent; }</code>
但是,在MSVC 中,它擴展為:
<code class="cpp">struct MyStructure { void Foo() { parent->GetProperty<Property1, Property2, Property3, Property4>(); } Base * parent; }</code>
說明
出現此問題的原因是MSVC 逐級應用巨集擴展,而GCC 一次完全擴展巨集。考慮巨集呼叫:
<code class="cpp">EXPAND_THESE(Property1, Property2, Property3, Property4)</code>
MSVC :
GCC:
GCC:
GCC:
<code class="cpp">#define FOO_CHOOSE_HELPER1(count) FOO##count #define FOO_CHOOSE_HELPER2(count) FOO_CHOOSE_HELPER1(count) #define FOO_CHOOSE_HELPER(count) FOO_CHOOSE_HELPER2(count) #define ERROR(...) GLUE(FOO_CHOOSE_HELPER(COUNT_ARGS_MAX5(__VA_ARGS__)), (__VA_ARGS__)) #define ASSERT1(expr) singleArgumentExpansion(expr) #define ASSERT2(expr, explain) twoArgumentExpansion(expr, explain) #define ASSERT(...) GLUE(FOO_CHOOSE_HELPER(COUNT_ARGS_MAX5(__VA_ARGS__)), (__VA_ARGS__))</code>VA_NARGS(屬性1、屬性2、屬性3,屬性4) -> 4
<code class="cpp">#define OVERLOAD_MACRO2(name, count) name##count #define OVERLOAD_MACRO1(name, count) OVERLOAD_MACRO2(name, count) #define OVERLOAD_MACRO(name, count) OVERLOAD_MACRO1(name, count) #define CALL_OVERLOAD(name, ...) GLUE(OVERLOAD_MACRO(name, COUNT_ARGS_MAX5(__VA_ARGS__)), (__VA_ARGS__)) #define ERROR1(title) printf("Error: %s\n", title); #define ERROR2(title, message) \ ERROR1(title); \ printf("Message: %s\n", message); #define ERROR(...) CALL_OVERLOAD(ERROR, __VA_ARGS__); #define ASSERT1(expr) singleArgumentExpansion(expr) #define ASSERT2(expr, explain) twoArgumentExpansion(expr, explain) #define ASSERT(...) CALL_OVERLOAD(ASSERT, __VA_ARGS__);</code>SEMI_EXPANDED(4, 屬性1, 屬性2, 屬性3, 屬性4) -> MAC4 (屬性1, 屬性2, 屬性3, 屬性4)EXPAND_THESE(MAC4(屬性1, 屬性2, 屬性3, 屬性4)) -> MAC4(屬性1, 屬性2, 屬性3, 屬性4) -->進一步展開MAC4宏 -->相當於多行ACTUAL_MACRO 調用解決方法 要實現與GCC 類似的行為,可以採用Jeff Walden 的方法,該方法涉及創建額外的宏助手並使用COUNT_ARGS_MAX5 宏來確定參數的數量:或者,「GLUE」巨集提供的抽象可用來簡化解決方法:
以上是為什麼 MSVC 和 GCC 之間的可變宏擴展不同?的詳細內容。更多資訊請關注PHP中文網其他相關文章!