C++ faq 38.5 - macros with multiple statements

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Erik Haugen

    C++ faq 38.5 - macros with multiple statements

    This item in the C++ faq:


    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

  • David Fisher

    #2
    Re: C++ faq 38.5 - macros with multiple statements

    "Erik Haugen" <haugen@Xenon.S tanford.EDU> wrote:
    [color=blue]
    > This item in the C++ faq:
    > http://www.parashift.com/c++-faq-lit....html#faq-38.5
    >
    > discusses macros with multiple statements.[/color]

    [snip]
    [color=blue]
    > 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?[/color]

    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




    Comment

    Working...