Question

Est-il possible dans la norme C ou avec GNU extensions pour ajouter des choses à une définition de macro? par exemple. , donné une macro définie comme
#define List foo bar
puis-je ajouter bas pour qu'il List comme si je dilate avais défini ce
#define List foo bar bas?

J'espérais que je pouvais faire quelque chose comme ceci:

#define List    foo bar bas

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

mais je ne peux pas comprendre comment définir la macro Expand() il fera ce que je veux.

Motivation: Je joue avec discriminé / syndicats marqués le long de ces lignes:

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

Je figure cela est un bon endroit pour le X-macro. Si je définir une macro
#define quux_table X(foo) X(bar) X(bas)
l'énumération et la structure peut être définie ainsi, et de ne jamais sortir de synchronisation:

#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

Bien sûr, les structures de quux_* peut se désynchroniser, donc je voudrais faire quelque chose comme ça, seulement légalement:

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)

(Eh bien, ce que je vraiment veulent être en mesure de faire quelque chose comme
member_struct(quux, foo) { int x; };
mais je suis bien conscient que les macros ne peuvent pas être (re) défini à l'intérieur des macros.)

Quoi qu'il en soit, c'est mon exemple motivant. Est-il possible d'y arriver?

exemples Boost.Preprocessor sont très bien, si vous pouvez me montrer comment faire le travail technique X-macro avec cette bibliothèque.

Était-ce utile?

La solution

En effet, non.

Les macros sont évaluées paresseusement. Lorsque vous #define List_ Expand(List), sa liste de remplacement est la séquence de quatre jetons Expand, (, List et ). Il n'y a pas moyen de développer une macro dans une liste de remplacement.

Tout remplacement macro a lieu lorsqu'une macro est invoquée.

Je recommande la recherche à l'aide de la bibliothèque Boost.Preprocessor pour la génération automatique de code. Il est un peu de travail, mais vous pouvez accomplir certains les choses assez impressionnantes utiliser. Il devrait être pleinement compatible avec C.

Autres conseils

Il y a un chemin!

En utilisant le nouveau mot-clé _Pragma cela peut être réalisé dans gcc (mais pas avec msvc)

Si vous sautez une macro au sein de sa propre définition, il va retarder son extension jusqu'à ce que la macro est élargi pour la première fois. Cela vous permet de faire cela fait partie de l'expansion précédente de sa propre définition. Cependant, comme il est sauté lors de l'expansion de, il ne peut être utilisé qu'une seule fois

Voici quelques exemples de code pour le voir en action

#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

Cette option devrait génération automatique de code un peu juste plus facile, mais malheureusement seulement sur gcc (peut-être clang, ont pas testé)

Pour être honnête, il n'y a aucune raison que je peux trouver pourquoi ce travail doit, ce comportement est très probablement non défini qui se passe au travail. Je devine que la raison est que, après popping foo, la macro en cours en cours d'extension n'est plus associé au nom foo qui permet le symbole foo à être étendu, mais qui est seulement ma conjecture

Edit:

Après avoir testé sur clang, cette ne pas fonctionne sur clang.

Je ne sais pas pourquoi je pensais que clang ne fonctionnait pas, peut-être il ne l'a pas sur une autre machine. Je certainement ai eu à travailler avec le code donné si

Je ne sais pas si cela aide, mais vous pouvez faire vari arg macros. M. Conrad du projet x264 aime abus de préprocesseur. S'ils sonnent comme ils pourraient vous aider pouvez en savoir plus

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top