August 02, 2006
Mandatory Error Codes RevisitedThe Solution
If you want to use this kind of framework effectively, you first need to tweak it a bit.
First, change your assumption that an ErrorCode must be used. There is no real way to make sure that users actually used it. You should be more concerned with callers accepting the return code, rather than having them use it. After all, a caller to this kind of method can accept the error code, then assign it to some variable that is not used.
Second, make sure that implicitly thrown exceptions won't terminate the process. To do this, first add a new class, ThrowableErrorCode (Listing Two). This class is returned from methods that want to enforce error code checking, instead of the ErrorCode. ThrowableErrorCode doesn't grant access to the error code it carries.
template <class CODE> class ThrowableErrorCode
Listing Two
As its name implies, ThrowableErrorCode might throw an exception. In fact, it throws one when it goes out of scope. The only way to stop it from doing so is by either explicitly ignoring the error code using ThrowableErrorCode's operator IgnoreError, or by assigning it into an ErrorCode.
The new ErrorCode (Listing Three) does not throw an exception. It disarms ThrowableErrorCode and grants access to the error code.
template <class CODE>
class ErrorCode {
CODE code_;
public:
// Explicit ctor to make sure that the user of this
// class knows what she/he is doing
explicit ErrorCode(ThrowableErrorCode<CODE>& code):
code_(code.code_) {
// prevent the throw
code.throw_ = false;
}
operator CODE() {
return this->code_;
}
~ErrorCode()
{}
};
Listing Three
So the caller to this kind of method has these alternatives:
Example 3 shows how you can use this new framework. Now when you revisit the problem encountered in Example 2, the code works fine because ErrorCodes ec1 and ec2 disarm the ThrowableErrorCodes that return from the fallable methods. That is, in case of an exception from these methods, the code reaches the catch statement just as you intended.
// function declaration ThrowableErrorCode<int> FallableFunction();
Example 3: Example use of the new framework.
Acknowledgment
Thanks to Andrei Alexandrescu. DDJ
|
|
||||||||||||||||||||||||||||||
|
|
|
|