Hi there,

I've decided upon getting better clued up on an area of my textbook I'm reading that I haven't properly understood yet. It's about exception handling. Not wanting to just dump a load of questions on the forum, I've done some research (and some code staring - which seems is one of my favourite methods of learning! )

Anyways...the DirectX book I'm reading puts a lot of stuff into classes. Including the code required to register and create a window. It also puts some fundamental DirectX code initialisation in there as well. In fact the main message loop itself is hosted inside a class function. Here's the part in question:

Code:
try
{
    BoxApp theApp(hInstance);
    if(!theApp.Initialize())
        return 0;

    return theApp.Run();
}
catch(DxException& e)
{
    MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
    return 0;
}
BoxApp inherits from class D3DApp which has the most generic functions in it which can be over-ridden by child classes for specific demo's in the book. Quite a clever design. The part we're interested in, in the above code is:

Code:
if(!theApp.Initialize())
Checking the function in BoxApp:

Code:
bool BoxApp::Initialize()
{
    if(!D3DApp::Initialize())
		return false;

.... code continues
So the child class calls the Initialise function in the parent class.

Code:
bool D3DApp::Initialize()
{
	if(!InitMainWindow())
		return false;

	if(!InitDirect3D())
		return false;

.... code continues
The interesting part here is in the InitDirect3D() function as this is where the macros are that cause a throw statement to occur. So in the try catch block above, this function is ultimately (once eventually called) the one that contains the throw statements. Here's an example of the macro:

Code:
bool D3DApp::InitDirect3D()
{
#if defined(DEBUG) || defined(_DEBUG) 
	// Enable the D3D12 debug layer.
{
	ComPtr<ID3D12Debug> debugController;
	ThrowIfFailed(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)));
	debugController->EnableDebugLayer();
}

.... code continues
Now the ThrowIfFailed macro:

Code:
#ifndef ThrowIfFailed
#define ThrowIfFailed(x)                                              \
{                                                                     \
    HRESULT hr__ = (x);                                               \
    std::wstring wfn = AnsiToWString(__FILE__);                       \
    if(FAILED(hr__)) { throw DxException(hr__, L#x, wfn, __LINE__); } \
}
#endif
I've put the throw statement in bold. Finally here's the user made class that the throw statement raises when the HRESULT is in failure:

Code:
class DxException
{
public:
    DxException() = default;
    DxException(HRESULT hr, const std::wstring& functionName, const std::wstring& filename, int lineNumber);

    std::wstring ToString()const;

    HRESULT ErrorCode = S_OK;
    std::wstring FunctionName;
    std::wstring Filename;
    int LineNumber = -1;
};
And its constructor (which you can see is called in the ThrowIfFailed macro)

Code:
DxException::DxException(HRESULT hr, const std::wstring& functionName, const std::wstring& filename, int lineNumber) :
    ErrorCode(hr),
    FunctionName(functionName),
    Filename(filename),
    LineNumber(lineNumber)
{
}
So an initialisation list essentially.

So... if I've got this right, the try catch block will experience a throw event if a function returns a HRESULT as a fail. That fail is buried rather deeply in the function calls of the child and parent classes. When the ThrowIfFailed macro activates in the InitDirect3D() function it creates a wstring variable of name wfn (probably means wide file name) using the function AnsiToWString():

Code:
inline std::wstring AnsiToWString(const std::string& str)
{
    WCHAR buffer[512];
    MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, buffer, 512);
    return std::wstring(buffer);
}
And then calls the class DxException constructor like so:

Code:
throw DxException(hr__, L#x, wfn, __LINE__);
So now as a result of the throw statement nested within the function calls (provided a function call fails) there is now a class of type DxException created where the throw statement has called its constructor and initialised its data members with the HRESULT, the function name (apprently that's what the L#x trickery is for), file name and line number.

Now in the catch statement the class type is recognised (as its the same as the one from the throw statement) which then does the following:

Code:
catch(DxException& e)
{
    MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
    return 0;
}
Noting that the DxException member function is defined as follows:

Code:
std::wstring DxException::ToString()const
{
    // Get the string description of the error code.
    _com_error err(ErrorCode);
    std::wstring msg = err.ErrorMessage();

    return FunctionName + L" failed in " + Filename + L"; line " +
    std::to_wstring(LineNumber) + L"; error: " + msg;
}
Which creates an object of type _com_error (not user defined) which has a member function in it that can retrieve an error message associated with the HRESULT ErrorCode the object was created with.

Finally this ToString() function bundles up the retrieved error message with all the DxException class data members (which have now been filled out with relevant data) into one large wstring which it returns and is then passed into a message box as shown above, here again below as a reminder:

Code:
MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
My real question is have I understood that properly? And how exactly does the L#x part retrieve a function name, and do I need to be concerned much with the __FILE__ and __LINE__ macros or should I just accept they retrieve a file name and line number?

Thanks