2016-07-05 3 views
1

Ich versuche, ein Makro zu erstellen, das über eine definierte Liste von Begriffen iterieren und für jeden einen anderen Makro möglicherweise mit zusätzlicher Argumentliste aufrufen würde. Hier ist, was ich habe:Ungültige Anzahl von Argumenten in einem Variadic-Makro

#define ITERATE_OVER_TERMS(MACRO, ...) \ 
MACRO(Term1, __VA_ARGS__) \ 
MACRO(Term2, __VA_ARGS__) \ 
MACRO(Term3, __VA_ARGS__) \ 
... and so on 

Allerdings, wenn ich versuche, es zu benutzen, die mit Visual Studio 2015, erhalte ich einen Fehler

warning C4003: not enough actual parameters for macro 'BODY' 

wo BODY ist der Name des Makros als die übergebene MACRO Argument. Obwohl es technisch eine Warnung ist, zeigt es, dass etwas mit der Erweiterung nicht stimmt.

In einem Versuch, den Fehler zu verengen, reduzierte ich mein Beispiel auf die folgende:

#include <iostream> 

#define ITERATE(MACRO, ...) \ 
MACRO(1, __VA_ARGS__) MACRO(2, __VA_ARGS__) 

#define BODY(IterationArg, Arg1, Arg2) \ 
std::cout << IterationArg << Arg1 << Arg2 << std::endl; 

int main() { 
    ITERATE(BODY, 8, 9) 
    return 0; 
} 

Es mir den Fehler gibt, wie oben gezeigt, während ich es erwartete erfolgreich zu kompilieren und die Ausgabe

produzieren
189 
289 

Es scheint mit g ++, aber nicht mit Visual Studio zu kompilieren. Was fehlt mir? Gibt es einen Umweg, damit das funktioniert?

+0

Visual Studio 2015 hat noch eine teilweise Unterstützung für C99-Präprozessor. Quelle: https://msdn.microsoft.com/en-us/library/hh567368.aspx – KABoissonneault

+0

@KABoissonneault Sie scheinen variadic Makros für eine lange Zeit zu unterstützen (https://msdn.microsoft.com/en-us/library /ms177415.aspx) Es gibt bereits Versionen für VS2005. – CygnusX1

+0

Sie unterstützen Variadic-Makros, aber um ehrlich zu sein habe ich noch nie ein Makro als Makro-Argument übergeben. Visual Studio erwartet wahrscheinlich, dass Sie 'BODY' direkt im' main'-Körper auswerten. – KABoissonneault

Antwort

2

Das Problem ist, dass Visual Studio __VA_ARGS__ erweitert, nachdem sie in einem nachfolgenden Makro und nicht vorher übergeben werden. Dies hat sich auch in der Vergangenheit Probleme verursacht, zum Beispiel hier - Why does this variadic argument count macro fail with VC++?

In Ihrem Fall eine einfache Änderung im Code betrachten:

#include <iostream> 

#define ITERATE(MACRO, ...) \ 
MACRO(1, __VA_ARGS__) MACRO(2, __VA_ARGS__) 

#define BODY(IterationArg, Arg1, Arg2) \ 
std::cout << #Arg1 << std::endl; 

int main() { 
    ITERATE(BODY, 8, 9) 
    return 0; 
} 

Das Argument #Arg1 Zeichenfolge ist, zeigt uns seine Inhalte in der Ausgabe:

8, 9 
8, 9 

Nicht was wir erwartet haben, nicht wahr?

Eine Lösung ist das gleiche wie in der verknüpften Frage: eine Expansion durch eine Dummy EXPAND Makro erzwingen:

#define EXPAND(x) x 

#define ITERATE(MACRO, ...) \ 
EXPAND(MACRO(1, __VA_ARGS__)) EXPAND(MACRO(2, __VA_ARGS__)) 

Dies gibt man das gewünschte Ergebnis sowohl in VS und GCC.

Verwandte Themen