Mandatory Error Code Revisited
by Guy Peleg 


Example 1: Using the framework.

ErrorCode<int> FallableFunction();          // function declaration
ErrorCode<int> result = FallableFunction(); // ok
if (FallableFunction ()) {...}              // ok
FallableFunction();                         // will throw
(IgnoreError) FallableFunction();           // ok


Example 2: Problem code.

void AClass::someMethod() 
{
   try {
      ErrorCode<int> ec1 = this->fallableMethod_1();
      ErrorCode<int> ec2 = this->fallableMethod_2();
      if (ec1 && ec2) {
	  this->doSomething();
      }
   }
   catch (...) {
      this->recover();
   }
}


Example 3: Example use of the new framework.

// function declaration
ThrowableErrorCode<int> FallableFunction(); 	


// ok
ErrorCode<int> result = FallableFunction();
if (0 == result) {...}	

// will throw - but will not terminate the process
if (FallableFunction ()) {...} 				

// will throw - but will not terminate the process
FallableFunction(); 					

// ok - Explicitly ignoring the error code
(IgnoreError) FallableFunction(); 			

// might throw - the caller is taking a risk!
ThrowableErrorCode<int> mightThrow = FallableFunction(); 


Listing One

struct IgnoreError {};

template <class T>
class ErrorCode
{
    mutable bool    read_;
    T           code_;
public:
    ErrorCode(const T& code):
read_(false), code_(code) {
}
ErrorCode(const ErrorCode& rhs):
read_(rhs.read_), code_(rhs.code_) {
    rhs.read_ = true;
}
operator T() {
    // disarm exception
    this->read_ = true;
    return this->code_;
}
    operator IgnoreError()  {
    // disarm exception
    this->read_ = true;
    return IgnoreError();
}
~ErrorCode() {
    if (!this->read_)
    {
        throw MandatoryErrorCodeException(....);
    }
}
};


Listing Two

template <class CODE>
class ThrowableErrorCode

{
    template <class CODE> friend class ErrorCode;
    CODE        code_;
    bool        throw_;
public:
    /// ctor - receive the code and arm the exception
    ThrowableErrorCode(CODE i_code):
    code_(i_code),
    throw_(true)
    {}
    // explicitly ignore the error code and avoid exception
    operator IgnoreError() {
        this-> throw_ = false;
        return IgnoreError();
    }
    ~ThrowableErrorCode() {
        // will throw unless ErrorCode<CODE> or
                // IgnoreError will prevent it
        if (this-> throw_)
        {
            throw MandatoryErrorCodeException(...);
        }
    }
};


Listing Three

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()
    {}
};




3


