<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 890: Improving &lt;system_error&gt; initialization</title>
<meta property="og:title" content="Issue 890: Improving &lt;system_error&gt; initialization">
<meta property="og:description" content="C++ library issue. Status: C++11">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue890.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#C++11">C++11</a> status.</em></p>
<h3 id="890"><a href="lwg-defects.html#890">890</a>. Improving <code>&lt;system_error&gt;</code> initialization</h3>
<p><b>Section:</b> 19.5.3 <a href="https://wg21.link/syserr.errcat">[syserr.errcat]</a> <b>Status:</b> <a href="lwg-active.html#C++11">C++11</a>
 <b>Submitter:</b> Beman Dawes <b>Opened:</b> 2008-09-14 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#syserr.errcat">issues</a> in [syserr.errcat].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++11">C++11</a> status.</p>
<p><b>Discussion:</b></p>
<p>
The <code>static const error_category</code> objects <code>generic_category</code> and
<code>system_category</code> in header <code>&lt;system_error&gt;</code> are currently declared:
</p>

<blockquote><pre>
const error_category&amp; get_generic_category();
const error_category&amp; get_system_category();

static const error_category&amp; generic_category = get_generic_category();
static const error_category&amp; system_category = get_system_category();
</pre></blockquote>

<p>
This formulation has several problems:
</p>

<ul>
<li>
Implementation details are exposed, since initialization is specified in
the interface. This over-constrains implementations without offsetting
user benefits. The form of initialization specified may be less than
maximally efficient on some platforms.
</li>
<li>
Use of the objects is more expensive in terms of number of machine level
instructions. See <i>Implementation experience</i> below.
</li>
<li>
Depending on the compiler, some cost may be incurred by each translation unit
that includes the header, even if the objects are not used. This is a
common scenario in user code, since the header is included by other
standard library headers. It should be mentioned that at least one
compilers is able to optimize this cost away, however.
</li>
</ul>

<p>
IO streams uses a somewhat different formulation for iostream_category, but 
still suffer much the same problems.
</p>

<p>
The original plan was to eliminate these problems by applying the C++0x
<code>constexpr</code> feature. See LWG issue <a href="lwg-closed.html#832" title="Applying constexpr to System error support (Status: NAD)">832</a><sup><a href="https://cplusplus.github.io/LWG/issue832" title="Latest snapshot">(i)</a></sup>. However, that approach turned out
to be unimplementable, since it would require a <code>constexpr</code> object of a
class with virtual functions, and that is not allowed by the core
language.
</p>

<p>
The proposed resolution was developed as an alternative. It mitigates the above 
problems by removing initialization from the visible interface, allowing 
implementations flexibility.
</p>

<p>
<b>Implementation experience:</b>
</p>

<p>
Prototype implementations of the current WP interface and proposed
resolution interface were tested with recent Codegear, GCC, Intel, and Microsoft 
compilers on Windows. The code generated by the Microsoft compiler was studied 
at length; the WP and proposal versions generated very similar code. For both versions 
the compiler did make use of static
initialization; apparently the compiler applied an implicit <code>constexpr</code>
where useful, even in cases where <code>constexpr</code> would not be permitted by
the language!
</p>

<p>
<b>Acknowledgements:</b>
</p>

<p>
Martin Sebor, Chris Kohlhoff, and John Lakos provided useful ideas and comments on initialization issues.
</p>

<p><i>[
San Francisco:
]</i></p>


<blockquote>
<p>
Martin: prefers not to create more file-scope static objects, and would
like to see <code>get_*</code> functions instead.
</p>
</blockquote>


<p><i>[Pre-Summit:]</i></p>

<blockquote>


<p>
Beman: The proposed resolution has been reworked to remove the file-scope 
static objects, per Martin&#39;s suggestions. The <code>get_</code> prefix has been 
eliminated from the function names as no longer necessary and to conform with 
standard library naming practice.
</p>

</blockquote>

<p><i>[
Post Summit:
]</i></p>


<blockquote><p>
Agreement that this is wise and essential, text provided works and has
been implemented. Seems to be widespread consensus. Move to Tentative Ready.
</p></blockquote>



<p id="res-890"><b>Proposed resolution:</b></p>

<p>Change 16.4.6.16 <a href="https://wg21.link/value.error.codes">[value.error.codes]</a> Value of error codes as indicated:</p>
<blockquote>
 <p>Certain functions in the C++ standard library report errors via a 
 <code>std::error_code</code> (19.4.2.2) object. That object's <code>category()</code> member shall 
 return <del>a reference to</del> <code>std::system_category</code><code><ins><code>()</code></ins></code> for errors originating from the 
 operating system, or a reference to an implementation-defined error_category 
 object for errors originating elsewhere. The implementation shall define the 
 possible values of value() for each of these error categories. [<i>Example:</i> For 
 operating systems that are based on POSIX, implementations are encouraged to 
 define the <code>std::system_category</code><code><ins><code>()</code></ins></code> values as identical to the POSIX <code>errno</code> values, 
 with additional values as defined by the operating system's documentation. 
 Implementations for operating systems that are not based on POSIX are 
 encouraged to define values identical to the operating system's values. For 
 errors that do not originate from the operating system, the implementation may 
 provide enums for the associated values --<i>end example</i>]</p>
</blockquote>

<p>
Change 19.5.3.1 <a href="https://wg21.link/syserr.errcat.overview">[syserr.errcat.overview]</a> Class <code>error_category</code> overview
<code>error_category</code> synopsis as indicated:
</p>

<blockquote>
<pre>
const error_category&amp; <del>get_</del>generic_category();
const error_category&amp; <del>get_</del>system_category();

<del>static storage-class-specifier const error_category&amp; generic_category = get_generic_category();
static storage-class-specifier const error_category&amp; system_category = get_system_category();</del>
</pre>
</blockquote>

<p>
Change 19.5.3.5 <a href="https://wg21.link/syserr.errcat.objects">[syserr.errcat.objects]</a> Error category objects as indicated:
</p>

<blockquote>
<pre>const error_category&amp; <del>get_</del>generic_category();
</pre>

<blockquote>

<p>
<i>Returns:</i> A reference to an object of a type derived from class <code>error_category</code>.
</p>

<p>
<i>Remarks:</i> The object's <code>default_error_condition</code> and <code>equivalent</code> virtual
functions shall behave as specified for the class <code>error_category</code>. The
object's <code>name</code> virtual function shall return a pointer to the string
<code>"GENERIC"</code>.
</p>
</blockquote>

<pre>
const error_category&amp; <del>get_</del>system_category();
</pre>

<blockquote>
<p>
<i>Returns:</i> A reference to an object of a type derived from class <code>error_category</code>.
</p>

<p>
<i>Remarks:</i> The object's <code>equivalent</code> virtual functions shall behave as
specified for class <code>error_category</code>. The object's <code>name</code> virtual function
shall return a pointer to the string <code>"system"</code>. The object's
<code>default_error_condition</code> virtual function shall behave as follows:
</p>
<blockquote><p>
If the argument <code>ev</code> corresponds to a POSIX <code>errno</code> value <code>posv</code>, the function
shall return <code>error_condition(posv, generic_category<ins>()</ins>)</code>. Otherwise, the
function shall return <code>error_condition(ev, system_category<ins>()</ins>)</code>. What
constitutes correspondence for any given operating system is
unspecified. [<i>Note:</i> The number of potential system error codes is large
and unbounded, and some may not correspond to any POSIX <code>errno</code> value.
Thus implementations are given latitude in determining correspondence.
&mdash; <i>end note</i>]
</p></blockquote>
</blockquote>

</blockquote>

<p>Change 19.5.4.2 <a href="https://wg21.link/syserr.errcode.constructors">[syserr.errcode.constructors]</a> Class <code>error_code</code> constructors 
as indicated:</p>
<blockquote>
 <pre>error_code();</pre>
 <blockquote>
 <p><i>Effects:</i> Constructs an object of type error_code.</p>
 <p><i>Postconditions:</i> <code>val_ == 0 </code>and <code>cat_ == &amp;system_category</code><code><ins>()</ins></code>.</p>
 </blockquote>
</blockquote>
<p>Change 19.5.4.3 <a href="https://wg21.link/syserr.errcode.modifiers">[syserr.errcode.modifiers]</a> Class <code>error_code</code> modifiers as 
indicated:</p>
<blockquote>
 <pre>void clear();</pre>
 <blockquote>
 <p>Postconditions: <code>value() == 0</code> and <code>category() == 
 system_category</code><code><ins>()</ins></code>.</p>
 </blockquote>
</blockquote>
<p>Change 19.5.4.5 <a href="https://wg21.link/syserr.errcode.nonmembers">[syserr.errcode.nonmembers]</a> Class <code>error_code</code> non-member 
functions as indicated:</p>
<blockquote>
 <pre>error_code make_error_code(errc e);</pre>
 <blockquote>
 <p><i>Returns:</i> <code>error_code(static_cast&lt;int&gt;(e), generic_category</code><code><ins>()</ins></code><code>)</code>.</p>
 </blockquote>
</blockquote>
<p>Change 19.5.5.2 <a href="https://wg21.link/syserr.errcondition.constructors">[syserr.errcondition.constructors]</a> Class <code>error_condition</code> 
constructors as indicated:</p>
<blockquote>
 <pre>error_condition();</pre>
 <blockquote>
 <p><i>Effects:</i> Constructs an object of type <code>error_condition</code>.</p>
 <p><i>Postconditions:</i> <code>val_ == 0</code> and <code>cat_ == &amp;generic_category</code><code><ins>()</ins></code>.</p>
 </blockquote>
</blockquote>
<p>Change 19.5.5.3 <a href="https://wg21.link/syserr.errcondition.modifiers">[syserr.errcondition.modifiers]</a> Class <code>error_condition</code> 
modifiers as indicated:</p>
<blockquote>
 <pre>void clear();</pre>
 <blockquote>
 <p><i>Postconditions:</i> <code>value() == 0</code> and <code>category() == 
 generic_category</code><code><ins>()</ins></code>.</p>
 </blockquote>
</blockquote>
<p>Change 19.5.5.5 <a href="https://wg21.link/syserr.errcondition.nonmembers">[syserr.errcondition.nonmembers]</a> Class <code>error_condition</code> 
non-member functions as indicated:</p>
<blockquote>
 <pre>error_condition make_error_condition(errc e);</pre>
 <blockquote>
 <p><i>Returns:</i> <code>error_condition(static_cast&lt;int&gt;(e), generic_category<ins>()</ins>)</code>.</p>
 </blockquote>
</blockquote>
 <p>Change 31.5 <a href="https://wg21.link/iostreams.base">[iostreams.base]</a> Iostreams base classes, Header <code>&lt;ios&gt;</code> 
 synopsis as indicated:</p>
<blockquote>
 <pre>concept_map ErrorCodeEnum&lt;io_errc&gt; { };
error_code make_error_code(io_errc e);
error_condition make_error_condition(io_errc e);
<del>storage-class-specifier</del> const error_category&amp; iostream_category<ins>()</ins>;</pre>
</blockquote>
<p>Change  [ios::failure] Class ios_base::failure, paragraph 2 as 
indicated:</p>
<blockquote>
<p>When throwing <code>ios_base::failure</code> exceptions, implementations should provide 
values of <code>ec</code> that identify the specific reason for the failure. [ <i>Note</i>: Errors 
arising from the operating system would typically be reported as <code>
system_category</code><code><ins>()</ins></code> errors with an error value of the 
error number reported by the operating system. Errors arising from within the 
stream library would typically be reported as <code>error_code(io_errc::stream, 
iostream_category<ins>()</ins>)</code>. &mdash; <i>end note</i> ]</p>
</blockquote>
<p>Change 31.5.6 <a href="https://wg21.link/error.reporting">[error.reporting]</a> Error reporting as indicated:</p>
<blockquote>
 <pre>error_code make_error_code(io_errc e);</pre>
 <blockquote>
 <p><i>Returns:</i> <code>error_code(static_cast&lt;int&gt;(e), iostream_category</code><ins>()</ins><code>)</code>.</p>
 </blockquote>
 <pre>error_condition make_error_condition(io_errc e);</pre>
 <blockquote>
 <p><i>Returns:</i> <code>error_condition(static_cast&lt;int&gt;(e), 
 iostream_category</code><ins>()</ins><code>)</code>.</p>
 </blockquote>
 <pre><del>storage-class-specifier</del> const error_category&amp; iostream_category<ins>()</ins>;</pre>
 <blockquote>
 <del><p>The implementation shall initialize iostream_category. Its storage-class-specifier 
 may be static or extern. It is unspecified whether initialization is static 
 or dynamic (3.6.2). If initialization is dynamic, it shall occur before 
 completion of the dynamic initialization of the first translation unit 
 dynamically initialized that includes header &lt;system_error&gt;.</p></del>
<p>
<ins><i>Returns:</i> A reference to an object of a type derived from class <code>error_category</code>.</ins>
</p>
<p><i>Remarks:</i> The object's default_error_condition and equivalent virtual functions shall 
behave as specified for the class error_category. The object's name virtual 
function shall return a pointer to the string &quot;iostream&quot;.</p>
 </blockquote>
</blockquote>







</body>
</html>
