🔒 Locked
Contradiction !! Macro ?? Function ??
Advertisement
Original Post
Hi All, I'm writing some DirectX application, and everytime I'm using DirectX functions, I'll do some simple error checking as below: HRESULT hr; hr = /* Some DirectX function */ ; if(FAILED(DXTrace(__FILE__, __LINE__, hr, DXGetErrorDescription(hr), FALSE))) { /* Error handling */ } Therefore, I wanna make a simple macro to simplify it and i write something like this in a common header file in the whole project: #define DXERR(x) DXTrace(__FILE__, __LINE__, x, DXGetErrorDescription(x), FALSE) so that I can call it by just: if(FAILED(DXERR( /* DirectX functions */ ))) { /* Error handling */ } However, I found that it will call the function twice everytime I call the macro. And then I try to replace it with an inline function: inline HRESULT DXErr(HRESULT hr) { return DXTrace(__FILE__, __LINE__, hr, DXGetErrorDescription(hr), FALSE); } This one solves the problem for calling twice of the function but the __FILE__ and __LINE__ now give me the position of the inline function instead of my caller function. Although I can totally solve it by: inline HRESULT DXErr(CHAR *strFile, DWORD dwline, HRESULT hr) { return DXTracestrFile, dwline, hr, DXGetErrorDescription(hr), FALSE); } I wanna keep the function in the most simple form, otherwise I don't need to writing anything about this everywhere simple error checking function. Thanks a lot.
something like
#define DXERR(x) do { DWORD hr = x; DXTrace(__FILE__, __LINE__, hr, DXGetErrorDescription(hr), FALSE) } while(0)
wouldn't work? (you couldn't have DXERR in an if(statement), then.. but you could set up, possibly, another one, just for this..)
hm.. long time since my last c++ :D
#define DXERR(x) do { DWORD hr = x; DXTrace(__FILE__, __LINE__, hr, DXGetErrorDescription(hr), FALSE) } while(0)
wouldn't work? (you couldn't have DXERR in an if(statement), then.. but you could set up, possibly, another one, just for this..)
hm.. long time since my last c++ :D
No, it is not pointless. In fact, omitting a safety wrapper on a multi-line macro is begging for obscure bugs.
Arguably, using preprocessor macros is begging for obscure bugs, but hey [wink]
Arguably, using preprocessor macros is begging for obscure bugs, but hey [wink]
You're almost there... use an inline function/macro combination:
Then you can do what you wanted in your code:
Hope this helps. [smile]
inline HRESULT DXErrHelper(CHAR* strFile, DWORD dwline, HRESULT hr){ return DXTracestrFile(dwline,hr,DXGetErrorDescription(hr),FALSE);}#define DXERR(x) DXErrHelper(__FILE__, __LINE__, x)Then you can do what you wanted in your code:
if(FAILED(DXERR( /* DirectX functions */ ))){/* Error handling */}Hope this helps. [smile]
Yep. The general principle is to keep macros as simple as possible, and use them for the part of the process that you can't do properly otherwise - typically this means making it just a wrapper around a usage of __FILE__ and/or __LINE__ (and/or __FUNCTION__/__PRETTY_FUNCTION__ depending on your compiler).
Quote:
Original post by ApochPiQ
No, it is not pointless. In fact, omitting a safety wrapper on a multi-line macro is begging for obscure bugs.
Arguably, using preprocessor macros is begging for obscure bugs, but hey [wink]
That's really a nasty patch! Another reason to avoid using macros. I'm amazed that I never went trough this problem.
Quote:
No, it is not pointless. In fact, omitting a safety wrapper on a multi-line macro is begging for obscure bugs.
Interesting. I'd never considered what a semi-colon there could do. Partly because, when I saw the error, I'd just delete the semi colon, but mostly because I'd write a function instead.
I personally like the if(true) variation proposed by the C++ Faq lite. However, I would just include a semi-colon after the else right in the macro. That way, it compiles corectly wether client code includes the semi-colon or not.
Quote:
Original post by Deyja
I personally like the if(true) variation proposed by the C++ Faq lite. However, I would just include a semi-colon after the else right in the macro. That way, it compiles corectly wether client code includes the semi-colon or not.
That's just as dangerous as just using a block as you first suggested.
if(true) if(false) MYMACRO(0, 0) else cout << "foo" << endl;else cout << "bar" << endl;This will work as "expected"; it will print foo. Put a semicolon after the macro, and the first semicolon (the one in the macro) will end the if-statement in the macro, but the second one will end the if-statement in the code. You will get errors about else-statements without if-statements.
Extra semicolons are not always redundant.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement