0

Short story is that I want this behavior:

#if defined(DEBUG) || defined(_DEBUG)
#define CHECK_HRESULT(x)                                    \
{                                                           \
    HRESULT hr = (x);                                       \
    if (FAILED(hr))                                         \
    {                                                       \
        DXTrace(__FILE__, (DWORD)__LINE__, hr, L#x, true);  \
    }                                                       \
}
#else
#define CHECK_HRESULT(x)    (x)
#endif

but I also want to save and return the HRESULT value for error checking in free builds. So basically, I want to be able to do something like:

HRESULT hr = CHECK_HRESULT(Some_Function_Call());

which will assign a value to hr for both free and check builds, but will also display a dialog box when an invalid HRESULT is returned for check builds. Yes, I know I could create an inline function, but then I would have to pass in a string for L#x which means copying the statement twice in my code, which is something I would like to avoid (also, the same issue arises when you try to write a macro that just takes hr in as the input). I would also like to avoid something like:

#if defined(DEBUG) || defined(_DEBUG)
#define CHECK_HRESULT(x)    (x);                            \
{                                                           \
    HRESULT hr = (x);                                       \
    if (FAILED(hr))                                         \
    {                                                       \
        DXTrace(__FILE__, (DWORD)__LINE__, hr, L#x, true);  \
    }                                                       \
}
#else
#define CHECK_HRESULT(x)    (x)
#endif

since x could very easily be a function that allocates memory or does something important, and calling that function twice would cause severe unwanted behavior, especially between checked and free builds. Also, it almost goes without saying that I would like to avoid the assumption that there is already an HRESULT named hr... I've gone down that dark path before. I do realize that it would probably be safe to assign a value of S_OK by default in checked builds since the program will most likely crash anyway, but that just seems sloppy to me.

Anyway, thanks for ya'lls help!

Duncan
  • 980
  • 6
  • 17

2 Answers2

3

You may introduce helper function:

#if defined(DEBUG) || defined(_DEBUG)
inline static HRESULT _Do_CheckHResult(HRESULT hr, const wchar* text, const wchar* file, DWORD line)
{
    if (FAILED(hr))                                         
    {                                                       
        DXTrace(file, line, hr, text, true);  
    }   
    return hr;
}

#define CHECK_HRESULT(x) _Do_CheckHResult(x, L#x, __FILE__, (DWORD)__LINE__)
#else
#define CHECK_HRESULT(x)    (x)
#endif

(I wrote it from top of my head, it should probably work with copy-pasting, but I did not tested it).

nothrow
  • 15,882
  • 9
  • 57
  • 104
  • Hmm. I actually thought of something like this. I don't remember why I threw it out, but yours looks like it will work to me! – Duncan Dec 18 '12 at 18:06
0

gcc has an extension allowing full code blocks in expressions but I'm assuming you need this for VC++? In which case, could you define a macro "CHECK_ASSIGN_HRESULT(v,x)" that does the checks but also assigns the result to v?

DrC
  • 7,528
  • 1
  • 22
  • 37
  • Oh, silly me! I keep forgetting you can do assignment with macros. Awesome man, this is exactly what I was looking for! – Duncan Dec 18 '12 at 18:11