标准C(或带有GNU扩展程序)是否有任何方法可以将东西附加到宏定义上? 例如, ,给定一个宏定义为
#define List foo bar
我可以附加吗? bas 这样 List 扩展好像我定义了
#define List foo bar bas?

我希望我能做这样的事情:

#define List    foo bar bas

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

但是我不知道如何定义 Expand() 宏,它会做我想做的。

动机:我沿着这些界线进行歧视/标记的工会:

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

我认为这是X-Macro的好地方。如果我定义了宏
#define quux_table X(foo) X(bar) X(bas)
枚举和结构可以因此而定义,永远不要摆脱同步:

#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

当然, quux_* 结构可以摆脱同步,因此我想做这样的事情,只能合法地:

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)

(好吧,我 真的 想做的就是这样
member_struct(quux, foo) { int x; };
但是我很清楚宏无法(重新)从宏内定义。)

无论如何,这是我的激励榜样。有没有办法实现这一目标?

如果您可以向我展示如何使X-MaCro技术与该库一起使用,则boost。

有帮助吗?

解决方案

有效,没有。

宏对宏进行评估。当你 #define List_ Expand(List), ,其替换列表是四个令牌的序列 Expand, (, List, , 和 ). 。没有任何方法可以将宏扩展为替换列表。

当调用宏时,所有宏替换都会发生。

我建议您使用boost.preprocessor库进行自动代码生成。这有点工作,但是您可以完成一些工作 相当令人印象深刻的事情 使用它。它应该与C完全兼容。

其他提示

有一种方法!

使用新的_pragma关键字,可以在GCC中实现(尽管不是MSVC)

如果您在自己的定义中弹出一个宏,它将延迟其扩展,直到首次扩展宏为止。这使您可以使其是其自身定义的先前扩展部分。但是,由于它在扩展过程中弹出,因此只能使用一次

这是一些示例代码,可以看到它

#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

此选项应该使自动代码生成变得更加容易,尽管不幸的是仅在GCC上(也许是clang,尚未测试)

老实说,没有理由我能找到为什么必须起作用的原因,很可能是不确定的行为。我猜想的原因是,在弹出foo之后,正在扩展的当前宏不再与允许符号的名称相关联 foo 要扩大,但这只是我的猜想

编辑:

在Clang上测试后, 才不是 确实在Clang上工作。

我不知道为什么我认为Clang不起作用,也许它没有在其他机器上。我肯定确实让它处理给定的代码

我不确定这是否有帮助,但是您可以做vari arg宏。 X264项目的Conrad先生喜欢预处理器滥用。如果他们听起来可能会帮助您找到更多 这里

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top