C++ 有没有办法在另一个#define 中执行#define?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3314032/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 12:36:59  来源:igfitidea点击:

Is there a way to do a #define inside of another #define?

c++c-preprocessor

提问by Victor Ronin

I know that I am trying to shoot myself in the leg ;) However, it will allow me to make the rest (big amount) of code smaller and more readable.

我知道我正试图向自己的腿开枪 ;) 但是,它可以让我使其余(大量)代码更小且更具可读性。

Is there any tricky way to create preprocessor macro inside of another preprocessor macro?

在另一个预处理器宏中创建预处理器宏有什么棘手的方法吗?

Here is the example, what I am looking for. My real scenario is more complex

这是我正在寻找的示例。我的真实场景更复杂

// That's what I want to do and surely C++ doesn't like it.
#define MACROCREATER(B) #define MACRO##B B+B

void foo()
{
 MACROCREATOR(5) // This should create new macro (#define MACRO5 5+5)

 int a = MACRO5; // this will use new macro
}

回答by hkaiser

The C++ Standard says (16.3.4.3):

C++ 标准说 (16.3.4.3):

The resulting completely macro-replaced preprocessing token sequence [... of the macro expansion...] is not processed as a preprocessing directive even if it resembles one...

生成的完全宏替换的预处理标记序列 [... 宏扩展...] 不会作为预处理指令处理,即使它类似于一个...

So no, there is no 'official' way of achieving what you want with macros.

所以不,没有“官方”的方式来实现你想要的宏。

回答by James McNellis

No. Even if a macro expands into something that looks like a preprocessing directive, the expansion is not evaluated as a preprocessing directive.

不可以。即使宏扩展为看起来像预处理指令的内容,扩展也不会被评估为预处理指令。

回答by Jon Purdy

As a supplement to the answers above, if you reallywanted to pre-process a source file twice—which is almost definitely notwhat you actually want to do—you could always invoke your compiler like this:

作为对上述答案的补充,如果您真的想对源文件进行两次预处理——这几乎肯定不是您真正想要做的——您总是可以像这样调用编译器:

g++ -E input.cpp | g++ -c -x c++ - -o output.o

That is, run the file through the preprocessor, then run the preprocessed output via pipe through a full compilation routine, including a second preprocessing step. In order for this to have a reasonably good chance of working, I'd imagine you'd have to be rather careful in how you defined and used your macros, and all in all it would most likely not be worth the trouble and increased build time.

也就是说,通过预处理器运行文件,然后通过管道通过完整的编译例程运行预处理的输出,包括第二个预处理步骤。为了让它有相当好的工作机会,我想你必须非常小心你如何定义和使用你的宏,总而言之,这很可能不值得麻烦和增加构建时间。

If you really want macros, use standard macro-based solutions. If you really want compile-time metaprogramming, use templates.

如果您确实需要宏,请使用基于宏的标准解决方案。如果您真的想要编译时元编程,请使用模板。

On a slightly related note, this reminds me of the fact that raytracing language POV-Ray made heavy use of a fairly complex preprocessing language, with flow-control directives such as #whilethat allowed conditional repetition, compile-time calculations, and other such goodies. Would that it were so in C++, but it simply isn't, so we just do it another way.

在一个稍微相关的说明中,这让我想起了这样一个事实,即光线跟踪语言 POV-Ray 大量使用了一种相当复杂的预处理语言,其中#while包含允许条件重复、编译时计算和其他此类优点的流控制指令。会不会在 C++ 中是这样,但它根本不是,所以我们只是用另一种方式来做。

回答by Laurence Gonsalves

No. The pre-processor is single-pass. It doesn't re-evaluate the macro expansions.

否。预处理器是单程的。它不会重新评估宏扩展。

回答by supercat

As noted, one can #include a particular file more than once with different macro definitions active. This can make it practical to achieve some effects that could not be practically achieved via any other means.

如前所述,可以多次#include 一个特定文件,同时激活不同的宏定义。这可以使实现一些通过任何其他方式实际上无法实现的效果变得切实可行。

As a simple example, on many embedded systems pointer indirection is very expensive compared to direct variable access. Code which uses a lot of pointer indirection may very well be twice as large and slow as code which simply uses variables. Consequently, if a particular routine is used with two sets of variables, in a scenario where one would usually pass in a pointer to a structure and then use the arrow operator, it may be far more efficient to simple put the routine in its own file (I normally use extension .i) which is #included once without macro _PASS2 defined, and a second time with. That file can then #ifdef _PASS2/#else to define macros for all the variables that should be different on the two passes. Even though the code gets generated twice, on some micros that will take less space than using the arrow operator with passed-in pointers.

作为一个简单的例子,在许多嵌入式系统上,指针间接访问与直接变量访问相比非常昂贵。使用大量指针间接的代码很可能是仅使用变量的代码的两倍大和慢。因此,如果特定例程与两组变量一起使用,在通常会传递指向结构的指针然后使用箭头运算符的情况下,将例程简单地放在其自己的文件中可能会更有效率(我通常使用扩展名 .i),它是 #included 一次,没有定义宏 _PASS2,第二次使用。然后该文件可以 #ifdef _PASS2/#else 为所有在两次传递中应该不同的变量定义宏。即使代码被生成两次,

回答by Jonathan Engdahl

Take a look at m4. It is similar to cpp, but recursive and much more powerful. I've used m4 to create a structured language for assemblers, e.g.

看看m4。它类似于 cpp,但递归且功能更强大。我已经使用 m4 为汇编程序创建了一种结构化语言,例如

  cmp r0, #0
  if(eq)
    mov r1, #0
  else
    add r1, #1
  end

The "if", "else", and "end" are calls to m4 macros I wrote that generate jumps and labels, the rest is native assembly. In order to nest these if/else/end constructs, you need to do defines within a macro.

“if”、“else”和“end”是对我编写的生成跳转和标签的 m4 宏的调用,其余的是本地程序集。为了嵌套这些 if/else/end 构造,您需要在宏中进行定义。