-1

The code is below. The compiler says "Expected a )", but I do not get it: ( and ) are matching. What did I do wrong?

enter image description here

#define CR_SUCCESS 0

#define EXIT_IF_FAILS(varResult, callString) \
    (\
        varResult = callString; \
        if(varResult != CR_SUCCESS) \
        { \
            return -1; \
        } \
    )

int testFunction(int a, int b)
{
    return -1;
}

int main()
{
    int result;
    EXIT_IF_FAILS(result, testFunction(1, 2));

}
Damn Vegetables
  • 11,484
  • 13
  • 80
  • 135
  • 3
    Macros aren't functions, they aren't called but rather substituted as text. Is the substituted `( ... = ... ; if(...) {...} )` valid **as code**? – StoryTeller - Unslander Monica Oct 01 '21 at 23:50
  • 4
    Did you mean to put that code block inside curly braces `{}` instead of parentheses `()`?? – πάντα ῥεῖ Oct 01 '21 at 23:51
  • When I searched for macro function examples, all the multi-line examples were enclosing the body with ( and ), so I thought that the parentheses were a part of the macro syntax. It seems that my assumption was wrong; I removed the parentheses, and it was compiled. – Damn Vegetables Oct 01 '21 at 23:53
  • @KenWhite I count three closing parentheses in the expanded version. One after `(1, 2)`, one after `!= 0)`, and one after `{return -1; } )`. – Nathan Pierson Oct 01 '21 at 23:54
  • 3
    Damn sweet of the IDE to show the expanded version. Why when I was a kid we got *Syntax error on line 6694*. And the program only had, say, 30 lines. Kids got it easy these days. – user4581301 Oct 01 '21 at 23:54
  • 1
    I suspect the examples you found were either (a) plain (complex) expressions with no statements, or (b) using the GNU extension `({ ... })`. Either way, the macro here is not an improvement. It saves on typing, not on mental complexity. – StoryTeller - Unslander Monica Oct 01 '21 at 23:56
  • @NathanPierson: You're right. Old eyes and the lack of contrast in the expanded text is where I'm assigning the blame. :-) Well, that and the fact that fonts aren't scaled in images, no matter what size you have text in your browser. – Ken White Oct 01 '21 at 23:56
  • 2
    As an aside, there's little reason to use function-like macros in modern C++. You should prefer inline functions (or even just functions, letting the optimising compiler figure out what's best). Especially in a case where you save no lines whatsoever: `if ((result = testFunction(1, 2)) != CR_SUCCESS) return -1;` – paxdiablo Oct 01 '21 at 23:58
  • @paxdiablo But I want to exit the function with that macro. If I use an actual function, how can I exit the caller from the function? Unless I check the result of the function and exists in the caller, which defeats the purpose of the function. – Damn Vegetables Oct 02 '21 at 00:01
  • 1
    @DamnVegetables One option would be throwing an exception. This will exit the surrounding function, unless it explicitly decides to handle the exception. – Yksisarvinen Oct 02 '21 at 00:02
  • 1
    @KenWhite "Lack of contrast" is a general problem I encounter in numerous current applications in "Dark Theme". For some reason, the developers mostly use light-grey text on grey background, like Android Studio, Visual Studio, Blender, etc, and it lacks contrast, making it difficult to read the text. That sucks. I could change the background of VS's text editor to pure black, but I forgot (or it is impossible) to change the background colour of the pop-up. – Damn Vegetables Oct 02 '21 at 00:05
  • @user4581301 I am using VS 2022 preview 4, and it has the A.I. code assisting which predicts (at least in C#) the line (not just a variable, but the whole line of code) I was trying to type and it is great. – Damn Vegetables Oct 02 '21 at 00:11
  • @DamnVegetables: for this particular use case, yes, inline functions are inappropriate. I probably should have clarified that (which I'm doing now). That's why I also gave the one-line code snippet which makes the whole macro unnecessary. – paxdiablo Oct 02 '21 at 00:37
  • Sadly I work in a slow-moving environment. By the time I get to upgrade from VS2010 I'll probably be in a museum exhibit featuring fossils of Ancient Man from the Silicon Ages. – user4581301 Oct 02 '21 at 00:51
  • @paxdiablo Actually, that was not the whole code of the macro function. I removed some of the lines to make it easier to figure out the error, in actual code, there were lines to print the error before exiting. – Damn Vegetables Oct 02 '21 at 05:48

2 Answers2

4

Expanding, your main looks like

int main()
{
    int result;
    (
        result = testFunction(1, 2);
        if(result != CR_SUCCESS)
        {
            return -1;
        }
    )
}

This is invalid, since you cannot have parentheses around statements.

For some things you might do when you want a macro which acts like a statement, see the C++ FAQ "What should be done with macros that have multiple lines?"

aschepler
  • 70,891
  • 9
  • 107
  • 161
0

You should, as a general rule, avoid function-like macros as much as possible, there's very little need to use them in modern C++(a). Most can be easily replaced with inline functions, or even non-inline functions if you trust the compiler to do the right thing.

I realise that's not appropriate for your specific use case since you need to exit the current function as part of the macro but I would ask you to think about why you think you need a macro for this case in the first place.

If it's to simply cut down on code lines, you can equally do that without a macro, such as with:

if ((result = testFunction(1, 2)) != CR_SUCCESS) return -1;

That's equally as succinct (in terms of line count) and doesn't require you to go looking for the macro definition to see what's actually happening.

It also doesn't need all the normal faffing about trying to make sure your macros work in all places where they may be used, such as needing to use the do { ... } while (0) trick to ensure it works inside if or else blocks without braces. See this question and its answers for more explanation on that point.


(a) In fact, even non-function-like macros may be better replaced with enumerations (at least those such as a set of mutually exclusive value like error codes). Nowadays, I tend to use #define only for conditional compilation, on those relatively rare occasions where I need it.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953