gpt4 book ai didi

我可以附加到预处理器宏吗?

转载 作者:太空狗 更新时间:2023-10-29 16:53:08 25 4
gpt4 key购买 nike

在标准 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() 宏,这样它就会执行我想要的操作。

动机:我正在按照这些思路处理受歧视/标记的 union :

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; };
但我很清楚不能从宏内部(重新)定义宏。)

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

Boost.Preprocessor 示例很好,如果你能告诉我如何使 X-macro 技术与该库一起工作。

最佳答案

有办法!

使用新的 _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 的名称 foo 相关联,但这只是我的猜想

编辑:

在 clang 上测试后,这个在 clang 上工作。

我不知道为什么我认为 clang 不起作用,也许它在不同的机器上不起作用。我确实确实让它与给定的代码一起工作

关于我可以附加到预处理器宏吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4550075/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com