123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html><meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <title>Major differences - Boost.Outcome documentation</title>
- <link rel="stylesheet" href="../css/boost.css" type="text/css">
- <meta name="generator" content="Hugo 0.52 with Boostdoc theme">
- <meta name="viewport" content="width=device-width,initial-scale=1.0"/>
- <link rel="icon" href="../images/favicon.ico" type="image/ico"/>
- <body><div class="spirit-nav">
- <a accesskey="p" href="../experimental/map.html"><img src="../images/prev.png" alt="Prev"></a>
- <a accesskey="u" href="../experimental.html"><img src="../images/up.png" alt="Up"></a>
- <a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="../experimental/status_result.html"><img src="../images/next.png" alt="Next"></a></div><div id="content">
- <div class="titlepage"><div><div><h1 style="clear: both">Major differences</h1></div></div></div>
- <p>The major design differences between <code><system_error></code> and proposed <code><system_error2></code> are
- as follows:</p>
- <ol>
- <li><p><code>experimental::status_code<DomainType></code> can represent warnings
- and form-of-success codes as well as failure codes. <code>experimental::errored_status_code<DomainType></code>
- is more similar to <code>std::error_code</code>, in that it can only represent failures
- (this is enforced by C++ 20 contract or runtime assertion check).</p></li>
- <li><p>The code’s domain implementation defines the payload type to be transported around by
- <code>experimental::status_code<DomainType></code>, rather than it being
- hardcoded to <code>int</code> as in <code>std::error_code</code>. The payload type can be anything
- you like, including non-trivially-copyable, move-only, complex etc types.</p>
- <p>This facility is extremely useful. Extra failure metadata such as stack
- backtraces can be returned, for example. You can absolutely vary the payload
- depending on whether <code>NDEBUG</code> or <code>_DEBUG</code> is defined, too.</p></li>
- <li><p>If your domain defines a payload type which is trivially copyable or
- move relocating<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>, it gains an implicit convertibility to a move-only
- <code>experimental::status_code<erased<T>></code> where <code>T</code> is another
- trivially copyable or move relocating type. This permits global headers
- to use a single, common, type erased, status code type which is highly
- desirable for code bases of any complexity. However, unlike <code>std::error_code</code>,
- which fulfils the exact same role in <code><system_error></code> based code, the type
- erased payload can be bigger than the hardcoded <code>int</code> in <code>std::error_code</code>.</p>
- <p>This facility is also extremely useful, as extra failure metadata can be
- type erased, transported through code with no knowledge of such things,
- and the original type with failure metadata resurrected at the handling point.
- Indeed P1095 proposed <code>std::error</code> is a type alias to
- <code>experimental::status_code<erased<intptr_t>></code>, and it can transport erased
- <code>std::exception_ptr</code> instances, POSIX error codes, and much more besides.</p></li>
- <li><p>Equality comparisons between status code’s with non-identical domains are
- always <b><em>semantic</em></b> i.e. are they semantically equivalent, rather than exactly
- equal? This mirrors when you compare <code>std::error_code</code> to a <code>std::error_condition</code>,
- but as there is no equivalent for the latter in <code><system_error2></code>, this means
- that when you see the code:</p>
- <div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="k">if</span><span class="p">(</span><span class="n">code1</span> <span class="o">==</span> <span class="n">code2</span><span class="p">)</span> <span class="p">...</span>
- </code></pre></div>
- <p>… you can be highly confident that this is an inexact, semantic, match operation.
- The same code under <code><system_error></code> is highly ambiguous as to whether exact
- or inexact comparison is being performed (after all, all there is is “<code>code1 == code2</code>”,
- so it depends on the types of <code>code1</code> and <code>code2</code> which usually is not obvious).</p>
- <p>The ambiguity, and high cognitive load during auditing <code><system_error></code> code for correctness, has
- led to many surprising and unexpected failure handling bugs during the past
- decade in production C++.</p></li>
- <li><p><code><system_error2></code>, being a new design, has all-constexpr construction and
- destruction which avoids the need for static global variables, as <code><system_error></code>
- has. Each of those static global variables requires an atomic fence just in
- case it has not been initialised, thus every retrieval of an error category bloats
- code and inhibits optimisation, plus makes the use of custom error code categories
- in header-only libraries unreliable. Boost.System has replicated the all-constexpr
- construction and destruction from <code><system_error2></code>, and thus now has similar
- characteristics in this regard.</p></li>
- <li><p>Finally, this is a small but important difference. Under <code><system_error></code>,
- this extremely common use case is ambiguous:</p>
- <div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="k">if</span><span class="p">(</span><span class="n">ec</span><span class="p">)</span> <span class="p">...</span>
- </code></pre></div>
- <p>Does this code mean “if there was an error?”, or “if the error code is set?”,
- or “is the error code non-zero?”. The correct answer according to the standard is the last choice, but
- a quick survey of open source <code><system_error></code> based code on github quickly
- demonstrates there is widespread confusion regarding correct usage.</p>
- <p><code><system_error2></code> solves this by removing the boolean test entirely. One
- now writes <code>if(sc.success()) ...</code>, <code>if(sc.failure()) ...</code>, <code>if(sc.empty()) ...</code>
- and so on, thus eliminating ambiguity.</p></li>
- </ol>
- <div class="footnotes">
- <hr />
- <ol>
- <li id="fn:1"><a href="http://wg21.link/P1029">Move relocating is not in the standard, nor has been reviewed by WG21 yet</a>. It is defined to be a type whose move constructor <code>memcpy()</code>’s the bits from source to destination, followed by <code>memcpy()</code> of the bits of a default constructed instance to source, and with a programmer-given guarantee that the destructor, when called on a default constructed instance, has no observable side effects. A surprising number of standard library types can meet this definition of move relocating, including <code>std::vector<T></code>, <code>std::shared_ptr<T></code>, and <code>std::exception_ptr</code>.
- <a class="footnote-return" href="#fnref:1"><sup>[return]</sup></a></li>
- </ol>
- </div>
- </div><p><small>Last revised: February 05, 2019 at 17:14:18 UTC</small></p>
- <hr>
- <div class="spirit-nav">
- <a accesskey="p" href="../experimental/map.html"><img src="../images/prev.png" alt="Prev"></a>
- <a accesskey="u" href="../experimental.html"><img src="../images/up.png" alt="Up"></a>
- <a accesskey="h" href="../index.html"><img src="../images/home.png" alt="Home"></a><a accesskey="n" href="../experimental/status_result.html"><img src="../images/next.png" alt="Next"></a></div></body>
- </html>
|