<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.</p>
<p>When exceptions derive from boost::<spanclass="RenoLink"><ahref="exception.html">exception</a></span>, arbitrary data can be added to exception objects:</p>
<div><ul><li>At the point of the throw;</li>
<li>At a later time as exceptions bubble up the call stack.</li>
<p>First, we instantiate the <spanclass="RenoLink"><ahref="error_info.html">error_info</a></span> template using a unique identifier -- tag_my_info, 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>Finally, (3) illustrates how the typedef from (1) can be used with <spanclass="RenoLink"><ahref="exception_operator_shl.html">operator<<</a></span> to store values in exception objects at the point of the throw.</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, err will point to it; otherwise a null pointer 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. Let's say we have an exception type file_read_error, which takes a file name in its constructor. Consider the following function:</p>
<p>How can the file_read function pass a file name to the exception type constructor? All it has is a FILE handle.</p>
<p>Using boost::<spanclass="RenoLink"><ahref="exception.html">exception</a></span> allows us to 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>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>
See also: <spanclass="RenoPageList"><ahref="boost-exception.html">Boost Exception</a> | <ahref="tutorial_enable_error_info.html">Integrating Boost Exception in Existing Exception Class Hierarchies</a></span>