<p>All exception types that derive from boost::<spanclass="RenoLink"><ahref="exception.html">exception</a></span> can be used as type-safe containers of arbitrary data objects, while complying with the no-throw requirements (15.5.1) of the ANSI C++ standard for exception types. Data can be added to a boost::<spanclass="RenoLink"><ahref="exception.html">exception</a></span> at the time of the throw, or at a later time.</p>
<p>First, we instantiate the <spanclass="RenoLink"><ahref="error_info.html">error_info</a></span> template using a unique identifier -- tag_errno, and the type of the info it identifies -- int. This provides compile-time type safety for the various values stored in exception objects.</p>
<p>Second, we define class my_error, which derives from boost::<spanclass="RenoLink"><ahref="exception.html">exception</a></span>.</p>
<p>Finally, (3) illustrates how the typedef from (1) can be used with <spanclass="RenoLink"><ahref="operator_shl_exception.html">operator<<</a></span> to store values in exception objects at the point of the throw.</p>
<p>The stored errno value can be recovered at a later time like this:</p>
<p>The <spanclass="RenoLink"><ahref="get_error_info.html">get_error_info</a></span> function template is instantiated with the typedef from (1), and is passed an exception object of a polymorphic type. If the exception object contains the requested value, the returned <spanclass="RenoLink"><ahref="http://www.boost.org/libs/smart_ptr/shared_ptr.htm">shared_ptr</a></span> will point to it; otherwise an empty <spanclass="RenoLink"><ahref="http://www.boost.org/libs/smart_ptr/shared_ptr.htm">shared_ptr</a></span> is returned.</p>
<p>Sometimes the throw site does not have all the information that is needed at the catch site to make sense of what went wrong. Here is an example:</p>
<p>We have defined an exception class file_read_error which can store a file name, so that when we catch a file_read_error object, we know which file the failure is related to. However, the file_read function does not have the file name at the time of the throw; all it has is a FILE handle.</p>
<p>One possible solution is to not use FILE handles directly. We could have our own class file which stores both a FILE handle and a file name, and pass that to file_read. However, this could be problematic if we communicate with 3rd party code that does not use our class file (probably because they have their own similar class.)</p>
<p>A better solution is to make class file_read_error derive (possibly indirectly) from boost::<spanclass="RenoLink"><ahref="exception.html">exception</a></span>, and free the file_read function from the burden of storing the file name in exceptions it throws:</p>
<p>If file_read detects a failure, it throws an exception which contains the information that is available at the time, namely the errno. Other relevant information, such as the file name, can be added in a context higher up the call stack, where it is known naturally:</p>
<p>The above function is (almost) exception-neutral -- if an exception is emitted by any function call within the try block, parse_file does not need to do any real work, but it intercepts any boost::<spanclass="RenoLink"><ahref="exception.html">exception</a></span> object, stores the file name, and re-throws using a throw-expression with no operand (15.1.6). The rationale for catching any boost::<spanclass="RenoLink"><ahref="exception.html">exception</a></span> object is that the file name is relevant to any failure that occurs in parse_file, <i>even if the failure is unrelated to file I/O</i>.</p>
<p>As usual, the stored data can be retrieved using <spanclass="RenoLink"><ahref="get_error_info.html">get_error_info</a></span>.</p>
<p>The code snippet below demonstrates how boost::<spanclass="RenoLink"><ahref="http://www.boost.org/libs/tuple/doc/tuple_users_guide.html">tuple</a></span> can be used to bundle the name of the function that failed, together with the reported errno so that they can be added to exception objects more conveniently together:</p>
<p>Note that the members of a boost::<spanclass="RenoLink"><ahref="http://www.boost.org/libs/tuple/doc/tuple_users_guide.html">tuple</a></span> are stored separately in exception objects; they can only be retrieved individually, using <spanclass="RenoLink"><ahref="get_error_info.html">get_error_info</a></span>.</p>