如何使C ++宏表现得像一个函数? [英] How do I make a C++ macro behave like a function?

查看:133
本文介绍了如何使C ++宏表现得像一个函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们说,由于某种原因,你需要写一个宏: MACRO(X,Y)(假设有一个很好的理由不能使用内联函数。)您希望此宏模拟对没有返回值的函数的调用。






示例1:这应该能正常工作。



  if(x> y)
MACRO(x,y);
do_something();



示例2:这不应导致编译器错误。



  if(x> y)
MACRO(x,y);
else
MACRO(y - x,x - y);



示例3:这不应该编译。



  do_something(); 
MACRO(x,y)
do_something();




写宏的方式如下:

  #define MACRO(X,Y)\ 
cout< < 第一个arg是:< (X) endl; \
cout<< 第二个arg是:< (Y) endl; \
cout<< Sum is:< ((X)+(Y))< endl;

这是一个非常糟糕的解决方案,失败了所有三个例子,我不需要解释为什么



忽略宏的实际功能,



现在,我最常看到写的宏是用大括号括起来的,如下:

  #define MACRO(X,Y)\ 
{\
cout< 第一个arg是:< (X) endl; \
cout<< 第二个arg是:< (Y) endl; \
cout<< Sum is:< ((X)+(Y))< endl; \
}

这解决了示例1,因为宏是在一个语句块中。但是示例2被打破,因为我们在调用宏之后放了一个分号。这使得编译器认为分号本身是一个语句,这意味着else语句不对应任何if语句!最后,示例3编译为OK,即使没有分号,因为代码块不需要分号。






有没有办法写一个宏,以便它通过所有三个例子?






注意:我正在提交自己的答案作为接受的方式共享一个提示,但如果任何人有一个更好的解决方案,感到自由地张贴在这里,它可能会获得比我的方法更多的投票。 :)

解决方案

通常应避免宏;在任何时候都喜欢内联函数给他们。任何有价值的编译器都应该能够内联一个小函数,就像它是一个宏,内联函数将会尊重命名空间和其他范围,以及一次评估所有的参数。



如果它必须是一个宏,一个while循环(已经建议)将工作,或者你可以尝试逗号运算符:

  #define MACRO(X,Y)\ 
(\
(cout <1st arg is:<<(X)< ,\
(cout <<2nd arg is:<<(Y)<< endl),\
(cout< <((X)+(Y))< - endl),\
(void)0 \

/ pre>

(void)0 使语句评估为 void 类型,使用逗号而不是分号允许它在语句内部使用,而不是作为独立的。我仍然推荐一个内联函数的主要原因,其中最小的范围和事实, MACRO(a ++,b ++)会增加 a b 两次。


Let's say that for some reason you need to write a macro: MACRO(X,Y). (Let's assume there's a good reason you can't use an inline function.) You want this macro to emulate a call to a function with no return value.


Example 1: This should work as expected.

if (x > y)
  MACRO(x, y);
do_something();

Example 2: This should not result in a compiler error.

if (x > y)
  MACRO(x, y);
else
  MACRO(y - x, x - y);

Example 3: This should not compile.

do_something();
MACRO(x, y)
do_something();


The naïve way to write the macro is like this:

#define MACRO(X,Y)                       \
cout << "1st arg is:" << (X) << endl;    \
cout << "2nd arg is:" << (Y) << endl;    \
cout << "Sum is:" << ((X)+(Y)) << endl;

This is a very bad solution which fails all three examples, and I shouldn't need to explain why.

Ignore what the macro actually does, that's not the point.


Now, the way I most often see macros written is to enclose them in curly braces, like this:

#define MACRO(X,Y)                         \
{                                          \
  cout << "1st arg is:" << (X) << endl;    \
  cout << "2nd arg is:" << (Y) << endl;    \
  cout << "Sum is:" << ((X)+(Y)) << endl;  \
}

This solves example 1, because the macro is in one statement block. But example 2 is broken because we put a semicolon after the call to the macro. This makes the compiler think the semicolon is a statement by itself, which means the else statement doesn't correspond to any if statement! And lastly, example 3 compiles OK, even though there is no semicolon, because a code block doesn't need a semicolon.


Is there a way to write a macro so that it pass all three examples?


Note: I am submitting my own answer as part of the accepted way of sharing a tip, but if anyone has a better solution feel free to post it here, it may get more votes than my method. :)

解决方案

Macros should generally be avoided; prefer inline functions to them at all times. Any compiler worth its salt should be capable of inlining a small function as if it were a macro, and an inline function will respect namespaces and other scopes, as well as evaluating all the arguments once.

If it must be a macro, a while loop (already suggested) will work, or you can try the comma operator:

#define MACRO(X,Y) \
 ( \
  (cout << "1st arg is:" << (X) << endl), \
  (cout << "2nd arg is:" << (Y) << endl), \
  (cout << "3rd arg is:" << ((X) + (Y)) << endl), \
  (void)0 \
 )

The (void)0 causes the statement to evaluate to one of void type, and the use of commas rather than semicolons allows it to be used inside a statement, rather than only as a standalone. I would still recommend an inline function for a host of reasons, the least of which being scope and the fact that MACRO(a++, b++) will increment a and b twice.

这篇关于如何使C ++宏表现得像一个函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆