<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>TR2 Diagnostics Enhancements</title>
</head>

<body>

<p>Doc. no.&nbsp;&nbsp; WG21/N2066=06-0136<br>
Date:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%Y-%m-%d" startspan -->2006-09-07<!--webbot bot="Timestamp" endspan i-checksum="12592" --><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>TR2 Diagnostics Enhancements</h1>
<h2>Introduction</h2>
<p><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1975.html">
N1975</a> Filesystem Library Proposal for TR2, accepted for Library Technical 
Report 2 (TR2) at the Berlin meeting, included additional components to 
supplement the Standard Library's Diagnostics clause. Since then, these error 
reporting components have received wider public scrutiny and enhancements have 
been made to the design. The enhanced version has been used by N2054, Networking 
Library Proposal for TR2, demonstrating that these error reporting components 
are in fact useful beyond of the original Filesystem Library.</p>
<p>The enhancements fall into two areas:</p>
<ul>
  <li>Minor interface tweaks to improve usability and simpify the interface.<br>
&nbsp;</li>
  <li>A new ability to handle additional error categories, including user-defined 
  categories.</li>
</ul>
<p>The original proposal viewed error categories as a binary choice between
<code>errno</code> (i.e. POSIX-style) and the native operating system's error 
codes. The enhancements proposed here allow as many additional error categories 
as are needed by either implementations or by users. The need to support 
additional error categories, for example, occurs in some networking library 
implementations because they are built on top of the POSIX <code>getaddrinfo</code> API that uses error codes 
not based on <code>errno</code>.</p>
  <h2><a name="Acknowledgements">Acknowledgements</a></h2>
  <p>Christopher Kohlhoff and Peter Dimov made important contributions to the 
  design. Comments and suggestions were also received from Pavel Vozenilek, 
  Gennaro Prota, Dave Abrahams, Jeff Garland, Iain Hanson, Oliver Kowalke, and 
  Oleg Abrosimov. Christopher Kohlhoff suggested several improvements in the 
  current paper.</p>
<h2>Proposed text</h2>
<p><span style="background-color: #FFFFFF"><i>Replace the text of the </i>
</span><span style="background-color: rgb(255, 255, 255);"><i>TR2 Diagnostics 
library with:</i></span></p>
<hr>
<h2>Chapter <span style="font-weight: 400;"><i>(tbs)</i></span> -
<a name="Diagnostics-library">Diagnostics library</a></h2>
<hr>
<p>This clause describes components that C++ programs may use to detect and 
report error conditions that have an associated error code.</p>
<h3>Header <code>&lt;error_code</code>&gt;</h3>
<pre>namespace std
{
  namespace tr2
  {
    namespace sys
    {
      class error_category;
      class error_code;
      class system_error;

      typedef int     (*errno_decoder)(const error_code &amp;);
      typedef string  (*message_decoder)(const error_code &amp;);
      typedef wstring (*wmessage_decoder)(const error_code &amp;);</pre>
<pre>      const error_category  errno_ecat(<i>unspecified-value</i>);
      const error_category  native_ecat(<i>unspecified-value</i>); // possibly same value as errno_ecat

      size_t hash_value(const error_code &amp; ec);

    } // namespace sys
  } // namespace tr2
} // namespace std</pre>
<h3>Non-member functions</h3>
<pre>size_t <a name="hash_value">hash_value</a>( const error_code &amp; ec );</pre>
<blockquote>
  <p><i>Returns: </i>&nbsp;A hash value representing <code>ec</code>.</p>
</blockquote>
<h3>Class <code>
error_category</code></h3>
<p>The class <code>error_category</code> defines the type of objects used to identify the  source and encoding of a particular 
category of error codes.</p>
<pre>namespace std
{
  namespace tr2
  {
    namespace sys
    {
      class error_category
      {
      public:
        typedef uint_least32_t value_type;

        error_category();
        explicit error_category( value_type v );

        const value_type value() const;
        void assign( value_type v );

        bool operator==( const error_category &amp; rhs ) const;
        bool operator!=( const error_category &amp; rhs ) const;
        bool operator&lt; ( const error_category &amp; rhs ) const;
        bool operator&lt;=( const error_category &amp; rhs ) const;
        bool operator&gt; ( const error_category &amp; rhs ) const;
        bool operator&gt;=( const error_category &amp; rhs ) const;
      };
    } // namespace sys
  } // namespace tr2
} // namespace std</pre>
<h3>Class <code>error_category</code> members</h3>
<p><code>error_category();</code></p>
<blockquote>
<p><i>Effects: </i>Constructs an object of type <code>error_category</code>.</p>
<p><i>Postconditions:</i> <code>value() == errno_ecat</code>.</p>
</blockquote>
<p><code>explicit error_category(value_type v);</code></p>
<blockquote>
<p><i>Effects: </i>Constructs an object of type <code>error_category</code>.</p>
<p><i>Postconditions:</i> <code>value() == v</code>.</p>
</blockquote>
<p><code>const value_type value() const;</code></p>
<blockquote>
<p><i>Returns:</i> The value specified by <i>postconditions</i>&nbsp;of the most 
recent <code>assign</code>, if any, or of the constructor.</p>
</blockquote>
<p><code>void assign(value_type v);</code></p>
<blockquote>
<p><i>Postconditions:</i> <code>value() == v</code>.</p>
</blockquote>
<p><code>bool operator==(const error_category &amp; rhs) const;</code></p>
<blockquote>
<p><i>Returns:</i> <code>value() == rhs.value()</code>.</p>
</blockquote>
<p><code>bool operator!=(const error_category &amp; rhs) const;</code></p>
<blockquote>
<p><i>Returns:</i> <code>value() != rhs.value()</code>.</p>
</blockquote>
<p><code>bool operator&lt; (const error_category &amp; rhs) const;</code></p>
<blockquote>
<p><i>Returns:</i> <code>value() &lt; rhs.value()</code>.</p>
</blockquote>
<p><code>bool operator&lt;=(const error_category &amp; rhs) const;</code></p>
<blockquote>
<p><i>Returns:</i> <code>value() &lt;= rhs.value()</code>.</p>
</blockquote>
<p><code>bool operator&gt; (const error_category &amp; rhs) const;</code></p>
<blockquote>
<p><i>Returns:</i> <code>value() &gt; rhs.value()</code>.</p>
</blockquote>
<p><code>bool operator&gt;=(const error_category &amp; rhs) const;</code></p>
<blockquote>
<p><i>Returns:</i> <code>value() &gt;= rhs.value()</code>.</p>
</blockquote>
<h3>Class <code>
error_code</code></h3>
<p>The class <code>error_code</code> defines the type of objects used to 
identify errors that have an associated error code value, such as those originating from 
the operating system.</p>
<pre>namespace std
{
  namespace tr2
  {
    namespace sys
    {
      class error_code
      {
      public:
        typedef int_least32_t value_type;

        // constructors and assignment:
        error_code();
        error_code(value_type val, error_category cat);
        void assign(value_type val, error_category cat);

        // observers:
        value_type      value() const;
        error_category  category() const;
        int             to_errno() const;
        string          message() const;
        wstring         wmessage() const;

        operator <i>unspecified-bool-type</i>() const;
        bool operator!() const;

        // relationals:
        bool operator==(const error_code &amp; rhs) const;
        bool operator!=(const error_code &amp; rhs) const;
        bool operator&lt; (const error_code &amp; rhs) const;
        bool operator&lt;=(const error_code &amp; rhs) const;
        bool operator&gt; (const error_code &amp; rhs) const;
        bool operator&gt;=(const error_code &amp; rhs) const;

        // statics:
        static error_category new_category(errno_decoder ed=0, message_decoder md=0, wmessage_decoder wmd=0);
        static bool get_decoders(error_category cat, errno_decoder &amp; ed, message_decoder &amp; md, wmessage_decoder &amp; wmd);
      };
    } // namespace sys
  } // namespace tr2
} // namespace std</pre>
<h3>Class <code>
error_code</code> members</h3>
<pre>error_code();</pre>
<blockquote>
  <p><i>Effects: </i>Constructs an object of type <code>error_code</code>.</p>
  <p><i>Postconditions:</i> <code>value() == 0 &amp;&amp; category() == errno_ecat</code>.</p>
</blockquote>
<pre>error_code(value_type val, error_category cat);</pre>
<blockquote>
  <p><i>Effects: </i>Constructs an object of type <code>error_code</code>.</p>
  <p><i>Postconditions:</i> <code>value() == val &amp;&amp; category() == cat</code>.</p>
</blockquote>
<pre>void assign(value_type val, error_category cat);</pre>
<blockquote>
  <p><i>Postconditions:</i> <code>value() == val &amp;&amp; category() == cat</code>.</p>
</blockquote>
  <p><code>value_type value() const;</code></p>
<blockquote>
<p><i>Returns:</i> <code>value()</code> as specified by <i>postconditions</i>&nbsp;of the most 
recent <code>assign</code>, if any, or of the constructor.</p>
</blockquote>
  <p><code>error_category category() const;</code></p>
<blockquote>
<p><i>Returns:</i> <code>category()</code> as specified by <i>postconditions</i>&nbsp;of the most 
recent <code>assign</code>, if any, or of the constructor.</p>
</blockquote>
  <p><code>int to_errno() const;</code></p>
<blockquote>
<p><i>Effects: </i>&nbsp;<code>errno_decoder ed;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; message_decoder md;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wmessage_decoder wmd;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool ok( get_decoders( category(), ed, md, 
wmd ) );</code></p>
<p><i>Returns:</i>&nbsp; If <code>ok &amp;&amp; ed</code>, <code>ed(*this)</code>, 
otherwise <code>EOTHER</code>.</p>
<p><i>[Note:</i> The intent is to return the <a href="http://www.unix.org/single_unix_specification/">
ISO/IEC 9945:2003, <i>Portable Operating System Interface (POSIX)</i></a> error 
number that the implementation determines most closely corresponds to <code>
value()</code>. <i>--end note.]</i></p>
</blockquote>
  <p><code>string message() const;<br>
  wstring wmessage() const;</code></p>
<blockquote>
<p><i>Effects: </i>&nbsp;<code>errno_decoder ed;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; message_decoder md;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; wmessage_decoder wmd;<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool ok( get_decoders( category(), ed, md, 
wmd ) );</code></p>
<p><i>Returns:<br>
&nbsp;&nbsp;&nbsp; message():</i>&nbsp; If <code>ok &amp;&amp; md</code>, <code>md(*this)</code>, 
otherwise <code>string()</code>.<br>
<i>&nbsp;&nbsp;&nbsp; wmessage():</i>&nbsp; If <code>ok &amp;&amp; wmd</code>, <code>wmd(*this)</code>, 
otherwise <code>wstring()</code>.</p>
<p><i>Remarks:</i> If <code>category() == errno_ec</code>, the string is as 
returned by <code>strerror()</code>. Otherwise, the method used by the 
implementation to determine the string is unspecified.</p>
<p><i>[Note:</i> The intent is to return a locale sensitive string that describes the error 
corresponding to <code>value()</code>.&nbsp; <i>--end note.]</i></p>
</blockquote>
<p><code>operator <i>unspecified-bool-type</i>() const;</code></p>
<blockquote>
<p><i>Returns:</i> if <code>value() != value_type()</code>, returns a value that will evaluate
<code>true</code> in a boolean context; otherwise, returns a value that will 
evaluate <code>false</code> in a boolean context. The value type returned shall 
not be convertible to <code>int</code>.</p>
<p><i>Throws:</i> nothing.</p>
<p>[ <i>Note: </i>This conversion can be used in contexts where a <code>bool</code> 
is expected (e.g., an <code>if</code> condition); however, implicit conversions 
(e.g., to <code>int</code>) that can occur with <code>bool</code> are not 
allowed, eliminating some sources of user error. One possible implementation 
choice for this type is pointer-to-member. <i>end note </i>]</p>
</blockquote>
<p><code>bool operator!() const;</code></p>
<blockquote>
<p><i>Returns:</i> <code>value() == value_type()</code>.</p>
</blockquote>
<p><code>bool operator==(const error_code &amp; rhs) const;</code></p>
<blockquote>
<p><i>Returns:</i> <code>value() == rhs.value() &amp;&amp; category() == rhs.category()</code>.</p>
</blockquote>
<p><code>bool operator!=(const error_code &amp; rhs) const;</code></p>
<blockquote>
<p><i>Returns:</i> <code>!(*this == rhs)</code>.</p>
</blockquote>
<p><code>bool operator&lt; (const error_code &amp; rhs) const;</code></p>
<blockquote>
<p><i>Returns:</i> <code>category()&lt;rhs.category() || (category()==rhs.category() 
&amp;&amp; value()&lt;rhs.value())</code>.</p>
</blockquote>
<p><code>bool operator&lt;=(const error_code &amp; rhs) const;</code></p>
<blockquote>
<p><i>Returns:</i> <code>!(*this &gt; rhs)</code>.</p>
</blockquote>
<p><code>bool operator&gt; (const error_code &amp; rhs) const;</code></p>
<blockquote>
<p><i>Returns:</i> <code>category()&gt;rhs.category() || (category()==rhs.category() 
&amp;&amp; value()&gt;rhs.value())</code>.</p>
</blockquote>
<p><code>bool operator&gt;=(const error_code &amp; rhs) const;</code></p>
<blockquote>
<p><i>Returns:</i> <code>!(*this &lt; rhs)</code>.</p>
</blockquote>
<pre>static error_category <a name="new_category">new_category</a>(errno_decoder ed=0, message_decoder md=0, wmessage_decoder wmd=0 );</pre>
<blockquote>
  <p><i>Effects:</i> Constructs a new <code>error_category</code> object.<code>
  </code>Creates an association between the object's <code>value()</code> and 
  the <code>ed</code>,&nbsp;
  <code>md</code>, and <code>wmd</code> decoder pointers.</p>
  <p><i>Returns:</i> The constructed object.</p>
</blockquote>
<pre>static bool <a name="get_decoders">get_decoders</a>(error_category cat, errno_decoder &amp; ed, message_decoder &amp; md, wmessage_decoder &amp; wmd);</pre>
<blockquote>
  <p><i>Effects:</i> If <code>cat.value()</code> has an association created by <code>new_category()</code>, 
  sets <code>ed</code>,&nbsp; <code>md</code>, and <code>wmd</code> to the 
  association's respective decoder pointers. Otherwise, no effects.</p>
  <p><i>Returns:</i>
  <code>true</code> if the association existed, otherwise <code>false</code>.</p>
</blockquote>
<h3>Class <code>
system_error</code></h3>
<pre>namespace std
{
  namespace tr2
  {
    namespace sys
    {
      enum message_action { append_message, no_message };

      class system_error : public std::runtime_error
      {
      public:
        explicit system_error(error_code ec);
        system_error(error_code ec, const std::string &amp; what_arg, message_action ma=append_message);
        system_error(error_code::value_type ev, error_category ecat);
        system_error(error_code::value_type ev, error_category ecat,
                     const std::string &amp; what_arg, message_action ma=append_message);
        virtual ~system_error() throw();

        const error_code &amp;   code() const throw();
        bool message_action  append_message() const throw();
        const char *         what() const throw();

      private:
        string what_msg; // <b><i>for exposition only</i></b>
      };
    } // namespace sys
  } // namespace tr2
} // namespace std</pre>
<p>The class <code>system_error</code> defines the type of objects thrown as 
exceptions to report errors originating from the operating system.</p>
<pre>system_error(error_code ec);</pre>
<blockquote>
  <p><i>Effects:</i> Constructs an object of class <code>system_error</code>, 
  calls <code>std::runtime_error(std::string())</code>.</p>
  <p><i>Postcondition:</i> <code>code() == ec &amp;&amp; append_message() == true</code>.</p>
</blockquote>
<pre>system_error(error_code ec, const std::string &amp; what_arg, message_action ma=append_message );</pre>
<blockquote>
  <p><i>Effects:</i> Constructs an object of class <code>system_error</code>, 
  calls <code>std::runtime_error(what_arg)</code>.</p>
  <p><i>Postcondition:</i> <code>code() == ec &amp;&amp; append_message() == ma</code>.</p>
</blockquote>
<pre>system_error(error_code::value_type ev, error_category ecat);</pre>
<blockquote>
  <p><i>Effects:</i> Constructs an object of class <code>system_error</code>, 
  calls <code>std::runtime_error(std::string())</code>.</p>
  <p><i>Postcondition:</i> <code>code() == error_code(ev, ecat) &amp;&amp; 
  append_message() == true</code>.</p>
</blockquote>
<pre>system_error(error_code::value_type ev, error_category ecat,
                     const std::string &amp; what_arg, message_action ma=append_message);</pre>
<blockquote>
  <p><i>Effects:</i> Constructs an object of class <code>system_error</code>, 
  calls <code>std::runtime_error(what_arg)</code>.</p>
  <p><i>Postcondition:</i> <code>code() == error_code(ev, ecat) &amp;&amp; 
  append_message() == ma</code>.</p>
</blockquote>
<pre>error_code code() const;</pre>
<blockquote>
  <p><i>Returns:</i> <code>ec</code> or <code>error_code(ev, ecat)</code>, from 
  the constructor, as indicated.</p>
</blockquote>
<pre>bool message_action  append_message() const throw();</pre>
<blockquote>
  <p><i>Returns:</i> <code>ma</code> or <code>true</code>, from the constructor, 
  as indicated.</p>
</blockquote>
<pre>const char * what() const;</pre>
<blockquote>
  <p><i>Returns: </i>If <code>!code() || !append_message()</code>, return <code>
  this-&gt;runtime_error::what()</code>. Otherwise, as if:</p>
  <blockquote>
    <pre>what_msg = this-&gt;runtime_error::what();
if ( !what_msg.empty() ) what_msg += &quot;: &quot;;
what_msg += code().message();
return what_msg.c_str();</pre>
  </blockquote>
</blockquote>
<hr>

</body>

</html>
