Erzeugende Funktion Erklärung mit Hilfe eines makro-iteration
Ich versuche zu generieren, die Funktionsdeklaration mit einem makro
/* goal: generate int f(int a, float b) */
template<typename P>
struct ptype;
template<typename P>
struct ptype<void(P)> { typedef P type; };
#define NAMEe
#define COMMAe
#define COMMA ,
#define NAME(N) N PARAMS
#define PARAMS(P, ...) COMMA ## __VA_ARGS__ P NAME ## __VA_ARGS__
#define PARAM_ITER(P) P NAME
#define PROTO(R, N, P) \
ptype<void R>::type N (PARAM_ITER P (,e))
PROTO((int), f, (int)(a)(float)(b));
Wird es iterativ mit der Bearbeitung des nächsten (name)
oder (type)
durch NAME
oder PARAMS
bzw. mit der ...
mit einer leeren makro-argument. Aber GCC beschwert sich mit
prototype.hpp:20:35: warning: ISO C99 requires rest arguments to be used
Und clang beschwert sich mit
ptype<void (int)>::type f (int aprototype.hpp:20:1: warning: varargs argument missing, but tolerated as an extension [-pedantic]
Ich denke, dies geschieht aufgrund der folgenden
#define FOO(X, ...)
FOO(A);
Weil ich mich nicht übergeben eines Arguments für die ...
oder jede dieser (name)
oder (type)
. Gibt es keine einfache Arbeit um die ich mich bewerben kann?
Hab ich ja jetzt eine Technik ähnlich dem Verfahren von @James zu finden, die Länge der parameter-Liste. Wenn als zweites argument, statt O
, ONT
übergeben wird, werde ich drucken Sie das Komma und die NAME
. Das folgende ist die endgültige Lösung:
/* goal: generate void f(int a, float b) */
template<typename P>
struct ptype;
template<typename P>
struct ptype<void(P)> { typedef P type; };
#define TYPE_DO(X) X
#define TYPE_DONT(X)
#define TYPE_MAYBE(X, A, ...) TYPE_D ## A (X)
#define COMMA_DO ,
#define COMMA_DONT
#define COMMA_MAYBE(A, B, ...) COMMA_D ## B
#define NAME_DO NAME
#define NAME_DONT
#define NAME_MAYBE(A, B, ...) NAME_D ## B
#define NAME(N) N PARAMS
#define PARAMS(...) COMMA_MAYBE(__VA_ARGS__,O,O) TYPE_MAYBE(__VA_ARGS__,O,O) \
NAME_MAYBE(__VA_ARGS__,O,O)
#define PARAM_ITER(P) P NAME
#define PROTO(R, N, P) \
ptype<void R>::type N (PARAM_ITER P (D,ONT))
Test:
#define STR1(X) #X
#define STR(X) STR1(X)
int main() {
//prints correctly
std::cout << STR(PROTO((int), f, (int)(a)(float)(b)));
}
Du musst angemeldet sein, um einen Kommentar abzugeben.
P99 hat ein makro, das genau das tut, was Sie wollen, ich glaube, nämlich
P99_PROTOTYPE
. Es hat eine "Signatur" vonwo
RT
ist der return-Typ (kannvoid
) undAT
sind die argument-Typen. Die Liste der argument-Typen kann auch leer sein, in welchem Fall es ersetzt wird durchvoid
.Vorsicht, dass die P99 ist für C99 und nicht für C++. Sie begegnen besonderen Schwierigkeiten, wenn Ihre Argumente, die Kommas enthalten. C++'s syntax Missbrauch des Token
<
und>
als Belichtungsreihe Ausdrücke für Vorlagen ist besonders schlecht für den Präprozessor. C-Präprozessor und C++ sind im Grunde unvereinbar Sprachen auf die syntax-Ebene.P99 bekommt von den Schwierigkeiten, die Sie konfrontiert sind durch die Erkennung der Anzahl der Argumente, das makro erhält einen Anruf und reagiert anders auf die Grenze Fällen.
void P
trick, um den Typ. Ich werde inP99_PROTOTYPE
- code und sehen wie er sich macht Sachen. Danke!P00_ROBUST
zur Halterung der Ausdruck. Dieses makro ist einfach wieder seiner Liste von Argumenten, aber im Rahmen einer makro-Ausdehnung dies hat den Vorteil, dass die Kommas trennen die Argumente derP00_ROBUST
werden nicht gezählt für die Argumente des anderen makro. Ich bin nicht sicher, ob die C++ hat die gleiche Auswertung, um als die von C99, so dass dies möglicherweise oder möglicherweise nicht arbeiten.Lösen die "
FOO
" problem, können Sie verschiedene Makros, je nach Dimension der Variablen Argumente pack. Hier gibt es einen ersten Schuss auf die:Beispiel:
(Ich werde versuchen, zu überdenken, diese zu bereinigen; ich denke, es gibt definitiv einige unnötige Makros drin. Ich hatte noch keine Gelegenheit einen Blick in die breitere problem, das Sie beschreiben, also ich bin mir nicht sicher, ob dies löst auch das. Möglicherweise gibt es eine einfachere Möglichkeit, um dieses problem zu lösen, zu... ich bin nicht besonders vertraut mit variadischen Makros. Diese preprocesses sauber auf mcpp.)