使用(高阶)宏可以做多少事情?

发布于 2024-07-19 04:55:47 字数 934 浏览 5 评论 0原文

将宏名称作为其他宏的参数来模拟高阶函数是否“安全”?

即我应该注意哪里才不会搬起石头砸自己的脚?

以下是一些片段:

#define foreach_even(ii, instr) for(int ii = 0; ii < 100; ii += 2) { instr; }
#define foreach_odd(ii, instr)  for(int ii = 1; ii < 100; ii += 2) { instr; }

#define sum(foreach_loop, accu) \
  foreach_loop(ii, {accu += ii});

int acc = 0;
sum(foreach_even, acc);
sum(foreach_odd, acc);

部分应用怎么样,我可以这样做吗? :

#define foreach(ii, start, end, step, instr) \
  for(int ii = start; ii < end; ii += step) { instr; }

#define foreach_even(ii, instr) foreach(ii, 0, 100, instr)
#define foreach_odd(ii, instr)  foreach(ii, 1, 100, instr)

#define sum(foreach_loop, accu) \
  foreach_loop(ii, {accu += ii});

int acc = 0;
sum(foreach_even, acc);
sum(foreach_odd, acc);

我可以在宏中定义宏吗?

#define apply_first(new_macro, macro, arg) #define new_macro(x) macro(arg,x)

Is it "safe" to give macros names as arguments to other macros to simulate higher order functions?

I.e. where should I look to not shoot myself in the foot?

Here are some snippets:

#define foreach_even(ii, instr) for(int ii = 0; ii < 100; ii += 2) { instr; }
#define foreach_odd(ii, instr)  for(int ii = 1; ii < 100; ii += 2) { instr; }

#define sum(foreach_loop, accu) \
  foreach_loop(ii, {accu += ii});

int acc = 0;
sum(foreach_even, acc);
sum(foreach_odd, acc);

What about partial application, can I do that? :

#define foreach(ii, start, end, step, instr) \
  for(int ii = start; ii < end; ii += step) { instr; }

#define foreach_even(ii, instr) foreach(ii, 0, 100, instr)
#define foreach_odd(ii, instr)  foreach(ii, 1, 100, instr)

#define sum(foreach_loop, accu) \
  foreach_loop(ii, {accu += ii});

int acc = 0;
sum(foreach_even, acc);
sum(foreach_odd, acc);

And can I define a macro inside a macro?

#define apply_first(new_macro, macro, arg) #define new_macro(x) macro(arg,x)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

毅然前行 2024-07-26 04:55:47

如果您想尽可能多地使用预处理器,您可能需要尝试 boost.preprocessor

但请注意,这样做不安全。 例如,在使用预处理器时,逗号会导致大量问题。 不要忘记预处理器不理解(或者甚至尝试理解)它们生成的任何代码。

我的基本建议是“不要这样做”,或者“尽可能谨慎地做”。

If you're into using preprocessor as much as possible, you may want to try boost.preprocessor.

But be aware that it is not safe to do so. Commas, for instance, cause a great number of problems when using preprocessors. Don't forget that preprocessors do not understand (or even try to understand) any of the code they are generating.

My basic advice is "don't do it", or "do it as cautiously as possible".

嘴硬脾气大 2024-07-26 04:55:47

我完全在 c 预处理器中实现了一个烂的小单元测试框架。 几十个宏,很多宏是另一个宏类型的参数。

从最佳实践的意义上来说,这种事情是“安全”的。 有一些微妙且非常有力的方法会搬起石头砸自己的脚。 单元测试项目是一个失控的玩具。

不知道是否可以嵌套宏定义。 我对此表示怀疑,但我会尝试一下...gcc 不喜欢它,并回应

nested_macro.cc:8: 错误:程序中出现杂散“#”
nested_macro.cc:3: 错误: '(' 标记之前预期的构造函数、析构函数或类型转换
nested_macro.cc:3: 错误: '}' 标记之前的预期声明

自插件:如果您有兴趣,可以在 https://sourceforge.net/projects/dut/

I've implemented a rotten little unit testing framework entirely in c-preprocessor. Several dozen macro, lots of macro is an argument to another macro type stuff.

This kind of thing is not "safe" in a best-practices sense of the word. There are subtle and very powerful ways to shoot yourself in the foot. The unit testing project is a toy that got out of hand.

Don't know if you can nest macro definitions. I doubt it, but I'll go try...gcc doesn't like it, and responds with

nested_macro.cc:8: error: stray '#' in program
nested_macro.cc:3: error: expected constructor, destructor, or type conversion before '(' token
nested_macro.cc:3: error: expected declaration before '}' token

Self plug: If you're interested the unit testing framework can be found at https://sourceforge.net/projects/dut/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文