C++ faq 38.5 - macros with multiple statements

E

Erik Haugen

This item in the C++ faq:
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-38.5

discusses macros with multiple statements.

The problem is that a macro such as

#define MYMACRO(a,b) stmt1; stmt2;

will cause unwanted astonishment if you say:

while(whatever)
MYMACRO(foo,bar);


This is also problematic:

#define MYMACRO(a,b) {stmt1; stmt2;}

because this won't compile:
if(foo())
MYMACRO(i,j);
else
baz();

since you can't have "}; else"


so the faq proposes this solution:

-------------
#define MYMACRO(a, b) \
if (true) { \
statement1; \
statement2; \
... \
statementN; \
} else
-------------

But this seems like a bad solution; what if you write this:

MYMACRO(foo,bar) // note no semicolon
baz();

it compiles fine, but baz() *never* gets called!

Is there a way to avoid this? Maybe the do/while idiom should be used
dispite the inlining problems?

// compiler may not inline functions that use this because of the loop...
#define MYMACRO(a, b) \
do { \
statement1; \
statement2; \
... \
statementN; \
} while (false)

thanks,
Erik
 
D

David Fisher

Erik Haugen said:
This item in the C++ faq:
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-38.5

discusses macros with multiple statements.
[snip]

the faq proposes this solution:

-------------
#define MYMACRO(a, b) \
if (true) { \
statement1; \
statement2; \
... \
statementN; \
} else
-------------

But this seems like a bad solution; what if you write this:

MYMACRO(foo,bar) // note no semicolon
baz();

it compiles fine, but baz() *never* gets called!

Is there a way to avoid this? Maybe the do/while idiom should be used
dispite the inlining problems?

How about this:

#define MYMACRO(a, b) \
if (true) { \
statement1; \
statement2; \
} else true

This makes the null statement explicit, and should cause a syntax error if
no semi colon follows (if this looks weird to anyone, an expression that
does nothing like "true" or "1+3" is a valid statement in C++).

The following cases mentioned in the FAQ should work OK:

while (whatever)
MYMACRO(foo, bar);

if (whatever)
MYMACRO(foo, bar);
else
baz;

And there will be a (possibly obscure !) syntax error if the semi colon is
missing, as in your example:

MYMACRO(foo,bar) // note no semicolon
baz();

- because it will expand to "true baz()" at the end.

The reason for using "true" as the null statement and not "0" is because
there is less chance of the statement still being valid without a semi
colon, eg. something beginning with "-" or "*".

Hope this helps - let me know if I've missed something !

David F
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top