2013-10-18 7 views
8

Ich verwende die Makros von dieser post Schleife durch meine Argumente. Alles funktioniert super! Aber gibt es eine Möglichkeit, diese beiden CCB_CREATE und CCB_CREATE_MORE zu kombinieren?C++ Präprozessor Makroschleife __VA_ARGS__ 1 vs 2 + Argumente

Ich muss das erste Argument object_type extrahieren, um zusätzlichen Code zu schreiben. Die zusätzlichen object_type s verwenden die FOR_EACH-Schleife zum Einfügen in die Karte.

Der Compiler Beschwerden, wenn ich nur ein Argument bei der Verwendung von CCB_CREATE_MORE(Type1). Um das zu beheben, habe ich ein anderes Makro erstellt, um das zu handhaben CCB_CREATE(Type1). Ich hoffe, eine clevere Lösung zu finden, diese beiden zu einem eleganten Makro zu kombinieren. Irgendwelche Ideen?

+5

Ich empfehle nicht, '__type__' zu verwenden. Es ist eine reservierte Kennung. – chris

+0

Vielen Dank, dass Sie darauf hingewiesen haben. Habe gerade eine Suche gemacht und diese ersetzt. – docchang

Antwort

5

Der Compiler beschweren sich wahrscheinlich über das abschließende Komma, wenn die variadic Argumente Liste leer ist. GCC und Visual Studio Compiler unterstützen die Nicht-Standard-Erweiterung ##__VA_ARGS__ das folgende Komma zu unterdrücken:

#define FOO(fmt, ...) printf(fmt, ##__VA_ARGS__) 

Die Visual Studio Compiler wird auch die nachlaufunterdrücken Komma auch ohne die ## Erweiterung.

Siehe GCC-Dokumentation here und Visual Studio-Dokumentation here.

Wenn Sie eine standardkonforme Lösung benötigen, finden Sie eine detaillierte Antwort auf this question.

Wenn Sie also entweder gcc oder Visual Studio verwenden, sollten Sie in der Lage sein, Ihre ursprünglichen Makro mit dieser einfachen Änderung zu verwenden:

#define CCB_CREATE(object_type,...) \ 
static CCNode * create##object_type##Node() { \ 
    std::map<std::string, CCNodeLoader*> loader_map; \ 
    std::string classname = #object_type; \ 
    FOR_EACH(INSERT_LOADER_MAP,object_type,##__VA_ARGS__); \ 
    return loadCCBFile((classname + ".ccbi").c_str(), loader_map); \ 
} 

Edit: Sie müssten die ##__VA_ARGS__ Erweiterung verwenden in das FOR_EACH() Makro auch, oder die elegantere Änderung, die von ugoren vorgeschlagen wird.

2

Neben Chris Olsen's suggestion eine leichte Änderung des FOR_EACH Makro benötigt wird:

#define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__) 

Als Ergebnis wird FOR_EACH(X, a)X(a) werden (statt X(a); X();). Dies beseitigt einen leeren INSERT_LOADER_MAP Aufruf.