Heim > Backend-Entwicklung > C++ > Warum unterscheidet sich die variadische Makroerweiterung von MSVC von der GCC und wie können wir diese Diskrepanz überwinden?

Warum unterscheidet sich die variadische Makroerweiterung von MSVC von der GCC und wie können wir diese Diskrepanz überwinden?

Barbara Streisand
Freigeben: 2024-11-06 09:10:02
Original
881 Leute haben es durchsucht

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

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>
Nach dem Login kopieren

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>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">EXPAND_THESE(Property1, Property2, Property3, Property4)
Nach dem Login kopieren

}

Basis * parent;
};

GCC-Erweiterung:

struct MyStructure<br>{<br> void Foo()<br> {</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">parent->GetProperty<Property1>(); 
parent->GetProperty<Property2>(); 
parent->GetProperty<Property3>(); 
parent->GetProperty<Property4>();
Nach dem Login kopieren

}

Basis * übergeordnetes Element;
}

MSVC-Erweiterung:

struct MyStructure<br>{<br> void Foo()<br> {</p>
<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">parent->GetProperty<Property1, Property2, Property3, Property4>();
Nach dem Login kopieren

}

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>
Nach dem Login kopieren

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>
Nach dem Login kopieren

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>
Nach dem Login kopieren

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!

Quelle:php.cn
Vorheriger Artikel:Wie kann ich eine benutzerdefinierte Klasse mit Qt serialisieren? Nächster Artikel:Wie füge ich doppelte Anführungszeichen in ein String-Literal ein?
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Aktuelle Ausgaben
verwandte Themen
Mehr>
Beliebte Empfehlungen
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage