Frage

Gibt es eine Möglichkeit in Standard -C - oder bei GNU -Erweiterungen -, um Dinge an eine Makrodefinition anzuhängen? Z.B, bei einem Makro als definiert als
#define List foo bar
Kann ich anhängen? bas So das ist es List erweitert, als hätte ich es definiert
#define List foo bar bas?

Ich hatte gehofft, ich könnte so etwas tun:

#define List    foo bar bas

#define List_   Expand(List)
#undef List
#define List    Expand(List_) quux

Aber ich kann nicht herausfinden, wie ich das definieren kann Expand() Makro, also wird es tun, was ich will.

Motivation:Ich spiele mit diskriminierten/markierten Gewerkschaften in diesem Sinne:

struct quux_foo { int x; };
struct quux_bar { char *s; };
struct quux_bas { void *p; };

enum quux_type {quux_foo, quux_bar, quux_bas};

struct quux {
    enum quux_type type;
    union {
        struct quux_foo foo;
        struct quux_bar bar;
        struct quux_bas bas;
    } t;
};

Ich denke, das ist ein guter Ort für die X-Makro. Wenn ich ein Makro definiere
#define quux_table X(foo) X(bar) X(bas)
Die Aufzählung und Struktur können so definiert werden und werden niemals aus Synchronisation herauskommen:

#define X(t) quux_ ## t,
enum quux_type {quux_table};
#undef X

#define X(t) struct quux_ ## t t;
struct quux {
    enum quux_type type;
    union {quux_table} t;
};
#undef X

Natürlich die quux_* Strukturen können aus der Synchronisierung herauskommen, also möchte ich so etwas nur legal tun:

struct quux_foo { int x; };
#define quux_table quux_table X(foo)

struct quux_bar { char *s; };
#define quux_table quux_table X(bar)

struct quux_bas { void *p; };
#define quux_table quux_table X(bas)

(Nun, was ich Ja wirklich will in der Lage sein zu können, ist so etwas wie
member_struct(quux, foo) { int x; };
Aber ich bin mir bewusst, dass Makros nicht innerhalb von Makros (Re) definiert werden können.)

Wie auch immer, das ist mein motivierendes Beispiel. Gibt es eine Möglichkeit, dies zu erreichen?

Boost.Proprocessor-Beispiele sind in Ordnung, wenn Sie mir zeigen können, wie die X-Macro-Technik mit dieser Bibliothek funktioniert.

War es hilfreich?

Lösung

Effektiv, nein.

Makros werden träge bewertet. Wenn du #define List_ Expand(List), Seine Ersatzliste ist die Abfolge von vier Token Expand, (, List, und ). Es gibt keine Möglichkeit, ein Makro in eine Ersatzliste zu erweitern.

Der gesamte Makroersatz erfolgt, wenn ein Makro aufgerufen wird.

Ich würde empfehlen, die Bibliothek von Boost.Proprocessor für die automatische Codegenerierung zu verwenden. Es ist ein bisschen Arbeit, aber Sie können einige erreichen ziemlich beeindruckende Dinge es benutzen. Es sollte vollständig mit C kompatibel sein mit C.

Andere Tipps

Da ist ein Weg!

Mit dem neuen _pragma -Schlüsselwort kann dies in GCC erreicht werden (wenn auch nicht mit MSVC)

Wenn Sie ein Makro in seine eigene Definition platzieren, verzögert dies die Erweiterung, bis das Makro zum ersten Mal erweitert wird. Dies ermöglicht es Ihnen, den vorherigen Erweiterung ein Teil seiner eigenen Definition zu ermöglichen. Da es jedoch während seiner Expansion geknallt ist, kann es nur einmal verwendet werden

Hier ist ein Beispielcode, um ihn in Aktion zu sehen

#define pushfoo _Pragma("push_macro(\"foo\")") //for convenience
#define popfoo _Pragma("pop_macro(\"foo\")")

#define foo 1

pushfoo                           //push the old value
#undef foo                        //so you don't get a warning on the next line
#define foo popfoo foo , 2        //append to the previous value of foo

pushfoo
#undef foo
#define foo popfoo foo , 3

pushfoo
#undef foo
#define foo popfoo foo , 4


foo //this whole list will expand to something like popfoo foo popfoo foo popfoo foo , 4
    //which will in turn expand to 1 , 2 , 3 , 4

foo //the second time this will expand to just 1

Diese Option sollte die automatische Codeerzeugung ein bisschen einfacher machen, wenn auch leider nur bei GCC (vielleicht Clang, nicht getestet)

Um ehrlich zu sein, gibt es keinen Grund, warum ich herausfinden kann, warum dies funktionieren muss. Es ist höchstwahrscheinlich undefiniertes Verhalten, das zufällig funktioniert. Ich vermute, der Grund dafür ist, dass nach dem Knallen Foo das aktuelle Makro nicht mehr mit dem Namen Foo zugeordnet ist, das das Symbol erlaubt foo erweitert werden, aber das ist nur meine Vermutung

Bearbeiten:

Nach dem Testen auf Clang, das nicht arbeitet an Clang.

Ich weiß nicht, warum ich dachte, Clang hat nicht funktioniert, vielleicht hat es sich vielleicht nicht auf einer anderen Maschine handelt. Ich habe es definitiv mit dem gegebenen Code zum Laufen gebracht

Ich bin mir nicht sicher, ob dies hilft, aber Sie können Vari -Arg -Makros machen. Herr Conrad vom X264 -Projekt liebt Präprozessormissbrauch. Wenn sie so klingen, als könnten sie helfen, können Sie mehr herausfinden Hier

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top