有没有办法在另一个#define中进行#define?

Vic*_*nin 47 c++ c-preprocessor

我知道我正试图在腿上射击自己;)然而,它将允许我使其余(大量)代码更小,更易读.

是否有任何棘手的方法在另一个预处理器宏内部创建预处理器宏?

这是一个例子,我在寻找什么.我的真实场景更复杂

// 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
}
Run Code Online (Sandbox Code Playgroud)

hka*_*ser 47

C++标准说(16.3.4.3):

由此产生的完全宏替换的预处理令牌序列[...宏扩展...的...]不会被处理为预处理指令,即使它类似于...

所以不,没有"官方"的方式来实现你想要的宏.


Jam*_*lis 15

不会.即使宏扩展为看起来像预处理指令的东西,扩展也不会被评估为预处理指令.


Jon*_*rdy 9

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

g++ -E input.cpp | g++ -c -x c++ - -o output.o
Run Code Online (Sandbox Code Playgroud)

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

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

在一个稍微相关的说明中,这让我想起了光线跟踪语言POV-Ray大量使用相当复杂的预处理语言这一事实​​,其中流控制指令#while允许条件重复,编译时计算和其他此类好处.在C++中是这样的,但事实并非如此,所以我们只是采用另一种方式.


Lau*_*ves 7

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


sup*_*cat 5

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

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


小智 5

看看m4。它与 cpp 类似,但递归且更强大。我使用 m4 为汇编器创建结构化语言,例如

  cmp r0, #0
  if(eq)
    mov r1, #0
  else
    add r1, #1
  end
Run Code Online (Sandbox Code Playgroud)

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