Domanda

C'è un modo in C standard o con GNU estensioni-per aggiungere roba per una definizione di macro? per es. , data una macro definita come
#define List foo bar
posso aggiungere bas in modo che List espande come se avessi definito che
#define List foo bar bas?

speravo avrei potuto fare qualcosa di simile:

#define List    foo bar bas

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

, ma non riesco a capire come definire la macro Expand() quindi farà quello che voglio.

Motivazione: Sto giocando con discriminato / tagged sindacati in queste righe:

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;
};

Immagino che questo è un buon posto per la X-macro. Se io definisco un
macro #define quux_table X(foo) X(bar) X(bas)
la struttura di enumerazione e può essere definita in tal modo, e non arrivano mai fuori sincrono:

#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

Naturalmente, le strutture quux_* possono ottenere fuori sincronia, quindi mi piacerebbe fare qualcosa di simile, solo legale:

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)

(Beh, quello che davvero vogliono essere in grado di fare è qualcosa di simile
member_struct(quux, foo) { int x; };
ma sono ben consapevole che le macro non può essere (ri) definiti all'interno delle Macro).

In ogni caso, questo è il mio esempio motivante. C'è un modo per ottenere questo?

esempi Boost.Preprocessor vanno bene, se mi si può mostrare come fare il X-macro lavoro tecnica con quella libreria.

È stato utile?

Soluzione

In effetti, no.

Le macro sono pigramente valutati. Quando si #define List_ Expand(List), la sua lista di sostituzione è la sequenza di quattro gettoni Expand, (, List e ). Non c'è alcun modo per espandere una macro in una lista di sostituzione.

Tutti sostituzione macro avviene quando una macro viene richiamato.

mi consiglia di guardare utilizzando la libreria Boost.Preprocessor per la generazione automatica di codice. E 'un po' di lavoro, ma si può realizzare alcune cose abbastanza impressionanti utilizzarlo. Dovrebbe essere pienamente compatibile con C.

Altri suggerimenti

C'è un modo!

Con la nuova parola chiave _Pragma questo può essere realizzato in GCC (anche se non con msvc)

Se si pop una macro all'interno di essa la propria definizione sarà ritardare di espansione fino a quando la macro viene espansa per la prima volta. Questo ti permette di fare è precedente parte espansione di essa la propria definizione. Tuttavia, dal momento che è spuntato nel corso di essa l'espansione, esso può essere utilizzato solo una volta

Ecco alcuni esempi di codice per vederlo in azione

#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

Questa opzione dovrebbe generazione automatica di codice un bel po 'più facile, anche se purtroppo solo su GCC (forse clang, non hanno testato)

Per essere onesti non c'è motivo riesco a trovare il motivo per cui questo lavoro deve, è molto probabilmente un comportamento indefinito che accade al lavoro. Sto indovinando il motivo è che dopo popping foo, la macro corrente in fase di espansione non è più associato al nome foo che permette al foo simbolo di essere ampliato, ma questa è solo la mia congettura

Modifica:

Dopo aver testato il clang, questo non funziona sulla clang.

Non so perché ho pensato clang non ha funzionato, forse non lo ha fatto su una macchina diversa. Ho sicuramente fatto arrivare al lavoro con il codice dato se

Non sono sicuro se questo aiuta, ma si può fare vari arg macro. Il signor Conrad del progetto x264 ama abusi preprocessore. Se suonano come potrebbero aiutare a saperne di più Qui

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top