首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >宏元编程恐怖

宏元编程恐怖
EN

Stack Overflow用户
提问于 2013-04-14 06:48:29
回答 3查看 1.7K关注 0票数 0

我正在尝试做一些类似的事情:

代码语言:javascript
复制
custommacro x;

它将扩展为:

代码语言:javascript
复制
declareSomething; int x; declareOtherthing;

这有可能吗?

我已经用operator=欺骗过它一次,让它这样做,但它不能用声明完成。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-04-29 01:52:22

只要您愿意接受两个附加内容,您就可以省略括号:

  1. 整个代码需要包装在一个块宏中
  2. 在echo指令后面需要有一些东西

例如:

代码语言:javascript
复制
#define LPAREN (
#define echo ECHO_MACRO LPAREN
#define done )

#define ECHO_MACRO(X) std::cout << (X) << "\n"

#define DSL(X) X

...
DSL(
    echo "Look ma, no brains!" done;
)
...

原因:

  1. 在没有括号的情况下,无法使类似函数的宏展开。这只是宏语言的基本要求;如果你想研究不同的宏processor
  2. Therefore,,我们需要插入括号;反过来,我们需要在指令后面有一些东西,比如done宏,它将扩展为包含必要的关闭paren
  3. Unfortunately,的表单,因为echo ... done表单看起来不像是对预处理器的宏调用,当预处理器进入它时,它没有被标记为扩展,我们是否放入括号是无关紧要的。因此,仅使用echo ... done将在文本中转储ECHO_MACRO调用
  4. 文本被重新扫描,标记为展开,当它是类似函数的宏的参数时再次展开,因此使用块宏(此处为DSL)包装整个块将导致在这次重新扫描传递时扩展对ECHO_MACRO的调用(DSL不会对结果做任何操作:它的存在只是为了强制重新扫描)
  5. 我们需要在简单的宏< ( >d24echo >后面的展开中隐藏代码,因为否则宏主体中不匹配的圆括号将混淆preprocessor

如果您想为这些命令创建一种完整的特定于域的语言,您还可以通过使核心命令更加笨拙来减少done命令的数量:

代码语言:javascript
复制
#define LPAREN (

#define begin NO_OP LPAREN 0
#define done );

#define echo ); ECHO_MACRO LPAREN
#define write ); WRITE_MACRO LPAREN
#define add ); ADD_MACRO LPAREN
#define sub ); SUB_MACRO LPAREN

#define NO_OP(X) 
#define ECHO_MACRO(X) std::cout << (X) << "\n"
#define WRITE_MACRO(X) std::cout << (X)
#define ADD_MACRO(D, L, R) (D) = (L) + (R)
#define SUB_MACRO(D, L, R) (D) = (L) - (R)

#define DSL(X) DSL_2 X
#define DSL_2(X) X

int main(void) {
int a, b;
DSL((
    begin
      add a, 42, 47
      sub b, 64, 50
      write "a is:  "
      echo a
      write "b is:  "
      echo b
    done
))
return 0;
}

在这种形式下,每个命令都预先设计为关闭前面的命令,因此只有最后一个命令需要一个done;您需要一个begin行,以便第一个要关闭的实际操作有一个open命令,否则两个括号将不匹配。

在C中处理这样的事情要比在C++中容易得多,因为C的预处理器更强大(它支持__VA_ARGS__,这对于复杂的宏元编程非常重要)。

哦对了,还有一件事-

...please从不在真正的代码中做到这一点。

票数 6
EN

Stack Overflow用户

发布于 2013-04-14 21:02:41

我知道你想做什么,但这是不可能的。宏只是一个文本替换,它不知道它后面会发生什么,所以尝试做custommacro x将扩展到custommacro是什么,一个空格,然后是x,这在语义上是不起作用的。

另外,关于你的echo黑客:在C++中使用运算符实际上非常简单:

代码语言:javascript
复制
#include <iostream>

#define echo std::cout <<

int main()
{
    echo "Hello World!";
}

但是你真的不应该写这样的代码(也就是,使用宏和伪回显hack)。你应该编写符合语言语法和你想要做的事情的语义的代码。如果您想写入标准输出,请使用std::cout。此外,如果您想使用echo,可以创建一个名为echo的函数,该函数在内部调用std::cout,但不要修改该语言的特性来创建您自己的特性。

票数 2
EN

Stack Overflow用户

发布于 2015-08-21 13:00:37

您可以使用for-loop和GnuC语句表达式扩展。

代码语言:javascript
复制
#define MY_MACRO\
  FOR_MACRO(_uniq##__COUNTER__##name,{/*declareSomething*/ },{ /* declareOtherthing */ }) int

#define FOR_MACRO(NAME,FST_BLOCK,SND_BLOCK)\
  for(int NAME = ({FST_BLOCK ;0;}); NAME<1 ; NAME++,(SND_BLOCK))

这是“非常卫生的”,尽管这意味着无论您在这些代码块中做什么,都无法逃脱for-loop作用域的限制。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15993789

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档