Rumah > pembangunan bahagian belakang > C++ > Mengapa Pengembangan Makro Variadic Berbeza Antara MSVC dan GCC?

Mengapa Pengembangan Makro Variadic Berbeza Antara MSVC dan GCC?

Patricia Arquette
Lepaskan: 2024-11-05 08:36:02
asal
1159 orang telah melayarinya

Why Does Variadic Macro Expansion Differ Between MSVC   and GCC?

Peluasan Makro Variadik dalam MSVC

Mekanisme makro variadik dalam MSVC berkelakuan berbeza daripada yang ada dalam GCC, yang membawa kepada kesukaran untuk mengembangkan makro dengan berbilang hujah. Pertimbangkan makro berikut:

<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>
Salin selepas log masuk

Dalam GCC, makro ini akan berkembang kepada:

<code class="cpp">struct MyStructure
{
  void Foo()
  {
    parent->GetProperty<Property1>(); 
    parent->GetProperty<Property2>(); 
    parent->GetProperty<Property3>(); 
    parent->GetProperty<Property4>();
  }

  Base * parent;
}</code>
Salin selepas log masuk

Walau bagaimanapun, dalam MSVC , ia berkembang kepada:

<code class="cpp">struct MyStructure
{
  void Foo()
  {
    parent->GetProperty<Property1, Property2, Property3, Property4>();
  }

  Base * parent;
}</code>
Salin selepas log masuk

Penjelasan

Isu timbul kerana MSVC menggunakan pengembangan makro peringkat demi peringkat, manakala GCC mengembangkan makro sepenuhnya dalam satu laluan. Pertimbangkan seruan makro:

<code class="cpp">EXPAND_THESE(Property1, Property2, Property3, Property4)</code>
Salin selepas log masuk
  • MSVC :

    1. VA_NARGS(Property1, Property2, Property3, Property4) -> 4
    2. SEPARUH_DILUASKAN(4, Harta1, Harta2, Hartanah3, Hartanah4) -> MAC4(Hartanah1, Harta2, Hartanah3, Hartanah4)
    3. KEMBANGKAN_INI(MAC4(Hartanah1, Hartanah2, Hartanah3, Hartanah4)) -> MAC4(Hartanah1, Harta2, Hartanah3, Hartanah4)
  • GCC:

    1. VA_NARGS(Hartanah1, Hartanah3, Hartanah3 Harta4) -> 4
    2. SEPARUH_DILUASKAN(4, Harta1, Harta2, Hartanah3, Hartanah4) -> MAC4(Hartanah1, Harta2, Hartanah3, Hartanah4)
    3. KEMBANGKAN_INI(MAC4(Hartanah1, Hartanah2, Hartanah3, Hartanah4)) -> MAC4(Hartanah1, Harta2, Hartanah3, Harta4)
      --> Selanjutnya membuka makro MAC4
      --> Bersamaan dengan berbilang talian panggilan ACTUAL_MACRO

Penyelesaian

Untuk mencapai tingkah laku yang serupa dengan GCC, seseorang boleh menggunakan pendekatan Jeff Walden, yang melibatkan mencipta pembantu makro tambahan dan menggunakan makro COUNT_ARGS_MAX5 untuk menentukan bilangan argumen:

<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>
Salin selepas log masuk

Sebagai alternatif, abstraksi yang disediakan oleh makro "GLUE" boleh digunakan untuk memudahkan penyelesaian:

<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>
Salin selepas log masuk

Atas ialah kandungan terperinci Mengapa Pengembangan Makro Variadic Berbeza Antara MSVC dan GCC?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan