C/C++ 宏展开与代码生成的区别

6
4个回答

9

对于C ++,我更喜欢使用模板元编程或代码生成而不是宏,但宏仍然有其用途。

您提供的dbtemplatelib示例可以使用C ++0x可变模板Variadic Templates来覆盖,还具有类型检查等其他优点。


谢谢您的建议。模板也有它们的优点。虽然可变参数宏已经存在,但可变参数模板由于C++0x仍然很新,尚未流行。 - Viet
准确地说,它甚至还没有发布,而且它将更像是一个“c++1x”。但是一些编译器已经实现了可变参数模板,例如,要在gcc中使用它们,您必须添加“-std=c++0x”作为编译器开关。 - Gunther Piez

5
在C或C++中,宏扩展是非常难以调试的。另一方面,编写代码生成器更容易调试,因为它本身是一个单独的程序。
然而,你应该意识到这只是C预处理器的限制。例如,在Lisp语言系列中,宏扩展就是代码生成,它们完全相同。要编写宏,你需要编写一个程序(用Lisp语言),将S表达式输入转换成另一个S表达式,然后传递给编译器。

感谢你的回复,Greg。编写一个好的代码生成器需要更多的时间,而宏似乎是快速完成任务的一种折中方案。 - Viet
++ 我完全同意。如果有一种方法可以逐步进行预处理,那就太好了。即便如此,如果代码生成足够简单,我更喜欢使用宏。 - Mike Dunlavey

3

两者都有其问题。与宏不同,代码生成可以产生可读和可调试的代码,但它的灵活性较差,更难更改。


2
这是一个权衡。让我举个例子。我在1985年左右偶然发现了差分执行技术,我认为它是编写用户界面的一种很好的工具。基本上,它采用简单的结构化程序,例如:
void Foo(..args..){
  x = y;
  if (..some test..){
    Bar(arg1, ...)
  }
  while(..another test..){
    ...
  }
  ...
}

“mucks” 是一个口语化的词汇,意思是“弄乱、捣乱”。因此,句子的大致意思是:“并且像这样搞乱控制结构:”。
void deFoo(..args..){
  if (mode & 1){x = y;}
  {int svmode = mode; if (deIf(..some test..)){
    deBar(((mode & 1) arg1 : 0), ...)
  } mode = svmode;}
  {int svmode = mode; while(deIf(..another test..)){
    ...
  } mode = svmode;}
  ...
}

现在,一个真正好的方法是编写 C 或任何基础语言的解析器,然后遍历解析树,生成我想要的代码。(当我用 Lisp 做时,这部分很容易。)
但是谁想写 C、C++ 或其他语言的解析器呢?
因此,我只需编写宏,以便可以像这样编写代码:
void deFoo(..args..){
  PROTECT(x = y);
  IF(..some test..)
    deBar(PROTECT(arg1), ...)
  END
  WHILE(..another test..)
    ...
  END
  ...
}

然而,在C#中这样做时,某些人认为宏是不好的,因此我不想编写C#解析器,所以我必须手动生成代码。这很麻烦,但与通常编写这些东西的方式相比仍然值得。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接