Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
513 views
in Technique[技术] by (71.8m points)

c preprocessor - How do I make a C++ macro behave like a function?

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. :)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There is a rather clever solution:

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

Now you have a single block-level statement, which must be followed by a semicolon. This behaves as expected and desired in all three examples.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...