Variadische Makroerweiterung in MSVC
Der variadische Makromechanismus in MSVC verhält sich anders als der in GCC, was zu Schwierigkeiten bei der Erweiterung von Makros führt mehrere Argumente. Betrachten Sie die folgenden Makros:
<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>
In GCC würde dieses Makro erweitert werden zu:
<code class="cpp">struct MyStructure { void Foo() { parent->GetProperty<Property1>(); parent->GetProperty<Property2>(); parent->GetProperty<Property3>(); parent->GetProperty<Property4>(); } Base * parent; }</code>
In MSVC wird es jedoch erweitert zu:
<code class="cpp">struct MyStructure { void Foo() { parent->GetProperty<Property1, Property2, Property3, Property4>(); } Base * parent; }</code>
Erklärung
Das Problem entsteht, weil MSVC die Makroerweiterung Ebene für Ebene anwendet, während GCC Makros in einem Durchgang vollständig erweitert. Betrachten Sie den Makroaufruf:
<code class="cpp">EXPAND_THESE(Property1, Property2, Property3, Property4)</code>
MSVC :
GCC:
Workaround
Um ein ähnliches Verhalten wie GCC zu erreichen, kann man den Ansatz von Jeff Walden anwenden beinhaltet das Erstellen zusätzlicher Makro-Helfer und die Verwendung des COUNT_ARGS_MAX5-Makros, um die Anzahl der Argumente zu bestimmen:
<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>
Alternativ kann die vom „GLUE“-Makro bereitgestellte Abstraktion verwendet werden, um die Problemumgehung zu vereinfachen:
<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>
Das obige ist der detaillierte Inhalt vonWarum unterscheidet sich die Variadic-Makroerweiterung zwischen MSVC und GCC?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!