Skip to main content
gamedev.net
🔒 Locked

Contradiction !! Macro ?? Function ??

Started by Aludirk Sep 26, 2006 at 4:16 AM 10 replies 1.8k views
Original Post
Aludirk
Aludirk
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.
davepermen
davepermen
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
If that's not the help you're after then you're going to have to explain the problem better than what you have. - joanusdmentia
My Page davepermen.net | My Music on Bandcamp and on Soundcloud
Deyja
Deyja
What's the do ... while(0) for? Perhaps you did not know you could use { ... } without a control statement?
Kylotan
Kylotan
It's common in macros; I can't remember why it gets used but I think it prevents obscure bugs that arise when you place the macro in certain contexts. Sorry to not be more specific.
Deyja
Deyja
Uhuh. I know. It's pointless. Just use {} around it. No need for a control statement at all.
ajones
ajones
You're almost there... use an inline function/macro combination:

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]
Aludirk
Aludirk
OH.. Thank you very much
That's really helpful :-D
Zahlman
Zahlman
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).
owl
owl
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.
[size="2"]I like the Walrus best.
Deyja
Deyja
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.
Brother Bob
Brother Bob
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.