Pregunta

¿Hay alguna forma en C o con extensiones GNU-anexar material estándar a una definición de macro? por ejemplo. , dada una macro define como
#define List foo bar
puedo añadir bas para que List se expande como si hubiera definí
#define List foo bar bas?

Tenía la esperanza de que pudiera hacer algo como esto:

#define List    foo bar bas

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

pero no puedo encontrar la manera de definir la macro Expand() por lo que hará lo que yo quiero.

de motivación: Estoy jugando con discriminado / etiquetado sindicatos a lo largo de estas líneas:

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

Calculo este es un lugar bueno para el X-macro. Si defino una macro
#define quux_table X(foo) X(bar) X(bas)
la estructura y la enumeración se puede definir de este modo, y nunca perder la sincronización:

#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

Por supuesto, las estructuras quux_* puede perder la sincronización, por lo que me gustaría hacer algo como esto, solamente legalmente:

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)

(Bueno, lo que realmente quieren ser capaz de hacer es algo así como
member_struct(quux, foo) { int x; };
pero soy muy consciente de que las macros no pueden ser (re) definido dentro de las macros.)

De todos modos, esa es mi ejemplo motivador. ¿Hay una manera de lograr esto?

ejemplos Boost.Preprocessor están bien, si usted me puede mostrar cómo hacer que el X-macro técnica de trabajo con esa biblioteca.

¿Fue útil?

Solución

En efecto, no.

Las macros se perezosamente evaluados. Cuando #define List_ Expand(List), su lista de reemplazo es la secuencia de cuatro fichas Expand, (, List y ). No hay ninguna manera de ampliar una macro en una lista de reemplazo.

Todo reemplazo macro tiene lugar cuando se invoca una macro.

Me gustaría recomendar mirando al uso de la biblioteca Boost.Preprocessor para la generación automática de código. Es un poco de trabajo, pero se puede lograr algunos cosas bastante impresionantes usarlo. Debe ser totalmente compatible con C.

Otros consejos

Hay un camino!

El uso de la nueva palabra clave _Pragma esto se puede lograr en gcc (aunque no con msvc)

Si usted hace estallar una macro dentro de su propia definición se demora es de expansión hasta que la macro se expanda por primera vez. Esto le permite hacer es anterior parte de expansión de su propia definición. Sin embargo, puesto que se extrae durante el mismo de la expansión, sólo puede ser usado una vez

Aquí hay un código de ejemplo para verlo en acción

#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

Esta opción debe realizar generación automática de código una feria poco más fácil, aunque por desgracia sólo en gcc (quizá sonido metálico, no se han probado)

Para ser honesto no hay ninguna razón por qué no puedo encontrar este trabajo imprescindible, es más probable que un comportamiento indefinido que pasa a trabajar. Supongo que la razón es que después de hacer estallar foo, la macro actual está ampliando ya no está asociado con el nombre foo del que permite el símbolo foo se expanda, pero eso es sólo mi conjetura

Editar:

Después de probar el sonido metálico, esto no Cómo funciona el sonido metálico.

No sé por qué pensé sonido metálico no funcionó, tal vez no lo hizo en una máquina diferente. Definitivamente hice conseguir que funcione con el código dado, aunque

No estoy seguro de si esto ayuda, pero se puede hacer vari arg macros. El Sr. Conrad del proyecto x264 ama abuso preprocesador. Si aunque parezca que lo podrían ayudar a que puede encontrar más información Aquí

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top