Introduction
It is boring to have to write a lot of if
s only to check for failures. At the same time, it is important to take care of every error that can happen in the code. The class described in this article just makes it easy to throw an exception every time a failure is returned from another function. This way you can do only what you have to do in the code and unify error handling.
With a little help from my colleagues from CP, here is an updated version with some traits for a no-throw version, and a new method to show a textual version for the HRESULT
error:
template<bool ThrowException>
struct HResultChecker
{
static void Check(HRESULT hr);
};
template<> struct HResultChecker<false>
{
static void Check(HRESULT hr)
{
hr;
}
};
template<> struct HResultChecker<true>
{
static void Check(HRESULT hr)
{
if( FAILED(hr) )
AtlThrow(hr);
}
};
template<bool ThrowException>
class HResultT
{
public:
HResultT(HRESULT hr = S_OK) { Assign(hr); }
HResultT &operator = (HRESULT hr)
{
Assign(hr);
return *this;
}
LPCTSTR ErrorMessage()
{
}
operator HRESULT () { return m_hr; }
private:
void Assign(HRESULT hr) {
HResultChecker<ThrowException>::Check(m_hr = hr);
}
HRESULT m_hr; std::basic_string<TCHAR> m_desc; };
typedef HResultT<true> HResult;
typedef HResultT<false> HResultSafe;
Using the code
The use is very straightforward. You can catch the exceptions inside the function or pass it to the callee:
void function()
{
HResult hr;
try
{
hr = MakeSomething();
hr = MakeSomethingElse();
hr = MakeTheFinalSomething();
}
catch(CAtlException& e)
{
cout << "wow! Error " << e.m_hr << ": " << e.ErrorMessage() << "\n";
}
}
void Class::Method() throw ( CAtlException )
{
HResult hr = MakeSomething();
hr = MakeSomethingElse();
hr = MakeTheFinalSomething();
}
Points of interest
Maybe before using the class above, you would to like to learn about CAtlException
, AtlThrow()
, and FormatMessage()
. Very interesting stuff for exception based error handling.