4

我正在写一些 Boost.Preprocessor 元程序,我有以下问题。考虑以下宏(这是为了说明问题而进行的简化):

#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++ 标准进行解释。

4

1 回答 1

3

我认为如果ITERATION(ARGS)遇到,它需要ITERATION_IMPL(hello, args(), world),替换argsARGS,然后重新扫描。ITERATION_IMPL(hello, ARGS(), world)是对 的调用ITERATION_IMPL。因此,它需要((p1),(p2),(p3),(p4)),并替换p2ARGS()(连同其他参数)。然后它重新扫描并解析为((hello),(a, b),(world),()). 我不知道为什么它在您的情况下调用带有 3 个参数的 4 参数宏。

你可以做

#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)将执行您的预期。

编辑:用 GCC 测试:)

编辑:我注意到你想要 string ((hello),(a),(b),(world)),但我的回答产生了 string 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)))

Xfor 外部EVAL被 替换时ITERATION_IMPL EVAL((hello, args(), world)),它会重新扫描并ITERATION_IMPL (hello, a, b, world)为调用EVAL. 然后它再次重新扫描以调用ITERATION并产生您真正想要的序列。

于 2011-04-15T12:50:34.723 回答