Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Mengapakah pengembangan makro variadik MSVC berbeza daripada GCC, dan bagaimanakah kita boleh mengatasi percanggahan ini?

Mengapakah pengembangan makro variadik MSVC berbeza daripada GCC, dan bagaimanakah kita boleh mengatasi percanggahan ini?

Barbara Streisand
Barbara Streisandasal
2024-11-06 09:10:02795semak imbas

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

Peluasan Makro Variadik MSVC

Makro variadik menawarkan keupayaan pengembangan serba boleh, membolehkan anda mengendalikan berbilang argumen dalam makro. Dalam GCC, makro seperti berikut berfungsi seperti yang dijangkakan:

<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>

Gelagat Pengembangan MSVC

Walau bagaimanapun, dalam Microsoft's C Compiler (MSVC ), pengembangan makro berkelakuan berbeza . Daripada mengembangkan setiap hujah secara berasingan, MSVC menggabungkan semua hujah menjadi satu ungkapan.

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

}

Asas * ibu bapa;
};

Peluasan GCC:

struct MyStructure
{
batal Foo()
{

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

}

Asas * ibu bapa;
}

MSVC Peluasan:

struktur MyStructure
{
void Foo()
{

parent->GetProperty<Property1, Property2, Property3, Property4>();

}

Asas * ibu bapa;
}

Penyelesaian:

Jeff Walden mencadangkan penyelesaian menggunakan corak berikut:

<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>

Pendekatan ini memerlukan penentuan makro CHOOSE_HELPER untuk setiap kiraan makro variadik yang dikehendaki (cth., ERROR1, ERROR2, dll.). Walau bagaimanapun, adalah penting untuk mengisytiharkan setiap makro CHOOSE_HELPER dalam skop definisi makro variadic.

Penyelesaian yang lebih ringkas dan mudah alih adalah dengan memanfaatkan teknik berikut:

<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>

Dengan persediaan ini , makro boleh ditakrifkan sebagai:

<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>

Dengan menggunakan OVERLOAD_MACRO hierarki, adalah mungkin untuk mengelak daripada menentukan makro CHOOSE_HELPER.

Atas ialah kandungan terperinci Mengapakah pengembangan makro variadik MSVC berbeza daripada GCC, dan bagaimanakah kita boleh mengatasi percanggahan ini?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
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