Paul Knopf
Paul Knopf

Reputation: 9786

VC C++ macro parameters getting executed/evaluated each time used in macro

I have a macro that checks an error state. If there is an error, it logs the result and returns out of the method.

CHECKHR_FAILED_RETURN(hr) if(FAILED(hr)){LOGHR_ERROR(hr); return hr;}

The macro is called like this:

CHECKHR_FAILED_RETURN(_recordingGraph->StopRecording(&currentFile));

However, if the result has indeed FAILED(hr), the method is executed again to perform the LOGHR_ERROR(hr). I see why my StopRecording is getting called twice in case of an error, so my question is...

How do you evaluate the result of a parameter in a macro, but use it multiple times within the same macro?

UPDATE:

Based on suggestions below, I changed my macros to the following.

#define CHECKHR_FAILED_RETURN(hr) do { \
    HRESULT result = hr; \
    if(FAILED(result)) \
    { \
        LOGHR_ERROR(result); \
        return result; \
    } \
} while (false);

#define CHECKHR_FAILED(hr) do { \
    HRESULT result = hr; \
    if(FAILED(result)) \
    { \
        LOGHR_ERROR(result); \
        return true; \
    } \
    else \
    { \
        return false; \
    } \
} while (false);

Upvotes: 1

Views: 130

Answers (1)

Mark Ransom
Mark Ransom

Reputation: 308392

As one commenter says, prefer a function to a macro in every place where it's possible. In this case it's not possible, since you want to embed a return into the code.

You can do an assignment to a temporary variable within the macro and use it instead of calling the parameter multiple times.

#define CHECKHR_FAILED_RETURN(hr) do{ HRESULT hr2=hr; if(FAILED(hr2)) {LOGHR_ERROR(hr2); return hr2; }}while(false)

The do loop is an idiom ensuring that the macro can be used in an if-else just like a function call. With C++11 and onwards you can alternatively use a lambda expression.

Upvotes: 1

Related Questions