c++ - 递增预处理器宏

标签 c++ loops c-preprocessor

我正在尝试制作一个简单的预处理器循环。 (我意识到这是一个可怕的想法,但是哦,好吧。)

// Preprocessor.h

#ifndef PREPROCESSOR_LOOP_ITERATION

#define MAX_LOOP_ITERATION 16 // This can be changed.

#define PREPROCESSOR_LOOP_ITERATION 0

#endif

#if (PREPROCESSOR_LOOP_ITERATION < MAX_LOOP_ITERATION)
#define PREPROCESSOR_LOOP_ITERATION (PREPROCESSOR_LOOP_ITERATION + 1) // Increment PREPROCESSOR_LOOP_ITERATION.
#include "Preprocessor.h"
#endif

问题是它看起来不像 PREPROCESSOR_LOOP_ITERATION 正在递增,所以它只是无限地包含自己。如果我将该行更改为实际整数(如 17),预处理器会正确地跳过 #include 指令。

我做错了什么?

最佳答案

“问题”是宏被惰性求值。考虑您的宏定义:

#define PREPROCESSOR_LOOP_ITERATION (PREPROCESSOR_LOOP_ITERATION + 1)

这定义了一个名为 PREPROCESSOR_LOOP_ITERATION 的宏,它的替换列表是五个预处理标记的序列 (, PREPROCESSOR_LOOP_ITERATION, +1)。定义宏时,宏不会在替换列表中扩展。宏替换仅在您调用宏时发生。考虑一个更简单的例子:

#define A X
#define B A

B // this expands to the token X

#undef A
#define A Y
B // this expands to the token Y

还有一个额外的规则,如果在替换列表中遇到被替换的宏的名称,则不会将其视为宏,因此不会被替换(这有效地禁止了宏替换期间的递归)。因此,在您的情况下,每当您调用 PREPROCESSOR_LOOP_ITERATION 宏时,它都会被替换为

( PREPROCESSOR_LOOP_ITERATION + 1 )

然后宏替换停止,预处理继续下一个标记。

您可以通过定义一系列宏并使用连接 (##) 运算符来使用预处理器执行有限的算术运算,但它非常乏味。您应该考虑使用 Boost.Preprocessor图书馆来帮助你。它适用于 C 和 C++ 代码。它允许有限的迭代,但它所允许的是非常有用的。最接近您的用例的功能可能是 BOOST_PP_ITERATE。序列 (BOOST_PP_SEQ) 处理程序等其他工具对于编写生成代码非常有帮助。

关于c++ - 递增预处理器宏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5025260/

相关文章:

c++ - AutoCAD 实体可以序列化吗?

c++ - 覆盖语法,返回指向固定大小数组的指针的专用模板方法

c++ - 不情愿地通过 RPC 调用 QueryInterface

PHP - 创建自定义模板系统?

php - 如何在smarty中显示数组?

c - 在库中覆盖#define

c++ - 类不被认可?

arrays - 如何在Rust中循环遍历整数向量?

c++ - #define 以及如何使用它们 - C++

c - 是否可以将定义的值用作标识符的一部分?