Max*_*xpm 1 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
Run Code Online (Sandbox Code Playgroud)
问题是它看起来不像PREPROCESSOR_LOOP_ITERATION是递增的,所以它只是无限地包含它自己.如果我将该行更改为实际整数(如17),则预处理器会#include正确跳过该指令.
我做错了什么?
"问题"是宏被懒惰地评估.考虑你的宏定义:
#define PREPROCESSOR_LOOP_ITERATION (PREPROCESSOR_LOOP_ITERATION + 1)
Run Code Online (Sandbox Code Playgroud)
这定义了一个名为宏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
Run Code Online (Sandbox Code Playgroud)
还有一个规则是,如果在替换列表中遇到要替换的宏的名称,则不将其视为宏,因此不会被替换(这有效地禁止宏替换期间的递归).因此,在您的情况下,每次调用PREPROCESSOR_LOOP_ITERATION宏时,都会被替换为
( PREPROCESSOR_LOOP_ITERATION + 1 )
Run Code Online (Sandbox Code Playgroud)
然后宏替换停止,预处理继续下一个令牌.
您可以通过定义一系列宏并使用concatenation(##)运算符对预处理器执行有限的算术运算,但这非常繁琐.您应该考虑使用Boost.Preprocessor库来帮助您.它适用于C和C++代码.它允许有限的迭代,但它允许的是非常有用的.可能是与您的用例匹配的最接近的功能BOOST_PP_ITERATE.其他设施如sequence(BOOST_PP_SEQ)处理程序对编写生成代码非常有帮助.
编辑:正如 James 所指出的,由于对宏的懒惰评估,我的原始解决方案不起作用。如果您的编译器支持它,宏__COUNTER__每次被调用时都会增加 1,您可以使用它来执行一个简单的预处理器循环,如下所示:
// Preprocessor.h
#define MAX_LOOP_ITERATION 16 // Be careful of off-by-one
// do stuff
#if (__COUNTER__ < MAX_LOOP_ITERATION)
#include "Preprocessor.h"
#endif
Run Code Online (Sandbox Code Playgroud)
我通过运行在 Visual C 中验证了这一点cl /P Preprocessor.h。
| 归档时间: |
|
| 查看次数: |
11938 次 |
| 最近记录: |