首頁  >  文章  >  後端開發  >  為什麼 MSVC 可變參數巨集擴充與 GCC 不同,我們如何克服這個差異?

為什麼 MSVC 可變參數巨集擴充與 GCC 不同,我們如何克服這個差異?

Barbara Streisand
Barbara Streisand原創
2024-11-06 09:10:02795瀏覽

Why does MSVC   variadic macro expansion differ from GCC, and how can we overcome this discrepancy?

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>

MSVC 擴充行為

但是,在Microsoft 的C 編譯器(MSVC ) 中,宏擴展的行為有所不同。 MSVC 不是單獨擴展每個參數,而是將所有參數連接成一個表達式。

struct MyStructure<br>{<br> void Foo()<br> {<pre class="brush:php;toolbar:false">EXPAND_THESE(Property1, Property2, Property3, Property4)

}

基礎* 父級;
}

基數};

GCC 擴充:



{ void Foo()parent->GetProperty<Property1>(); 
parent->GetProperty<Property2>(); 
parent->GetProperty<Property3>(); 
parent->GetProperty<Property4>();
{

void Foo()



}

基礎* 父級;}


MSVC 擴充:

MSVC 擴充:parent->GetProperty();
struct MyStructure<p>{</p> void Foo()<p> {<br><br></p>}<p><strong>Base *parent;</strong>}</p><p>Base *parent;</p>}<pre class="brush:php;toolbar:false"><code class="cpp">#define ERRORn(...) ERROR_CHOOSE_HELPERn(COUNT_ARGS_MAX5(__VA_ARGS__), __VA_ARGS__)
#define ERROR_CHOOSE_HELPER1(count) ERROR1
#define ERROR_CHOOSE_HELPER2(count) ERROR2
#define ERROR_CHOOSE_HELPER(count) ERROR_CHOOSE_HELPER##count</code>
}

解:
<code class="cpp">#define GLUE(x, y) x y

#define RETURN_ARG_COUNT(_1_, _2_, _3_, _4_, _5_, count, ...) count
#define EXPAND_ARGS(args) RETURN_ARG_COUNT args
#define COUNT_ARGS_MAX5(...) EXPAND_ARGS((__VA_ARGS__, 5, 4, 3, 2, 1, 0))

#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__))</code>

Jeff Walden 提出了一個解決方法,使用以下模式:
<code class="cpp">#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>

此方法需要為每個所需的可變參數巨集計數(例如ERROR1、ERROR2 等)定義一個CHOOSE_HELPER 巨集。但是,必須在可變參數巨集定義的範圍內宣告每個 CHOOSE_HELPER 巨集。 更簡潔和可移植的解決方案是利用以下技術:使用此設置,巨集可以定義為:透過使用OVERLOAD_MACRO 層次結構,可以避免定義CHOOSE_HELPER 巨集。

以上是為什麼 MSVC 可變參數巨集擴充與 GCC 不同,我們如何克服這個差異?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn