首頁 >後端開發 >C++ >為什麼 MSVC 和 GCC 之間的可變宏擴展不同?

為什麼 MSVC 和 GCC 之間的可變宏擴展不同?

Patricia Arquette
Patricia Arquette原創
2024-11-05 08:36:021163瀏覽

Why Does Variadic Macro Expansion Differ Between MSVC   and GCC?

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 :

    1. VA_NARGS(Property1, Property2, Property3, Property 🎜>
    2. SEMI_EXPANDED(4, 屬性1, 屬性2, 屬性3, 屬性4) -> MAC4(屬性1, 屬性2, 屬性3, 屬性4)
    3. EXPAND_THESE(MAC4(屬性1,屬性2, 屬性3, 屬性4)) -> MAC4(屬性1、屬性2、屬性3、屬性4)
  • GCC:

      GCC:
    1. GCC:


    2. 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中文網其他相關文章!

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