简体   繁体   English

递增预处理器宏

[英]Incrementing Preprocessor Macros

I'm trying to make a simple preprocessor loop. 我试图做一个简单的预处理器循环。 (I realize this is a horrible idea, but oh well.) (我意识到这是一个可怕的主意,但是哦。)

// 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

The issue is that it doesn't look like PREPROCESSOR_LOOP_ITERATION is being incremented, so it just keeps including itself infinitely. 问题在于,它看起来不像PREPROCESSOR_LOOP_ITERATION有所增加,因此它只是无限地包含其自身。 If I change the line to an actual integer (like 17 ), the preprocessor skips over the #include directive properly. 如果我将行更改为实际整数(如17 ),则预处理器会正确跳过#include指令。

What am I doing incorrectly? 我做错了什么?

The "problem" is that macros are lazily evaluated. “问题”是懒惰地评估宏。 Consider your macro definition: 考虑一下您的宏定义:

#define PREPROCESSOR_LOOP_ITERATION (PREPROCESSOR_LOOP_ITERATION + 1)

This defines a macro named PREPROCESSOR_LOOP_ITERATION and its replacement list is the sequence of five preprocessing tokens ( , PREPROCESSOR_LOOP_ITERATION , + , 1 , and ) . 这定义了一个名为PREPROCESSOR_LOOP_ITERATION的宏,其替换列表是五个预处理标记(PREPROCESSOR_LOOP_ITERATION+1)的序列。 The macro is not expanded in the replacement list when the macro is defined. 定义宏后,该宏不会在替换列表中展开。 Macro replacement only takes place when you invoke the macro. 宏替换仅在您调用宏时发生。 Consider a simpler example: 考虑一个更简单的示例:

#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

There is an additional rule that if the name of a macro being replaced is encountered in a replacement list, it is not treated as a macro and thus is not replaced (this effectively prohibits recursion during macro replacement). 还有一个附加规则,如果在替换列表中遇到要替换的宏的名称,则该名称不会被视为宏,因此不会被替换(这实际上禁止了在宏替换期间进行递归)。 So, in your case, any time you invoke the PREPROCESSOR_LOOP_ITERATION macro, it gets replaced with 因此,就您而言,只要您调用PREPROCESSOR_LOOP_ITERATION宏,它就会被替换为

( PREPROCESSOR_LOOP_ITERATION + 1 )

then macro replacement stops and preprocessing continues with the next token. 然后宏替换将停止,并且预处理将继续处理下一个标记。

You can perform limited arithmetic with the preprocessor by defining a sequence of macros and making use of the concatenation ( ## ) operator, but it's quite tedious. 您可以通过定义宏序列并使用串联( ## )运算符来使用预处理器执行有限的算术运算,但这很繁琐。 You should consider using the Boost.Preprocessor library to help you with this. 您应该考虑使用Boost.Preprocessor库来帮助您。 It will work with both C and C++ code. 它将与C和C ++代码一起使用。 It allows for limited iteration, but what it does allow is extraordinarily useful. 它允许有限的迭代,但是它允许的功能非常有用。 The closest feature that matches your use case is likely BOOST_PP_ITERATE . 与您的用例最接近的功能可能是BOOST_PP_ITERATE Other facilities like the sequence ( BOOST_PP_SEQ ) handlers are very helpful for writing generative code. 诸如序列( BOOST_PP_SEQ )处理程序之类的其他工具对于编写生成代码非常有帮助。

EDIT: As James pointed out, my original solution did not work due to lazy evaluation of macros. 编辑:正如詹姆斯指出,由于对宏的惰性评估,我的原始解决方案无法正常工作。 If your compiler supports it, the macro __COUNTER__ increments by one every time it is called, and you can use it to do a simple preprocessor loop like this: 如果您的编译器支持它,则每次调用宏__COUNTER__时,它__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

I verified this in Visual C by running cl /P Preprocessor.h . 我通过运行cl /P Preprocessor.h在Visual C中对此进行了验证。

Seriously, find another way to do this. 认真地,找到另一种方式来做到这一点。

The preprocessor should be relegated to include guards and simple conditional compilations. 预处理程序应降级为包括防护和简单的条件编译。

Everything else it was ever useful for has a better way to do it in C++ (inlining, templates and so forth). 它曾经有用的所有其他东西都有更好的方法可以在C ++中实现(内联,模板等)。

The fact that you state I realize this is a horrible idea ... should be a dead giveaway that you should rethink what you're doing :-) 你说I realize this is a horrible idea ...的事实I realize this is a horrible idea ...应该是一个死胡同,你应该重新考虑自己在做什么:-)

What I would suggest is that you step back and tell us the real problem that you're trying to solve. 我建议您退后一步,告诉我们您要解决的实际问题。 I suspect that implementing recursive macros isn't the problem, it's a means to solve a problem you're having. 我怀疑实现递归宏不是问题,这是解决您遇到的问题的一种方法。 Knowing the root problem will open up all sorts of other wondrous possibilities. 知道了根本问题,将开辟各种其他奇妙的可能性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM