Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

C/C++

Mandatory Error Codes Revisited


Guy is chief architect of event processing for the Amdocs Billing Platform (http://www.amdocs.com). He can be contacted at [email protected].


In his article "Three Ideas" (http://www.ddj.com/dept/cpp/184401917), Andrei Alexandrescu described a framework for "mandatory error codes" that forces callers of a method to accept and use the returned error code. In this article, I refer to these codes as "forcing methods."

The idea is simple, yet powerful: A template class ErrorCode, which holds the real error code, is returned from a forcing method. When the returned ErrorCode goes out of scope, it throws an exception—unless the caller uses the error code (using the cast operator). The caller can explicitly ignore the error code by casting the ErrorCode with IgnoreError. Listing One presents the classes that make up this framework, while Example 1 shows how you can use it.



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 One

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

Example 1: Using the framework.

However, the problem with this framework is the exception that might be thrown at the destructor of ErrorCode. For instance, Example 2 looks perfectly normal. You don't ignore the returned error codes; you accept and use them. There's even a special recover method that can handle everything. Well, almost everything.

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 2: Problem code.

Here's the problem: If this->fallableMethod_2() throws, then the ec1 destructor is activated. But since no one has yet used ec1, another exception is thrown (from activating ec1's destructor), which terminates the process (set_terminate is called but this won't help). This is a big surprise if you've followed all the rules.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.