<html>

<head>
<meta http-equiv="Content-Language" content="en-us">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Cloning and Throwing Dynamically Typed Exceptions</title>
</head>

<body>

<p>Doc. no.&nbsp;&nbsp; N2229==07-0089<br>
Date:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2007-05-05<!--webbot bot="Timestamp" endspan i-checksum="12340" --><br>
Project:&nbsp;&nbsp;&nbsp;&nbsp; Programming Language C++<br>
Reply to:&nbsp;&nbsp; Beman Dawes &lt;<a href="mailto:bdawes@acm.org">bdawes@acm.org</a>&gt;</p>

<h1>Cloning and Throwing Dynamically Typed Exceptions (Rev 1)<br>
<font size="5">(Library-only support for exception propagation from threads)</font></h1>

<p><a href="#Preface">Preface</a><br>
<a href="#Introduction">Introduction</a><br>
<a href="#Proposed">Proposed changes to the working paper</a><br>
<a href="#Rationale-1">Rationale for mixin approach</a><br>
<a href="#Standard-1">Impact on the Standard</a><br>
<a href="#code-1">Impact on existing code</a><br>
<a href="#Implementation">Implementation experience using the proposed mixin</a><br>
<a href="#Acknowledgements">Acknowledgements</a><br>
<a href="#History">Revision history</a><br>
<a href="#Demonstration">Demonstration program</a>&nbsp;&nbsp;&nbsp; </p>

<h2><a name="Preface">Preface</a></h2>

<p>An alternate proposal,
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2179.html">
N2179</a>, <i>Language Support for Transporting Exceptions between Threads</i>, 
by Peter Dimov, was accepted in principle by the C++ Committee's Enhancements 
Working Group at the Oxford meeting. That proposal is considered superior to the 
pure-library approach presented here, so this proposal is of interest only if 
the N2179 proposal stalls.</p>

<h2><a name="Introduction">Introduction</a></h2>

<p>The underlying problem addressed in this proposal is a need to catch an 
exception by dynamic type (i.e. most-derived class), save it and later rethrow it, 
knowing only the static type (i.e. base class), and then finally to catch it 
again using the derived type.</p>

<p>Although this behavior might be useful elsewhere, it becomes a pressing need 
if exceptions are to be propagated from a thread-of-execution to a different 
thread.</p>

<p>Here is a non-threaded example of the problem, expressed in psuedo-C++:</p>

<blockquote>
  <pre>class B {
  /* ... */
  virtual ~B();
};

class D : public B {
  /*...*/
};

void f() { throw D(); }

int g()
{
  B * p = 0;

  try { 
    f();
  }

  catch ( const B &amp; ex ) {
    p = dynamic_new B(ex); // effectively: new D(ex)
  }

  // ...

  try {
    if ( p ) dynamic_throw p; // type thrown is D
  }

  catch ( const D &amp; ex ) {
    // we want this catch to be executed
  }
  catch ( const B &amp; ex ) {
    // we don't want this catch to be executed
  }
}</pre>
</blockquote>
<p>The above code will not currently work, because the language does not supply 
the <code>dynamic_new</code> and <code>dynamic_throw</code> or equivalent 
operators, and that is the heart of the problem addressed by this proposal.</p>

<p>This proposal does not require language or compiler support, and has been 
implemented in C++03. It allows exception propagation from threads under the 
current language rules, but is also useful outside a threading context.</p>

<p>An early version of this paper was discussed at the Redmond ad-hoc threads 
meeting in August, 2006. There 
was a strong consensus to go forward with a pure library-based approach to exception 
propagation from threads, while also pursuing solutions requiring core language 
or compiler support. Thus the pure-library approach would be available as a 
fallback if the core language or compiler support approaches ended up being 
unacceptable to the committee.</p>

<h2><a name="Proposed">Proposed</a> changes to the working paper</h2>

<p>In a header to be decided, add:</p>
<blockquote>
  <pre>namespace std
{
  class cloneable
  {
  public:
    typedef shared_ptr&lt;cloneable&gt; ptr_type;

    virtual ptr_type  dynamic_clone() const=0;
    virtual void      dynamic_throw() const=0;
    virtual          ~cloneable(){}
  };
}</pre>
  <p><b>Class <code>cloneable</code></b></p>
  <p>Class <code>cloneable</code> provides a mixin base class for objects that 
  need to clone  or throw themselves based on dynamic type.</p>
  <p><i>[Examples:</i></p>
  <pre>class my_exception : public std::exception
{
public:
  ptr_type dynamic_clone() const { return ptr_type(new my_exception(*this)); }
  void     dynamic_throw() const { throw *this; }

  // ...
};</pre>
</blockquote>
<blockquote>
  <pre>class non_std_exception : public virtual std::cloneable
{
public:
  ptr_type dynamic_clone() const { return ptr_type(new non_std_exception(*this)); }
  void     dynamic_throw() const { throw *this; }

  // ...
};</pre>
  <p><i>-- end examples]</i></p>
</blockquote>

<p>To 18.7.1, Class exception, change:</p>

<blockquote>

<p><code>class exception {</code></p>

</blockquote>

<p>to:</p>

<blockquote>

<p><code>class exception : public virtual cloneable {</code></p>

</blockquote>

<p>and add:</p>

  <blockquote>

  <pre>ptr_type dynamic_clone() const;</pre>
  <blockquote>
    <p><i>Returns:</i> <code>ptr_type(new exception(*this))</code></p>
  </blockquote>
  <pre>void dynamic_throw() const;</pre>
  <blockquote>
    <p><i>Effects: </i><code>throw *this</code></p>
  </blockquote>

</blockquote>

<h2><a name="Rationale-1">Rationale</a> for 
<a href="http://en.wikipedia.org/wiki/Mixin">mixin</a> approach</h2>

<p>Users will need to write catch clauses for specific exception classes, both 
Standard Library and user-defined. To implement this behavior, it must be 
possible save and re-throw exceptions without knowing anything more than their 
base class. The <code>dynamic_clone</code> and <code>dynamic_throw</code> functions 
make this possible. Using a mixin base class allows use in user-defined exception types, 
whether or not they are derived from <code>std::exception</code>.</p>

<h2>Impact on the <a name="Standard-1">Standard</a></h2>

<p>This is a pure library proposal. It can be portably 
implemented with any C++03 compiler. It's impact on the standard is limited to 
the change to <code>std::exception</code>.</p>

<h2>Impact on existing <a name="code-1">code</a></h2>

<p>No practical impact foreseen. It is remotely possible that some existing code 
somehow depends on std::exception having no base class, but that seems pretty 
unlikely.</p>

<h2><a name="Implementation">Implementation</a> experience using the proposed 
mixin</h2>

<p>The proposal has been implemented and tested, both in an multi-threading 
environment using Boost.Threads, and in a non-multithreading environment. No 
problems were encountered in either environment, and exceptions of the desired 
type were successfully propagated.</p>

<h2><a name="Acknowledgements">Acknowledgements</a></h2>

<p>Alisdair Meredith suggested the mixin approach rather than adding the 
functionality directly to <code>std::exception</code>, and 
also provided an 
alternative approach that did not require changes to exception classes (but did 
require changes to code that throws exceptions.) Peter Dimov and Howard Hinnant 
provided helpful comments to the original paper.</p>

<h2>Revision <a name="History">history</a></h2>

<p>N2229, <i>Cloning and Throwing Dynamically Typed Exceptions 
(Rev 1)</i>, removed option 2, which required compiler support, and 
further refined the library-only solution to the problem.</p>

<p><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2106.html">
N2106</a>, <i>Cloning and Throwing Dynamically Typed Exceptions</i>, was a major revision of
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2061.html">
N2061</a>, <i>Library Exception Propagation Support</i>.</p>

<h2><a name="Demonstration">Demonstration</a> program</h2>

<pre>// cloneable demonstation ----------------------------------------------- //

#include &lt;boost/shared_ptr.hpp&gt;
#include &lt;string&gt;
#include &lt;cassert&gt;
#include &lt;iostream&gt;

// ---------------------------------------------------------------------- //

// this would normally be in a header file:

class cloneable
{
public:
  typedef boost::shared_ptr&lt;cloneable&gt; ptr_type;
  virtual ptr_type      dynamic_clone() const=0;
  virtual void          dynamic_throw() const=0;
  virtual              ~cloneable(){}
};

// ---------------------------------------------------------------------- //

// this is a user-defined cloneable type:

class my_type : public virtual cloneable
{
public:
  my_type(const std::string&amp; what_) : _what_(what_) {}

  ptr_type dynamic_clone() const { return ptr_type(new my_type(*this)); }

  void dynamic_throw() const { throw *this; }

  const std::string&amp; what() const { return _what_; }

private:
  std::string _what_;
};

// ---------------------------------------------------------------------- //

int main()
{
  cloneable::ptr_type p;

  try { throw my_type(&quot;bingo!&quot;); }

  catch (const cloneable &amp; ex) {
    p = ex.dynamic_clone(); // save a copy of the exception
  }

  // ...

  try { p-&gt;dynamic_throw(); } // rethrow the saved copy

  catch (const my_type&amp; ex) { // this block should be entered
    assert(ex.what()==&quot;bingo!&quot;);
    std::cout &lt;&lt; ex.what() &lt;&lt; '\n';
  }

  // if the dynamic type was not propagated correctly, this
  // catch block would be entered and the assert would fire
  catch (...) { assert(false); }

  return 0;
}</pre>
<hr>
<p> Copyright Beman Dawes 2006, 2007</p>

</body>

</html>