We have a large code base with a lot of code which does this kind of thing:
bool DoSomething(CString Value)
{
if(Value == "bad")
{
AfxMessageBox("description of error");
return false;
}
return true;
}
or even just this:
bool DoSomething(CString Value)
{
if(Value == "bad")
{
return false;
}
return true;
}
We have considered various alternatives:
So I wondered if we could create a set of classes like the following:
class CResult
{
protected:
CResult()
{
// Don't have to initialize because the derived class will do it
}
public:
operator bool() { return m_Result; };
bool m_Result;
CString m_Message;
};
class CSuccess : public CResult
{
public:
CSuccess()
{
m_Result = true;
}
};
class CFailure : public CResult
{
public:
CFailure(const CString & Message)
{
m_Result = false;
m_Message = Message;
}
};
Then the above code could look like this:
CResult DoSomething(CString Value)
{
if(Value == "bad")
{
return CFailure("description of error");
}
return CSuccess();
}
What I like about it:
The main drawback I see is that there is higher overhead on success, in that an object and a string and a bool will all be instantiated - but a lot of the times in our app the code in question is not performance sensitive, such as validating user input, etc.
Am I missing some other big drawback? Is there an even better solution?
It can be useful to separate "errors" in two categories:
Fatal errors
These are the kind of errors from which a recovery make no sense.
void check(bool cond, const string& msg)
{
if (!cond)
{
// eventually log it somewhere
std::cerr << "Fatal: " << msg << std::endl;
exit(1);
}
}
Exceptional errors
These are the kind of errors that you can recover from and keep the program in a running state.
void check_ex(bool cond, const string& msg)
{
if (!cond)
{
// eventually log it somewhere
throw std::runtime_error(msg);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With