我可以附加到预处理器宏吗?
-
13-10-2019 - |
题
标准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先生喜欢预处理器滥用。如果他们听起来可能会帮助您找到更多 这里