2
0
mirror of https://github.com/boostorg/outcome.git synced 2026-01-21 17:12:15 +00:00
Files
outcome/doc/html/index.html
2026-01-18 22:37:08 +00:00

244 lines
21 KiB
HTML

<!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>Home - 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="h" href="./index.html"><img src="./images/home.png" alt="Home"></a><a accesskey="n" href="./requirements.html"><img src="./images/next.png" alt="Next"></a></div><div id="content">
<h1 id="outcome-2-2-library">Outcome 2.2 library</h1>
<div>
<div class="author">
<h3 class="author"><span class="firstname">Niall</span> <span class="surname">Douglas</span></h3>
</div>
</div>
<div><p class="copyright">Copyright &#169; 2014-2026 Niall Douglas <a href="./credits.html">and others</a></p></div>
<div><div class="legalnotice">
<a name="outcome.legal"></a><p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="./LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></div>
<div class="toc">
<p><b>Table of Contents</b></p>
<dl class="toc">
<dt><span class="section"><a href="./requirements.html">Prerequisites</a></span></dt>
<dt><span class="section"><a href="./build.html">Build and install</a></span></dt>
<dt><span class="section"><a href="./alternatives.html">Review of Error Handling Frameworks</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="./alternatives/exceptions.html">std exception throws</a></span></dt>
<dt><span class="section"><a href="./alternatives/error_code.html">std error codes</a></span></dt>
<dt><span class="section"><a href="./alternatives/expected.html">std expected</a></span></dt>
<dt><span class="section"><a href="./alternatives/outcome.html">Outcome (proposed std result)</a></span></dt>
<dt><span class="section"><a href="./alternatives/leaf.html">LEAF</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="./motivation.html">Motivation</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="./motivation/exceptions.html">Exceptions</a></span></dt>
<dt><span class="section"><a href="./motivation/errno.html">errno</a></span></dt>
<dt><span class="section"><a href="./motivation/error_codes.html">Error codes</a></span></dt>
<dt><span class="section"><a href="./motivation/std_error_code.html">std::error_code</a></span></dt>
<dt><span class="section"><a href="./motivation/plug_error_code.html">Plugging a library into <code>std::error_code</code></a></span></dt>
<dt><span class="section"><a href="./motivation/plug_error_code2.html">Plugging a library into <code>boost::system::error_code</code></a></span></dt>
<dt><span class="section"><a href="./motivation/narrow_contract.html">Narrow contracts</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="./abi-stability.html">Future ABI stability guarantees</a></span></dt>
<dt><span class="section"><a href="./tutorial.html">Tutorial</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="./tutorial/essential.html">Essential</a></span></dt>
<dt><span class="section"><a href="./tutorial/advanced.html">Advanced</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="./recipes.html">Recipes</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="./recipes/asio-integration.html">ASIO/Networking TS : Boost &lt; 1.70</a></span></dt>
<dt><span class="section"><a href="./recipes/asio-integration-1-70.html">ASIO/Networking TS: Boost &gt;= 1.70</a></span></dt>
<dt><span class="section"><a href="./recipes/foreign-try.html">Extending <code>BOOST_OUTCOME_TRY</code></a></span></dt>
<dt><span class="section"><a href="./recipes/rust.html">Rust FFI</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="./experimental.html">Experimental</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="./experimental/advantages.html">The main advantages</a></span></dt>
<dt><span class="section"><a href="./experimental/map.html">Approximate map between error code designs</a></span></dt>
<dt><span class="section"><a href="./experimental/differences.html">Major differences</a></span></dt>
<dt><span class="section"><a href="./experimental/status_result.html"><code>status_result</code> and <code>status_outcome</code></a></span></dt>
<dt><span class="section"><a href="./experimental/outcome.html">Tying it all together</a></span></dt>
<dt><span class="section"><a href="./experimental/worked-example.html">Worked example: Custom domain (the short way)</a></span></dt>
<dt><span class="section"><a href="./experimental/worked-example-long.html">Worked example: Custom domain (the long way)</a></span></dt>
<dt><span class="section"><a href="./experimental/c-api.html">Using Outcome from C code</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="./reference.html">API reference</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="./reference/macros.html">Macros</a></span></dt>
<dt><span class="section"><a href="./reference/concepts.html">Concepts</a></span></dt>
<dt><span class="section"><a href="./reference/converters.html">Converters</a></span></dt>
<dt><span class="section"><a href="./reference/traits.html">Traits</a></span></dt>
<dt><span class="section"><a href="./reference/policies.html">Policies</a></span></dt>
<dt><span class="section"><a href="./reference/types.html">Types</a></span></dt>
<dt><span class="section"><a href="./reference/aliases.html">Aliases</a></span></dt>
<dt><span class="section"><a href="./reference/functions.html">Functions</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="./faq.html">Frequently asked questions</a></span></dt>
<dt><span class="section"><a href="./videos.html">Videos</a></span></dt>
<dt><span class="section"><a href="./changelog.html">Changelog</a></span></dt>
<dd><dl>
<dt><span class="section"><a href="./changelog/upgrade_v21_v22.html">Upgrade guide v2.1 =&gt; v2.2</a></span></dt>
<dt><span class="section"><a href="./changelog/v22.html">v2.2 major changes</a></span></dt>
</dl></dd>
<dt><span class="section"><a href="./history.html">History</a></span></dt>
</dl>
</div>
<h2 class="title">Introduction</h2>
<div class="notices note" style="background: url('images/note.png') top left no-repeat padding-box padding-box;">
<div class="notices heading">note</div>
<div class="notices message"><p>At the end of December 2021, Standalone Outcome
<a href="./abi-stability.html">went guaranteed future ABI stable</a>.
From v2.2.3 onwards, you get ABI compatibilty guarantees across Outcome releases.</p>
</div>
</div>
<p>Outcome is a set of tools for reporting and handling function failures in contexts where <em>directly</em> using C++ exception handling is unsuitable. Such contexts include:</p>
<ul>
<li><p>there are programs, or parts thereof, that are compiled with exceptions disabled;</p></li>
<li><p>there are parts of program that have a lot of branches depending on types of failures,
where if-statements are cleaner than try-catch blocks;</p></li>
<li><p>there is a hard requirement that the failure path of execution should not cost more than the successful path of execution;</p></li>
<li><p>there are situations, like in the <a href="http://www.boost.org/doc/libs/release/libs/filesystem/doc/index.htm"><code>filesystem</code></a> library, where whether the failure should be handled remotely
(using a C++ exception throw), or locally cannot be made inside the function and needs to be decided by the caller,
and in the latter case throwing a C++ exception is not desirable for the aforementioned reasons;</p></li>
<li><p>there are parts of the program/framework that themselves implement exception handling and prefer
to not use exceptions to propagate failure reports across threads, tasks, fibers, etc;</p></li>
<li><p>one needs to propagate exceptions through layers that do not implement exception throw safety;</p></li>
<li><p>there is an external requirement (such as a company-wide policy) that failure handling paths are explicitly indicated in the code.</p></li>
<li><p>where interoperation with C code, without having to resort to C++ exception wrapper shims, is important.</p></li>
<li><p>where your mostly C code base needs exception-like error handling, and the subset of Outcome&rsquo;s functionality available in C is sufficient for your needs.</p></li>
</ul>
<p>Outcome addresses failure handling through returning a special type from functions, which is able to store either a successfully computed value (or <code>void</code>), or the information about failure. Outcome also comes with a set of idioms for dealing with such types.</p>
<p>Particular care has been taken to ensure that Outcome has the lowest possible impact on build times,
thus making it suitable for use in the global headers of really large codebases. Storage layout is
guaranteed and is C-compatible for <code>result&lt;T, E&gt;</code><sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>, thus making Outcome based code long term ABI-stable.</p>
<p>Fully deterministic all-<code>noexcept</code> C++ Coroutine support in Outcome is particularly strong, and we
supply Outcome-optimising <a href="./reference/types/awaitables/eager.html" class="api-reference"><code>eager&lt;T, Executor = void&gt;/atomic_eager&lt;T, Executor = void&gt;</code></a>
, <a href="./reference/types/awaitables/lazy.html" class="api-reference"><code>lazy&lt;T, Executor = void&gt;/atomic_lazy&lt;T, Executor = void&gt;</code></a>
and <a href="./reference/types/awaitables/generator.html" class="api-reference"><code>generator&lt;T, Executor = void&gt;</code></a>
awaitables which work for any user type.</p>
<h2 id="sample-usage-c">Sample usage (C++)</h2>
<p>The main workhorse in the Outcome library is <code>result&lt;T&gt;</code>: it represents either a successfully computed value of type <code>T</code>, or a <code>std::error_code</code>/<code>boost::system::error_code</code><sup class="footnote-ref" id="fnref:2"><a href="#fn:2">2</a></sup> representing the reason for failure. You use it in the function&rsquo;s return type:</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="n">outcome</span><span class="o">::</span><span class="n">result</span><span class="o">&lt;</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">data_from_file</span><span class="p">(</span><span class="n">string_view</span> <span class="n">path</span><span class="p">)</span> <span class="k">noexcept</span><span class="p">;</span>
</code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/intro_example.cpp#L49" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>It is possible to inspect the state manually:</p>
<div class="code-snippet"><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">outcome</span><span class="o">::</span><span class="n">result</span><span class="o">&lt;</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">rslt</span> <span class="o">=</span> <span class="n">data_from_file</span><span class="p">(</span><span class="s">&#34;config.cfg&#34;</span><span class="p">))</span>
<span class="n">use_string</span><span class="p">(</span><span class="n">rslt</span><span class="p">.</span><span class="n">value</span><span class="p">());</span> <span class="c1">// returns string
</span><span class="c1"></span><span class="k">else</span>
<span class="k">throw</span> <span class="n">LibError</span><span class="p">{</span><span class="n">rslt</span><span class="p">.</span><span class="n">error</span><span class="p">(),</span> <span class="s">&#34;config.cfg&#34;</span><span class="p">};</span> <span class="c1">// returns error_code
</span><span class="c1"></span></code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/intro_example.cpp#L54" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>Or, if this function is called in another function that also returns <code>result&lt;T&gt;</code>, you can use a dedicated control statement:</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="n">outcome</span><span class="o">::</span><span class="n">result</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">process</span><span class="p">(</span><span class="k">const</span> <span class="n">string</span><span class="o">&amp;</span> <span class="n">content</span><span class="p">)</span> <span class="k">noexcept</span><span class="p">;</span>
<span class="n">outcome</span><span class="o">::</span><span class="n">result</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">int_from_file</span><span class="p">(</span><span class="n">string_view</span> <span class="n">path</span><span class="p">)</span> <span class="k">noexcept</span>
<span class="p">{</span>
<span class="n">BOOST_OUTCOME_TRY</span><span class="p">(</span><span class="k">auto</span> <span class="n">str</span><span class="p">,</span> <span class="n">data_from_file</span><span class="p">(</span><span class="n">path</span><span class="p">));</span>
<span class="c1">// if control gets here data_from_file() has succeeded
</span><span class="c1"></span> <span class="k">return</span> <span class="nf">process</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> <span class="c1">// decltype(str) == string
</span><span class="c1"></span><span class="p">}</span>
</code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/intro_example.cpp#L62" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p><code>BOOST_OUTCOME_TRY</code> is a control statement. If the returned <code>result&lt;T&gt;</code> object contains an error information, the enclosing function is immediately returned with <code>result&lt;U&gt;</code> containing the same failure information; otherwise an automatic object of type <code>T</code>
is available in scope.</p>
<h2 id="sample-usage-c-1">Sample usage (C)</h2>
<p>Equivalent to the C++ API: <code>BOOST_OUTCOME_C_DECLARE_RESULT_SYSTEM(ident, T)</code> declares the C type, thereafter <code>BOOST_OUTCOME_C_RESULT_SYSTEM(ident)</code> refers to it. You use it in the function&rsquo;s return type:</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="n">BOOST_OUTCOME_C_DECLARE_RESULT_SYSTEM</span><span class="p">(</span><span class="n">result_string</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="p">)</span>
<span class="n">BOOST_OUTCOME_C_RESULT_SYSTEM</span><span class="p">(</span><span class="n">result_string</span><span class="p">)</span> <span class="n">data_from_file</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">path</span><span class="p">);</span>
</code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/intro_c_example.cpp#L40" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>It is possible to inspect the state manually:</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"> <span class="n">BOOST_OUTCOME_C_RESULT_SYSTEM</span><span class="p">(</span><span class="n">result_string</span><span class="p">)</span> <span class="n">rslt</span> <span class="o">=</span> <span class="n">data_from_file</span><span class="p">(</span><span class="s">&#34;config.cfg&#34;</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">BOOST_OUTCOME_C_RESULT_HAS_VALUE</span><span class="p">(</span><span class="n">rslt</span><span class="p">))</span>
<span class="n">use_string</span><span class="p">(</span><span class="n">rslt</span><span class="p">.</span><span class="n">value</span><span class="p">);</span> <span class="c1">// returns string
</span><span class="c1"></span> <span class="k">else</span>
<span class="nf">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&#34;%s</span><span class="se">\n</span><span class="s">&#34;</span><span class="p">,</span> <span class="n">outcome_status_code_message</span><span class="p">(</span><span class="o">&amp;</span><span class="n">rslt</span><span class="p">.</span><span class="n">error</span><span class="p">));</span>
</code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/intro_c_example.cpp#L48" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>Or, if this function is called in another function that also returns <code>BOOST_OUTCOME_C_RESULT_SYSTEM(ident)</code>, you can use a dedicated control statement:</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="n">BOOST_OUTCOME_C_DECLARE_RESULT_SYSTEM</span><span class="p">(</span><span class="n">result_int</span><span class="p">,</span> <span class="kt">int</span><span class="p">)</span>
<span class="n">BOOST_OUTCOME_C_RESULT_SYSTEM</span><span class="p">(</span><span class="n">result_int</span><span class="p">)</span> <span class="n">process</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">content</span><span class="p">);</span>
<span class="n">BOOST_OUTCOME_C_RESULT_SYSTEM</span><span class="p">(</span><span class="n">result_int</span><span class="p">)</span> <span class="n">int_from_file</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">path</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">BOOST_OUTCOME_C_RESULT_SYSTEM_TRY</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">str</span><span class="p">,</span> <span class="n">result_int</span><span class="p">,</span> <span class="cm">/* cleanup on fail */</span><span class="p">,</span> <span class="n">data_from_file</span><span class="p">(</span><span class="n">path</span><span class="p">));</span>
<span class="c1">// if control gets here data_from_file() has succeeded
</span><span class="c1"></span> <span class="k">return</span> <span class="nf">process</span><span class="p">(</span><span class="n">str</span><span class="p">);</span> <span class="c1">// decltype(str) == string
</span><span class="c1"></span><span class="p">}</span>
</code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/intro_c_example.cpp#L57" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>The C Result is guaranteed to be layout identical to its C++ equivalent. Convenience conversion functions are available, but you can reinterpret cast too.</p>
<div class="notices note" style="background: url('images/note.png') top left no-repeat padding-box padding-box;">
<div class="notices heading">note</div>
<div class="notices message"><p>This library joined <a href="https://www.boost.org/doc/libs/develop/libs/outcome/doc/html/index.html">the Boost C++ libraries</a> in the 1.70 release (Spring 2019). <a href="https://github.com/boostorg/outcome">It can be grafted into much older Boost releases if desired</a>.</p>
</div>
</div>
<div class="footnotes">
<hr />
<ol>
<li id="fn:1">If you choose a C-compatible <code>T</code> and <code>E</code> type.
<a class="footnote-return" href="#fnref:1"><sup>[return]</sup></a></li>
<li id="fn:2"><code>result&lt;T&gt;</code> defaults to <code>std::error_code</code> for Standalone Outcome, and to <code>boost::system::error_code</code> for Boost.Outcome. You can mandate a choice using <code>std_result&lt;T&gt;</code> or <code>boost_result&lt;T&gt;</code>.
<a class="footnote-return" href="#fnref:2"><sup>[return]</sup></a></li>
</ol>
</div>
</div><p><small>Last revised: July 16, 2024 at 21:33:35 &#43;0100</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="./history.html"><img src="./images/prev.png" alt="Prev"></a>
<a accesskey="h" href="./index.html"><img src="./images/home.png" alt="Home"></a><a accesskey="n" href="./requirements.html"><img src="./images/next.png" alt="Next"></a></div></body>
</html>