如何将宏展开的结果划分为不同的参数



我正在写一些Boost。预处理器元程序,我有以下问题。考虑以下宏(这是对问题的简化说明):

#define ITERATION_IMPL(p1, p2, p3, p4) ((p1),(p2),(p3),(p4))
#define ITERATION(args) ITERATION_IMPL(hello, args(), world)
#define ARGS() a, b
ITERATION(ARGS)

预处理后的输出如下:

((hello),(a, b),(world),())

表示args()没有被分割成多个参数。根据我对标准的理解,宏的参数在被粘贴到替换列表之前是完全展开的。因此,我期望下面的展开序列:

ITERATION(ARGS)
ITERATION_IMPL(hello, ARGS(), world)
ITERATION_IMPL(hello, a, b, world)
((hello),(a),(b),(world))

那是我想要的结果。如何在不修改ITERATION_IMPL和调用本身的情况下实现它?

编辑:如果不可能(我猜是),请根据C或c++的任何标准解释

我认为如果遇到ITERATION(ARGS),则取ITERATION_IMPL(hello, args(), world),用ARGS替换args,然后重新扫描。ITERATION_IMPL(hello, ARGS(), world)ITERATION_IMPL的调用。因此,它取((p1),(p2),(p3),(p4)),并用ARGS()(以及其他参数)替换p2。然后重新扫描并解析为((hello),(a, b),(world),())。我不知道为什么它的工作原理,它调用一个4参数宏与3个参数在你的情况下。

你可以做

#define EVAL(X) X
#define ITERATION(args) ITERATION_IMPL EVAL((hello, args(), world))

这将占用X,替换(hello, ARGS(), world),然后重新扫描,导致ARGS()a, b替换。然后,生成的令牌字符串ITERATION_IMPL (hello, a, b, world)将执行您所期望的操作。

EDIT: test with GCC:)

编辑:我注意到你想要字符串((hello),(a),(b),(world)),但我的答案产生字符串ITERATION_IMPL (hello, a, b, world)。我认为这是因为当它在调用ITERATION后重新扫描时,它将IERATION_IMPL EVAL((hello, ARGS(), world))替换为ITERATION_IMPL (hello, a, b, wold)。然后,它需要另一次扫描才能注意到它现在可以用这些参数调用ITERATION_IMPL了。所以ITERATION应该是

#define ITERATION(args) EVAL(ITERATION_IMPL EVAL((hello, args(), world)))

当外部EVALXITERATION_IMPL EVAL((hello, args(), world))取代时,它会重新扫描并产生ITERATION_IMPL (hello, a, b, world)来调用EVAL。然后,它再次重新扫描ITERATION的调用,并生成您真正想要的序列。

最新更新