Heim > Artikel > Backend-Entwicklung > Warum unterscheidet sich die variadische Makroerweiterung von MSVC von der GCC und wie können wir diese Diskrepanz überwinden?
Variadic-Makroerweiterung von MSVC
Variadic-Makros bieten vielseitige Erweiterungsmöglichkeiten, sodass Sie mehrere Argumente innerhalb von Makros verarbeiten können. In GCC funktionieren Makros wie die folgenden wie erwartet:
<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-Erweiterungsverhalten
Im C-Compiler (MSVC) von Microsoft verhält sich die Makroerweiterung jedoch anders . Anstatt jedes Argument einzeln zu erweitern, verkettet MSVC alle Argumente in einem einzigen Ausdruck.
struct MyStructure<br>{<br> void Foo()<br> {</p> <pre class="brush:php;toolbar:false">EXPAND_THESE(Property1, Property2, Property3, Property4)
}
Basis * parent;
};
GCC-Erweiterung:
struct MyStructure<br>{<br> void Foo()<br> {</p> <pre class="brush:php;toolbar:false">parent->GetProperty<Property1>(); parent->GetProperty<Property2>(); parent->GetProperty<Property3>(); parent->GetProperty<Property4>();
}
Basis * übergeordnetes Element;
}
MSVC-Erweiterung:
struct MyStructure<br>{<br> void Foo()<br> {</p> <pre class="brush:php;toolbar:false">parent->GetProperty<Property1, Property2, Property3, Property4>();
}
Base * parent;
}
Lösung:
Jeff Walden hat eine Problemumgehung wie folgt vorgeschlagen Muster:
<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>
Dieser Ansatz erfordert die Definition eines CHOOSE_HELPER-Makros für jede gewünschte variadische Makroanzahl (z. B. ERROR1, ERROR2 usw.). Es ist jedoch wichtig, jedes CHOOSE_HELPER-Makro im Rahmen der Definition des Variadic-Makros zu deklarieren.
Eine prägnantere und tragbarere Lösung ist die Verwendung der folgenden Technik:
<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>
Mit diesem Setup , Makros können wie folgt definiert werden:
<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>
Durch die Verwendung der OVERLOAD_MACRO-Hierarchie ist es möglich, die Definition zu vermeiden CHOOSE_HELPER-Makros.
Das obige ist der detaillierte Inhalt vonWarum unterscheidet sich die variadische Makroerweiterung von MSVC von der GCC und wie können wir diese Diskrepanz überwinden?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!