[DEV] add v1.76.0

This commit is contained in:
2021-10-05 21:37:46 +02:00
parent a97e9ae7d4
commit d0115b733d
45133 changed files with 4744437 additions and 1026325 deletions

View File

@@ -0,0 +1,86 @@
<!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>In use - 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="../../../tutorial/advanced/interop/app-map-tidylib.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/conclusion.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">In use</h1></div></div></div>
<p>This is how you might now write application code using these three libraries:</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="k">namespace</span> <span class="n">app</span>
<span class="p">{</span>
<span class="c1">// A markup function to indicate when we are ValueOrError converting
</span><span class="c1"></span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">T</span><span class="o">&gt;</span> <span class="kr">inline</span> <span class="n">outcome</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">::</span><span class="n">value_type</span><span class="o">&gt;</span> <span class="n">ext</span><span class="p">(</span><span class="n">T</span> <span class="o">&amp;&amp;</span><span class="n">v</span><span class="p">)</span>
<span class="p">{</span> <span class="c1">//
</span><span class="c1"></span> <span class="k">return</span> <span class="n">outcome</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">T</span><span class="o">::</span><span class="n">value_type</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">v</span><span class="p">));</span>
<span class="p">}</span>
<span class="n">outcome</span><span class="o">&lt;</span><span class="kt">void</span><span class="o">&gt;</span> <span class="n">go</span><span class="p">()</span> <span class="c1">// NOT noexcept, this can throw STL exceptions e.g. bad_alloc
</span><span class="c1"></span> <span class="p">{</span>
<span class="c1">// Note that explicit construction is required when converting between differing types
</span><span class="c1"></span> <span class="c1">// of outcome and result. This makes it explicit what you intend to do as conversion
</span><span class="c1"></span> <span class="c1">// may be a lot more expensive than moves.
</span><span class="c1"></span>
<span class="c1">// Try to GET this URL. If an unsuccessful HTTP status is returned, serialise a string
</span><span class="c1"></span> <span class="c1">// containing a description of the HTTP status code and the URL which failed, storing
</span><span class="c1"></span> <span class="c1">// that into a httplib_error exception type which is stored as an exception ptr. The
</span><span class="c1"></span> <span class="c1">// TRY operation below will return that exception ptr to be rethrown in the caller.
</span><span class="c1"></span> <span class="c1">// Otherwise the fetched data is returned in a std::string data.
</span><span class="c1"></span> <span class="n">BOOST_OUTCOME_TRY</span><span class="p">(</span><span class="k">auto</span> <span class="n">data</span><span class="p">,</span> <span class="n">ext</span><span class="p">(</span><span class="n">httplib</span><span class="o">::</span><span class="n">get</span><span class="p">(</span><span class="s">&#34;http://www.nedproductions.biz/&#34;</span><span class="p">)));</span>
<span class="n">string_view</span> <span class="nf">data_view</span><span class="p">(</span><span class="n">data</span><span class="p">);</span>
<span class="c1">// HTML tidy the fetched data. If the C library fails due to an error corresponding to
</span><span class="c1"></span> <span class="c1">// a standard library exception type, throw that. Otherwise, synthesise an exception
</span><span class="c1"></span> <span class="c1">// ptr of type tidylib_error which stores the error code returned in an error code with
</span><span class="c1"></span> <span class="c1">// generic category (i.e. errno domain).
</span><span class="c1"></span> <span class="c1">// TRY operation below will return that exception ptr to be rethrown in the caller.
</span><span class="c1"></span> <span class="c1">// Otherwise the tidied data is returned into holdmem, with the string view updated to
</span><span class="c1"></span> <span class="c1">// point at the tidied data.
</span><span class="c1"></span> <span class="n">BOOST_OUTCOME_TRY</span><span class="p">(</span><span class="k">auto</span> <span class="n">holdmem</span><span class="p">,</span> <span class="n">ext</span><span class="p">(</span><span class="n">tidy_html</span><span class="p">(</span><span class="n">data_view</span><span class="p">)));</span>
<span class="c1">// Write the tidied data to some file. If the write fails, synthesise a filesystem_error
</span><span class="c1"></span> <span class="c1">// exception ptr exactly as if one called filelib::write_file(data_view).value().
</span><span class="c1"></span> <span class="n">BOOST_OUTCOME_TRY</span><span class="p">(</span><span class="k">auto</span> <span class="n">written</span><span class="p">,</span> <span class="n">ext</span><span class="p">(</span><span class="n">filelib</span><span class="o">::</span><span class="n">write_file</span><span class="p">(</span><span class="n">data_view</span><span class="p">)));</span>
<span class="k">return</span> <span class="nf">success</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span> <span class="c1">// namespace app
</span><span class="c1"></span></code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/finale.cpp#L377" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>The curiosity will be surely the <code>ext()</code> markup function, which needs
explaining. It was felt
important during Outcome&rsquo;s design that <code>value_or_error</code> conversions never
be implicit, as they almost always represent a transition across an
ABI or semantic boundary. They are also usually non-trivial to implement
and compile, and it was felt important that the programmer ought to
always mark the semantic boundary transition at the point of every use,
as considerable amounts of code may execute.</p>
<p>How the end user chooses to mark up their code is up to them, however
above we use a simple <code>ext()</code> function to mark up that the function
being called is <em>external</em> to the application. This ticks our box of
requiring the documentation, at the point of use, of every transition
in failure handling boundaries.</p>
<p>Note that we are able to use <code>TRY</code> as normal throughout this function.
Everything &ldquo;just works&rdquo;.</p>
<p>And most especially note that we never, <strong>at any stage</strong>, needed to modify
the source code of <code>httplib</code>, <code>tidylib</code> nor <code>filelib</code>, nor inject
custom things into their namespaces. This entire worked example was
achieved solely by <code>app</code> based customisation points, and via <code>convert</code>.</p>
</div><p><small>Last revised: December 15, 2020 at 12:22:39 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/interop/app-map-tidylib.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/conclusion.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>

View File

@@ -0,0 +1,70 @@
<!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>Mapping the File I/O library into the Application - 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="../../../tutorial/advanced/interop/app-map-httplib2.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/app-map-tidylib.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">Mapping the File I/O library into the Application</h1></div></div></div>
<p>To handle the File I/O library, once again we turn to custom <code>ValueOrError</code>
converters:</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="c1">// Inject custom ValueOrError conversion
</span><span class="c1"></span><span class="n">BOOST_OUTCOME_V2_NAMESPACE_BEGIN</span>
<span class="k">namespace</span> <span class="n">convert</span>
<span class="p">{</span>
<span class="c1">// Provide custom ValueOrError conversion from filelib::result&lt;U&gt;
</span><span class="c1"></span> <span class="c1">// into any app::outcome&lt;T&gt;
</span><span class="c1"></span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">T</span><span class="p">,</span> <span class="k">class</span><span class="err"> </span><span class="nc">U</span><span class="o">&gt;</span> <span class="c1">//
</span><span class="c1"></span> <span class="k">struct</span> <span class="n">value_or_error</span><span class="o">&lt;</span><span class="n">app</span><span class="o">::</span><span class="n">outcome</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">filelib</span><span class="o">::</span><span class="n">result</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;&gt;</span>
<span class="p">{</span>
<span class="c1">// True to indicate that this converter wants `result`/`outcome`
</span><span class="c1"></span> <span class="c1">// to NOT reject all other `result`
</span><span class="c1"></span> <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">bool</span> <span class="n">enable_result_inputs</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="c1">// False to indicate that this converter wants `outcome` to NOT
</span><span class="c1"></span> <span class="c1">// reject all other `outcome`
</span><span class="c1"></span> <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">bool</span> <span class="n">enable_outcome_inputs</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">X</span><span class="p">,</span> <span class="c1">//
</span><span class="c1"></span> <span class="k">typename</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">enable_if_t</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">is_same</span><span class="o">&lt;</span><span class="n">filelib</span><span class="o">::</span><span class="n">result</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">decay_t</span><span class="o">&lt;</span><span class="n">X</span><span class="o">&gt;&gt;::</span><span class="n">value</span> <span class="c1">//
</span><span class="c1"></span> <span class="o">&amp;&amp;</span> <span class="n">std</span><span class="o">::</span><span class="n">is_constructible</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span> <span class="n">U</span><span class="o">&gt;::</span><span class="n">value</span><span class="o">&gt;&gt;</span> <span class="c1">//
</span><span class="c1"></span> <span class="k">constexpr</span> <span class="n">app</span><span class="o">::</span><span class="n">outcome</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="k">operator</span><span class="p">()(</span><span class="n">X</span> <span class="o">&amp;&amp;</span><span class="n">src</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// Forward any successful value
</span><span class="c1"></span> <span class="k">if</span><span class="p">(</span><span class="n">src</span><span class="p">.</span><span class="n">has_value</span><span class="p">())</span>
<span class="p">{</span>
<span class="k">return</span> <span class="p">{</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">X</span><span class="o">&gt;</span><span class="p">(</span><span class="n">src</span><span class="p">).</span><span class="n">value</span><span class="p">()};</span>
<span class="p">}</span>
<span class="c1">// Synthesise a filesystem_error, exactly as if someone had
</span><span class="c1"></span> <span class="c1">// called src.value()
</span><span class="c1"></span> <span class="k">auto</span> <span class="o">&amp;</span><span class="n">fi</span> <span class="o">=</span> <span class="n">src</span><span class="p">.</span><span class="n">error</span><span class="p">();</span>
<span class="n">BOOST_OUTCOME_V2_NAMESPACE</span><span class="o">::</span><span class="n">try_throw_std_exception_from_error</span><span class="p">(</span><span class="n">fi</span><span class="p">.</span><span class="n">ec</span><span class="p">);</span> <span class="c1">// might throw
</span><span class="c1"></span> <span class="k">return</span> <span class="p">{</span><span class="n">std</span><span class="o">::</span><span class="n">make_exception_ptr</span><span class="p">(</span> <span class="c1">//
</span><span class="c1"></span> <span class="n">filelib</span><span class="o">::</span><span class="n">filesystem_error</span><span class="p">(</span><span class="n">fi</span><span class="p">.</span><span class="n">ec</span><span class="p">.</span><span class="n">message</span><span class="p">(),</span> <span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">fi</span><span class="p">.</span><span class="n">path1</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">fi</span><span class="p">.</span><span class="n">path2</span><span class="p">),</span> <span class="n">fi</span><span class="p">.</span><span class="n">ec</span><span class="p">))};</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="p">}</span> <span class="c1">// namespace convert
</span><span class="c1"></span><span class="n">BOOST_OUTCOME_V2_NAMESPACE_END</span>
</code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/finale.cpp#L296" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>Note that the conversion exactly duplicates the implementation of
<code>throw_as_system_error_with_payload(failure_info fi)</code> from
namespace <code>filelib</code>. In a production implementation, you probably
ought to call that function and catch the exception it throws
into a pointer, as that would be more long term maintainable.</p>
</div><p><small>Last revised: February 11, 2019 at 13:38:04 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/interop/app-map-httplib2.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/app-map-tidylib.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>

View File

@@ -0,0 +1,97 @@
<!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>Mapping the HTTP library into the Application &lt;sup&gt;1&lt;/sup&gt;&frasl;&lt;sub&gt;2&lt;/sub&gt; - 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="../../../tutorial/advanced/interop/app.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/app-map-httplib2.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">Mapping the HTTP library into the Application <code>1/2</code></h1></div></div></div>
<p>Firstly, remember that we are the application writer who has the problem of
integrating three third party libraries into our application&rsquo;s Outcome-based
failure handling mechanism. We cannot modify those third party library
sources; we must be <em>non-intrusive</em>.</p>
<p>We start by dealing with the HTTP library. We will integrate this
into our application by wrapping up <code>httplib::failure</code> into a custom
STL exception type. We then type erase it into an <code>exception_ptr</code>
instance. Please note that this code is exclusively defined in the <code>app</code> namespace:</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="k">namespace</span> <span class="n">app</span>
<span class="p">{</span>
<span class="c1">// Specialise an exception type for httplib errors
</span><span class="c1"></span> <span class="k">struct</span> <span class="nl">httplib_error</span> <span class="p">:</span> <span class="n">std</span><span class="o">::</span><span class="n">runtime_error</span>
<span class="p">{</span>
<span class="c1">// passthrough
</span><span class="c1"></span> <span class="k">using</span> <span class="n">std</span><span class="o">::</span><span class="n">runtime_error</span><span class="o">::</span><span class="n">runtime_error</span><span class="p">;</span>
<span class="n">httplib_error</span><span class="p">(</span><span class="n">httplib</span><span class="o">::</span><span class="n">failure</span> <span class="n">_failure</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">msg</span><span class="p">)</span>
<span class="o">:</span> <span class="n">std</span><span class="o">::</span><span class="n">runtime_error</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">msg</span><span class="p">))</span>
<span class="p">,</span> <span class="n">failure</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">_failure</span><span class="p">))</span>
<span class="p">{</span>
<span class="p">}</span>
<span class="c1">// the original failure
</span><span class="c1"></span> <span class="n">httplib</span><span class="o">::</span><span class="n">failure</span> <span class="n">failure</span><span class="p">;</span>
<span class="p">};</span>
<span class="c1">// Type erase httplib::result&lt;U&gt; into a httplib_error exception ptr
</span><span class="c1"></span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">U</span><span class="o">&gt;</span> <span class="c1">//
</span><span class="c1"></span> <span class="kr">inline</span> <span class="n">std</span><span class="o">::</span><span class="n">exception_ptr</span> <span class="n">make_httplib_exception</span><span class="p">(</span><span class="k">const</span> <span class="n">httplib</span><span class="o">::</span><span class="n">result</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;</span> <span class="o">&amp;</span><span class="n">src</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">str</span><span class="p">(</span><span class="s">&#34;httplib failed with error &#34;</span><span class="p">);</span>
<span class="k">switch</span><span class="p">(</span><span class="n">src</span><span class="p">.</span><span class="n">error</span><span class="p">().</span><span class="n">status</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">case</span> <span class="n">httplib</span><span class="o">::</span><span class="n">status_code</span><span class="o">::</span><span class="nl">success</span><span class="p">:</span>
<span class="n">str</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#34;success&#34;</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="n">httplib</span><span class="o">::</span><span class="n">status_code</span><span class="o">::</span><span class="nl">bad_request</span><span class="p">:</span>
<span class="n">str</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#34;bad request&#34;</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="n">httplib</span><span class="o">::</span><span class="n">status_code</span><span class="o">::</span><span class="nl">access_denied</span><span class="p">:</span>
<span class="n">str</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#34;access denied&#34;</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="n">httplib</span><span class="o">::</span><span class="n">status_code</span><span class="o">::</span><span class="nl">logon_failed</span><span class="p">:</span>
<span class="n">str</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#34;logon failed&#34;</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="n">httplib</span><span class="o">::</span><span class="n">status_code</span><span class="o">::</span><span class="nl">forbidden</span><span class="p">:</span>
<span class="n">str</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#34;forbidden&#34;</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="n">httplib</span><span class="o">::</span><span class="n">status_code</span><span class="o">::</span><span class="nl">not_found</span><span class="p">:</span>
<span class="n">str</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#34;not found&#34;</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="n">httplib</span><span class="o">::</span><span class="n">status_code</span><span class="o">::</span><span class="nl">internal_error</span><span class="p">:</span>
<span class="n">str</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#34;internal error&#34;</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">str</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#34; [url was &#34;</span><span class="p">);</span>
<span class="n">str</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">src</span><span class="p">.</span><span class="n">error</span><span class="p">().</span><span class="n">url</span><span class="p">);</span>
<span class="n">str</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">&#34;]&#34;</span><span class="p">);</span>
<span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">make_exception_ptr</span><span class="p">(</span><span class="n">httplib_error</span><span class="p">(</span><span class="n">src</span><span class="p">.</span><span class="n">error</span><span class="p">(),</span> <span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">str</span><span class="p">)));</span>
<span class="p">}</span>
<span class="p">}</span> <span class="c1">// namespace app
</span><span class="c1"></span></code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/finale.cpp#L202" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>Most of the complexity in this code fragment is driven by the need to create
some sort of descriptive string for <code>std::runtime_error</code>
so its <code>.what()</code> returns a useful summary of the original failure. This
is the main purpose of the <code>app::make_httplib_exception()</code> function.</p>
<p>(Note that if you have Reflection in your C++ compiler, it may be possible to script
the conversion of enum values to string representations)</p>
<p>The only real thing to note about <code>app::httplib_error</code> is that it squirrels away
the original <code>httplib::failure</code> in case that is ever needed.</p>
</div><p><small>Last revised: February 11, 2019 at 13:38:04 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/interop/app.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/app-map-httplib2.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>

View File

@@ -0,0 +1,94 @@
<!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>Mapping the HTTP library into the Application &lt;sup&gt;2&lt;/sup&gt;&frasl;&lt;sub&gt;2&lt;/sub&gt; - 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="../../../tutorial/advanced/interop/app-map-httplib1.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/app-map-filelib.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">Mapping the HTTP library into the Application <code>2/2</code></h1></div></div></div>
<p>If you remember the tutorial section on the <a href="../value-or-error"><code>value_or_error</code> Concept</a>,
this is an example of how to implement a custom <code>value_or_error</code> Concept converter
in Outcome:</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="c1">// Inject custom ValueOrError conversion
</span><span class="c1"></span><span class="n">BOOST_OUTCOME_V2_NAMESPACE_BEGIN</span>
<span class="k">namespace</span> <span class="n">convert</span>
<span class="p">{</span>
<span class="c1">// Provide custom ValueOrError conversion from
</span><span class="c1"></span> <span class="c1">// httplib::result&lt;U&gt; into any app::outcome&lt;T&gt;
</span><span class="c1"></span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">T</span><span class="p">,</span> <span class="k">class</span><span class="err"> </span><span class="nc">U</span><span class="o">&gt;</span> <span class="c1">//
</span><span class="c1"></span> <span class="k">struct</span> <span class="n">value_or_error</span><span class="o">&lt;</span><span class="n">app</span><span class="o">::</span><span class="n">outcome</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">httplib</span><span class="o">::</span><span class="n">result</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;&gt;</span>
<span class="p">{</span>
<span class="c1">// False to indicate that this converter wants `result`/`outcome`
</span><span class="c1"></span> <span class="c1">// to NOT reject all other `result`
</span><span class="c1"></span> <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">bool</span> <span class="n">enable_result_inputs</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="c1">// False to indicate that this converter wants `outcome` to NOT
</span><span class="c1"></span> <span class="c1">// reject all other `outcome`
</span><span class="c1"></span> <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">bool</span> <span class="n">enable_outcome_inputs</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">X</span><span class="p">,</span> <span class="c1">//
</span><span class="c1"></span> <span class="k">typename</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">enable_if_t</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">is_same</span><span class="o">&lt;</span><span class="n">httplib</span><span class="o">::</span><span class="n">result</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">decay_t</span><span class="o">&lt;</span><span class="n">X</span><span class="o">&gt;&gt;::</span><span class="n">value</span> <span class="c1">//
</span><span class="c1"></span> <span class="o">&amp;&amp;</span> <span class="n">std</span><span class="o">::</span><span class="n">is_constructible</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span> <span class="n">U</span><span class="o">&gt;::</span><span class="n">value</span><span class="o">&gt;&gt;</span> <span class="c1">//
</span><span class="c1"></span> <span class="k">constexpr</span> <span class="n">app</span><span class="o">::</span><span class="n">outcome</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span> <span class="k">operator</span><span class="p">()(</span><span class="n">X</span> <span class="o">&amp;&amp;</span><span class="n">src</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// Forward any successful value, else synthesise an exception ptr
</span><span class="c1"></span> <span class="k">return</span> <span class="n">src</span><span class="p">.</span><span class="n">has_value</span><span class="p">()</span> <span class="o">?</span> <span class="c1">//
</span><span class="c1"></span> <span class="n">app</span><span class="o">::</span><span class="n">outcome</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">{</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">X</span><span class="o">&gt;</span><span class="p">(</span><span class="n">src</span><span class="p">).</span><span class="n">value</span><span class="p">()}</span> <span class="c1">//
</span><span class="c1"></span> <span class="o">:</span>
<span class="n">app</span><span class="o">::</span><span class="n">outcome</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">{</span><span class="n">app</span><span class="o">::</span><span class="n">make_httplib_exception</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">X</span><span class="o">&gt;</span><span class="p">(</span><span class="n">src</span><span class="p">))};</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="p">}</span> <span class="c1">// namespace convert
</span><span class="c1"></span><span class="n">BOOST_OUTCOME_V2_NAMESPACE_END</span>
</code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/finale.cpp#L257" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>The first thing that you should note is that these custom converters must be injected
directly into the <code>BOOST_OUTCOME_V2_NAMESPACE::convert</code> namespace, and they must partially
or completely specialise <a href="../../../reference/converters/value_or_error.html" class="api-reference"><code>value_or_error&lt;T, U&gt;</code></a>
. Here we specialise the
converter for <code>value_or_error</code> conversions from <code>httplib::result&lt;U&gt;</code> to <code>app::outcome&lt;T&gt;</code>
i.e. from our third party HTTP library&rsquo;s error type into our application&rsquo;s <code>outcome</code>
type (which is unique to our application, as we hard code an <code>app</code>-local error type).</p>
<p>The second thing to note is that you need to set <code>enable_result_inputs</code> and <code>enable_outcome_inputs</code>
appropriately, otherwise <code>result</code> and <code>outcome</code> inputs will not be matched by this
converter<sup class="footnote-ref" id="fnref:1"><a href="#fn:1">1</a></sup>. In this converter, we really do wish to convert other <code>result</code> and
<code>outcome</code> inputs, so we mark these booleans as <code>true</code>.</p>
<p>The third thing to note is the requirements on <code>operator()</code>. If the requirements are
not met, the <code>value_or_error</code> converting constructor in <code>basic_result</code> and <code>basic_outcome</code>
disables. Note the requirement that the decayed <code>operator()</code> input <code>X</code> matches
<code>httplib::result&lt;U&gt;</code>, and that <code>T</code> is constructible from <code>U</code>. This means that the
<a href="../../../reference/types/basic_result/explicit_valueorerror_converting_constructor.html" class="api-reference"><code>explicit basic_result(concepts::value_or_error&lt;T, E&gt; &amp;&amp;)</code></a>
and <a href="../../../reference/types/basic_outcome/explicit_valueorerror_converting_constructor.html" class="api-reference"><code>explicit basic_outcome(concepts::value_or_error&lt;T, E&gt; &amp;&amp;)</code></a>
constructors are available if, and only if, the input type is a <code>httplib::result&lt;U&gt;</code>,
and the result&rsquo;s value type is constructible from the input&rsquo;s value type.</p>
<p>If <code>operator()</code> is available, it naturally converts a <code>httplib::result&lt;U&gt;</code> into an
<code>app::outcome&lt;T&gt;</code> by either forwarding any success as-is, or calling <code>app::make_httplib_exception()</code>
to type erase the <code>httplib::failure</code> into an <code>app::httplib_error</code>.</p>
<div class="footnotes">
<hr />
<ol>
<li id="fn:1">Here we refer to <code>result</code> and <code>outcome</code> as defined by this specific Outcome library. If <code>result</code> or <code>outcome</code> from another Outcome implementation is seen, those <strong>always</strong> must get parsed via the <code>ValueOrError</code> matching conversion framework.
<a class="footnote-return" href="#fnref:1"><sup>[return]</sup></a></li>
</ol>
</div>
</div><p><small>Last revised: December 15, 2020 at 12:22:39 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/interop/app-map-httplib1.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/app-map-filelib.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>

View File

@@ -0,0 +1,66 @@
<!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>Mapping the HTMLTidy library into the Application - 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="../../../tutorial/advanced/interop/app-map-filelib.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/app-go.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">Mapping the HTMLTidy library into the Application</h1></div></div></div>
<p>Once again, we create a custom STL exception type to represent failure
from the HTMLTidy library. We also create an <code>app</code> namespace wrapper
for the C <code>tidy_html()</code> function which is more C++ friendly.</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="k">namespace</span> <span class="n">app</span>
<span class="p">{</span>
<span class="c1">// Specialise an exception type for tidylib errors
</span><span class="c1"></span> <span class="k">struct</span> <span class="nl">tidylib_error</span> <span class="p">:</span> <span class="n">std</span><span class="o">::</span><span class="n">system_error</span>
<span class="p">{</span>
<span class="c1">// passthrough
</span><span class="c1"></span> <span class="k">using</span> <span class="n">std</span><span class="o">::</span><span class="n">system_error</span><span class="o">::</span><span class="n">system_error</span><span class="p">;</span>
<span class="n">tidylib_error</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
<span class="k">explicit</span> <span class="nf">tidylib_error</span><span class="p">(</span><span class="kt">int</span> <span class="n">c</span><span class="p">)</span>
<span class="o">:</span> <span class="n">std</span><span class="o">::</span><span class="n">system_error</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">generic_category</span><span class="p">())</span>
<span class="p">{</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="c1">// Create a C++ invoking wrapper for the tidylib C API, modifying data with the returned data,
</span><span class="c1"></span> <span class="c1">// returing a unique_ptr to release storage on scope exit.
</span><span class="c1"></span> <span class="k">struct</span> <span class="n">call_free</span>
<span class="p">{</span>
<span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">T</span><span class="o">&gt;</span> <span class="kt">void</span> <span class="k">operator</span><span class="p">()(</span><span class="n">T</span> <span class="o">*</span><span class="n">p</span><span class="p">)</span> <span class="p">{</span> <span class="o">::</span><span class="n">free</span><span class="p">(</span><span class="n">p</span><span class="p">);</span> <span class="p">}</span>
<span class="p">};</span>
<span class="kr">inline</span> <span class="n">outcome</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="kt">char</span><span class="p">,</span> <span class="n">call_free</span><span class="o">&gt;&gt;</span> <span class="n">tidy_html</span><span class="p">(</span><span class="n">string_view</span> <span class="o">&amp;</span><span class="n">data</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">out</span> <span class="o">=</span> <span class="k">nullptr</span><span class="p">;</span>
<span class="n">size_t</span> <span class="n">outlen</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">errcode</span> <span class="o">=</span> <span class="o">::</span><span class="n">tidy_html</span><span class="p">(</span><span class="o">&amp;</span><span class="n">out</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">outlen</span><span class="p">,</span> <span class="n">data</span><span class="p">.</span><span class="n">data</span><span class="p">(),</span> <span class="n">data</span><span class="p">.</span><span class="n">size</span><span class="p">());</span>
<span class="k">if</span><span class="p">(</span><span class="n">errcode</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// If the error code matches a standard STL exception, throw as that.
</span><span class="c1"></span> <span class="n">BOOST_OUTCOME_V2_NAMESPACE</span><span class="o">::</span><span class="n">try_throw_std_exception_from_error</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">error_code</span><span class="p">(</span><span class="n">errcode</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">generic_category</span><span class="p">()));</span>
<span class="c1">// Otherwise wrap the error code into a tidylib_error exception throw
</span><span class="c1"></span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">make_exception_ptr</span><span class="p">(</span><span class="n">tidylib_error</span><span class="p">(</span><span class="n">errcode</span><span class="p">));</span>
<span class="p">}</span>
<span class="c1">// Reset input view to tidied html
</span><span class="c1"></span> <span class="n">data</span> <span class="o">=</span> <span class="n">string_view</span><span class="p">(</span><span class="n">out</span><span class="p">,</span> <span class="n">outlen</span><span class="p">);</span>
<span class="c1">// Return a unique ptr to release storage on scope exit
</span><span class="c1"></span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="kt">char</span><span class="p">,</span> <span class="n">call_free</span><span class="o">&gt;</span><span class="p">(</span><span class="n">out</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span> <span class="c1">// namespace app
</span><span class="c1"></span></code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/finale.cpp#L336" class="code-snippet-url" target="_blank">View this code on Github</a></div>
</div><p><small>Last revised: February 08, 2019 at 22:18:08 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/interop/app-map-filelib.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/app-go.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>

View File

@@ -0,0 +1,67 @@
<!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>The Application - 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="../../../tutorial/advanced/interop/filelib.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/app-map-httplib1.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">The Application</h1></div></div></div>
<p>The application is of course also based on Outcome, and like the HTTP library
is also of mixed-failure design in that failure can be returned via error code,
type erased <code>exception_ptr</code> or indeed a C++ exception throw.</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="c1">// This is the namespace of the application which is connecting together the httplib,
</span><span class="c1">// filelib and tidylib libraries into a solution.
</span><span class="c1"></span><span class="k">namespace</span> <span class="n">app</span>
<span class="p">{</span>
<span class="c1">// Create an ADL bridge so copy/move hooks will be searched for in this namespace
</span><span class="c1"></span> <span class="k">struct</span> <span class="nl">error_code</span> <span class="p">:</span> <span class="k">public</span> <span class="n">std</span><span class="o">::</span><span class="n">error_code</span>
<span class="p">{</span>
<span class="c1">// passthrough
</span><span class="c1"></span> <span class="k">using</span> <span class="n">std</span><span class="o">::</span><span class="n">error_code</span><span class="o">::</span><span class="n">error_code</span><span class="p">;</span>
<span class="n">error_code</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
<span class="n">error_code</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">error_code</span> <span class="n">ec</span><span class="p">)</span>
<span class="o">:</span> <span class="n">std</span><span class="o">::</span><span class="n">error_code</span><span class="p">(</span><span class="n">ec</span><span class="p">)</span>
<span class="p">{</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="c1">// Localise an outcome implementation for this namespace
</span><span class="c1"></span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">using</span> <span class="n">outcome</span> <span class="o">=</span> <span class="c1">//
</span><span class="c1"></span> <span class="n">BOOST_OUTCOME_V2_NAMESPACE</span><span class="o">::</span><span class="n">outcome</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span> <span class="n">error_code</span> <span class="cm">/*, std::exception_ptr */</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">using</span> <span class="n">BOOST_OUTCOME_V2_NAMESPACE</span><span class="o">::</span><span class="n">success</span><span class="p">;</span>
<span class="p">}</span> <span class="c1">// namespace app
</span><span class="c1"></span></code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/finale.cpp#L178" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>Here we localise a passthrough <code>error_code</code> solely for the purpose of ADL bridging, otherwise
the localised <code>outcome</code> configured is the default one which comes with Outcome.
<a href="../../../tutorial/advanced/hooks/adl_bridging.html">We covered this technique of &ldquo;passthrough <code>error_code</code>&rdquo; earlier in this tutorial</a>.</p>
<p>The way we are going to configure interop is as follows:</p>
<ol>
<li>The application shall use <code>error_code</code> for anticipated failure and C++
exception throws for unanticipated failure.</li>
<li>We shall choose the convention that <code>app::outcome</code> with exception ptr
solely and exclusively represents a type erased failure from a third party
library.</li>
</ol>
<p>Thus if one calls <code>.value()</code> on an <code>app::outcome</code>, both anticipated failure
within the app and type erased failure from a third party library shall be
converted to a C++ exception throw.</p>
</div><p><small>Last revised: February 11, 2019 at 17:14:51 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/interop/filelib.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/app-map-httplib1.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>

View File

@@ -0,0 +1,38 @@
<!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>Conclusion - 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="../../../tutorial/advanced/interop/app-go.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../recipes.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">Conclusion</h1></div></div></div>
<p>This worked example was in fact excessively complex: a quicker route
to achieving the same thing would be to add explicit converting constructors
to <code>app::error_code</code> for each of the third party library <code>E</code> types.
One then could have saved oneself with having to bother injecting
custom converters into the <code>BOOST_OUTCOME_V2_NAMESPACE::convert</code> namespace.
If you control your application&rsquo;s <code>E</code> type, then that is probably a
better, and certainly simpler, approach.</p>
<p>However there are occasions when you don&rsquo;t have control over the
implementation of the destination <code>E</code> type e.g. in callbacks. Outcome&rsquo;s <code>value_or_error</code>
infrastructure lets you inject custom interop code for any pair
of incommensurate third party <code>E</code> types, without needing to modify either&rsquo;s
source code.</p>
<p>This is without doubt a &ldquo;power users&rdquo; feature, but
one which will prove useful as <code>T|E</code> based C++ code proliferates.</p>
</div><p><small>Last revised: December 15, 2020 at 12:22:39 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/interop/app-go.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../recipes.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>

View File

@@ -0,0 +1,65 @@
<!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>The File I/O library - 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="../../../tutorial/advanced/interop/tidylib.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/app.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">The File I/O library</h1></div></div></div>
<p>The File I/O library we shall be using is very similar <a href="../../payload/copy_file2">to the one we saw earlier
in this tutorial</a>:</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="c1">// You may remember this from the tutorial section on Custom Payloads
</span><span class="c1"></span><span class="k">namespace</span> <span class="n">filelib</span>
<span class="p">{</span>
<span class="c1">// Error code + paths related to a failure. Also causes ADL discovery
</span><span class="c1"></span> <span class="c1">// to check this namespace.
</span><span class="c1"></span> <span class="k">struct</span> <span class="n">failure_info</span>
<span class="p">{</span>
<span class="n">std</span><span class="o">::</span><span class="n">error_code</span> <span class="n">ec</span><span class="p">;</span>
<span class="n">path</span> <span class="n">path1</span><span class="p">{},</span> <span class="n">path2</span><span class="p">{};</span>
<span class="p">};</span>
<span class="c1">// Tell Outcome that failure_info is to be treated as a std::error_code
</span><span class="c1"></span> <span class="kr">inline</span> <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">error_code</span> <span class="o">&amp;</span><span class="n">make_error_code</span><span class="p">(</span><span class="k">const</span> <span class="n">failure_info</span> <span class="o">&amp;</span><span class="n">fi</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">fi</span><span class="p">.</span><span class="n">ec</span><span class="p">;</span> <span class="p">}</span>
<span class="c1">// Tell Outcome that no-value observation should throw a custom exception
</span><span class="c1"></span> <span class="kr">inline</span> <span class="kt">void</span> <span class="n">outcome_throw_as_system_error_with_payload</span><span class="p">(</span><span class="n">failure_info</span> <span class="n">fi</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">// If the error code is not filesystem related e.g. ENOMEM, throw that
</span><span class="c1"></span> <span class="c1">// as a standard STL exception.
</span><span class="c1"></span> <span class="n">BOOST_OUTCOME_V2_NAMESPACE</span><span class="o">::</span><span class="n">try_throw_std_exception_from_error</span><span class="p">(</span><span class="n">fi</span><span class="p">.</span><span class="n">ec</span><span class="p">);</span>
<span class="c1">// Throw the exact same filesystem_error exception which the throwing
</span><span class="c1"></span> <span class="c1">// copy_file() edition does.
</span><span class="c1"></span> <span class="k">throw</span> <span class="nf">filesystem_error</span><span class="p">(</span><span class="n">fi</span><span class="p">.</span><span class="n">ec</span><span class="p">.</span><span class="n">message</span><span class="p">(),</span> <span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">fi</span><span class="p">.</span><span class="n">path1</span><span class="p">),</span> <span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">fi</span><span class="p">.</span><span class="n">path2</span><span class="p">),</span> <span class="n">fi</span><span class="p">.</span><span class="n">ec</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// Localise a result implementation specific to this namespace.
</span><span class="c1"></span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">T</span><span class="o">&gt;</span> <span class="k">using</span> <span class="n">result</span> <span class="o">=</span> <span class="n">BOOST_OUTCOME_V2_NAMESPACE</span><span class="o">::</span><span class="n">result</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span> <span class="n">failure_info</span><span class="o">&gt;</span><span class="p">;</span>
<span class="c1">// Writes a chunk of data to some file. Returns bytes written, or
</span><span class="c1"></span> <span class="c1">// failure_info. Never throws exceptions.
</span><span class="c1"></span> <span class="n">result</span><span class="o">&lt;</span><span class="n">size_t</span><span class="o">&gt;</span> <span class="n">write_file</span><span class="p">(</span><span class="n">string_view</span> <span class="n">chunk</span><span class="p">)</span> <span class="k">noexcept</span><span class="p">;</span>
<span class="p">}</span> <span class="c1">// namespace filelib
</span><span class="c1"></span></code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/finale.cpp#L110" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>This uses the advanced Outcome feature of programming the lazy synthesis of
custom C++ exception throws from a payload carrying <code>E</code> type called <code>failure_info</code>.
Like the HTTP library, it too template aliases a localised <code>result</code> implementation
into its namespace with ADL bridging so Outcome customisation points can be
discovered.</p>
</div><p><small>Last revised: February 08, 2019 at 22:18:08 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/interop/tidylib.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/app.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>

View File

@@ -0,0 +1,73 @@
<!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>The HTTP library - 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="../../../tutorial/advanced/interop/value-or-error.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/tidylib.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">The HTTP library</h1></div></div></div>
<p>Let us imagine a simple application: it fetches a HTTP page using a HTTP library,
sends it through HTML tidy via the htmltidy library, and then writes it to disc
using a filelib library. So three third party libraries, two using Outcome in
incompatible ways, and the third being a C library just for kicks.</p>
<p>Let us imagine that the HTTP library has the following public interface:</p>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="c1">// This is some standalone library implementing high level HTTP
</span><span class="c1"></span><span class="k">namespace</span> <span class="n">httplib</span>
<span class="p">{</span>
<span class="c1">// These are the error code that this HTTP library can return
</span><span class="c1"></span> <span class="k">enum</span> <span class="k">class</span><span class="err"> </span><span class="nc">status_code</span>
<span class="p">{</span>
<span class="n">success</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="c1">// not the HTTP success code of 200
</span><span class="c1"></span>
<span class="c1">// A subset of all HTTP status codes for brevity
</span><span class="c1"></span> <span class="n">bad_request</span> <span class="o">=</span> <span class="mi">400</span><span class="p">,</span>
<span class="n">access_denied</span> <span class="o">=</span> <span class="mi">401</span><span class="p">,</span>
<span class="n">logon_failed</span> <span class="o">=</span> <span class="mi">402</span><span class="p">,</span>
<span class="n">forbidden</span> <span class="o">=</span> <span class="mi">403</span><span class="p">,</span>
<span class="n">not_found</span> <span class="o">=</span> <span class="mi">404</span><span class="p">,</span>
<span class="n">internal_error</span> <span class="o">=</span> <span class="mi">500</span>
<span class="p">};</span>
<span class="c1">// This is the error type that this HTTP library can return
</span><span class="c1"></span> <span class="k">struct</span> <span class="n">failure</span>
<span class="p">{</span>
<span class="n">status_code</span> <span class="n">status</span><span class="p">{</span><span class="n">status_code</span><span class="o">::</span><span class="n">success</span><span class="p">};</span>
<span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">url</span><span class="p">{};</span> <span class="c1">// The failing URL
</span><span class="c1"></span> <span class="p">};</span>
<span class="c1">// Localise a result implementation to this library, holding
</span><span class="c1"></span> <span class="c1">// the logic error of incorrect observation to mean program
</span><span class="c1"></span> <span class="c1">// termination.
</span><span class="c1"></span> <span class="k">template</span> <span class="o">&lt;</span><span class="k">class</span><span class="err"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">using</span> <span class="n">result</span> <span class="o">=</span> <span class="c1">//
</span><span class="c1"></span> <span class="n">BOOST_OUTCOME_V2_NAMESPACE</span><span class="o">::</span><span class="n">result</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span> <span class="n">failure</span><span class="p">,</span> <span class="n">BOOST_OUTCOME_V2_NAMESPACE</span><span class="o">::</span><span class="n">policy</span><span class="o">::</span><span class="n">terminate</span><span class="o">&gt;</span><span class="p">;</span>
<span class="cm">/* Performs a HTTP GET on the url, returning the body if successful,
</span><span class="cm"> a failure with status_code if unsuccessful at the HTTP level, or a
</span><span class="cm"> C++ exception throw if something catastrophic happened e.g. bad_alloc
</span><span class="cm"> */</span>
<span class="n">result</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">get</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">url</span><span class="p">);</span>
<span class="p">}</span> <span class="c1">// namespace httplib
</span><span class="c1"></span></code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/finale.cpp#L47" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>The HTTP library is a mixed-failure design. Likely failures (HTTP status codes)
are returned via <code>httplib::failure</code>, unlikely failures (e.g. out of memory)
are returned via throw of the usual STL exception types.</p>
<p>The sole API we bother describing is an implementation of HTTP GET. It fetches
a URL, and either returns the contents or the failure reason why not.</p>
</div><p><small>Last revised: February 08, 2019 at 22:18:08 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/interop/value-or-error.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/tidylib.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>

View File

@@ -0,0 +1,82 @@
<!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>Incommensurate E types - 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="../../../tutorial/advanced/interop.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/value-or-error.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">Incommensurate E types</h1></div></div></div>
<p>Back in the essential tutorial section on <code>result</code>, we studied a likely very common
initial choice of <code>E</code> type: <a href="../../../tutorial/essential/result.html">a strongly typed enum</a>.
We saw how <a href="../../../motivation/plug_error_code.html">by marking up strongly typed enums to tell the C++ standard library
what they are</a>, they gain implicit convertibility into <code>std::error_code</code>, and we
then pointed out that you might as well now always set <code>E = std::error_code</code>, as that
comes with the enormous advantage that you can use the boilerplate saving
<code>BOOST_OUTCOME_TRY</code> macro when the <code>E</code> type is always the same.</p>
<p>We thus strongly recommend to users that for any given piece of code, always
using the same <code>E</code> type across the codebase is very wise, except where you explicitly want
to prevent implicit propagation of failure up a call stack e.g. local failures in
some domain specific piece of code.</p>
<p>However it is unreasonable to expect that any non-trivial codebase can make do
with <code>E = std::error_code</code>. This is why Outcome allows you to use <a href="../../payload">custom <code>E</code>
types which carry payload</a> in addition to an error code, yet
still have that custom type treated as if a <code>std::error_code</code>, including <a href="../../payload/copy_file3">lazy custom exception
throw synthesis</a>.</p>
<p>All this is good, but if library A uses <code>result&lt;T, libraryA::failure_info&gt;</code>,
and library B uses <code>result&lt;T, libraryB::error_info&gt;</code> and so on, there becomes
a problem for the application writer who is bringing in these third party
dependencies and tying them together into an application. As a general rule,
each third party library author will not have built in explicit interoperation
support for unknown other third party libraries. The problem therefore lands
with the application writer.</p>
<p>The application writer has one of three choices:</p>
<ol>
<li><p>In the application, the form of result used is <code>result&lt;T, std::variant&lt;E1, E2, ...&gt;&gt;</code>
where <code>E1</code>, <code>E2</code> &hellip; are the failure types for every third party library
in use in the application. This has the advantage of preserving the original
information exactly, but comes with a certain amount of use inconvenience
and maybe excessive coupling between high level layers and implementation detail.</p></li>
<li><p>One can translate/map the third party&rsquo;s failure type into the application&rsquo;s
failure type at the point of the failure
exiting the third party library and entering the application. One might do
this, say, with a C preprocessor macro wrapping every invocation of the third
party API from the application. This approach may lose the original failure detail,
or mis-map under certain circumstances if the mapping between the two systems
is not one-one.</p></li>
<li><p>One can type erase the third party&rsquo;s failure type into some application
failure type, which can later be reconstituted if necessary. This is the cleanest
solution with the least coupling issues and no problems with mis-mapping, but
it almost certainly requires the use of <code>malloc</code>, which the previous two did not.</p></li>
</ol>
<p>Things get even more complicated in the presence of callbacks. If in the
callback you supply to library A, you call library B, you may need to insert
switch statement maps or other mechanisms to convert library B&rsquo;s failures into
something library A can understand, and then somehow extract that out &ndash; preferably
without loss of original information &ndash; into the application&rsquo;s failure handling
mechanism if library A subsequently returns failure as well. This implies
transmitting state by which to track these interrelated pieces of failure data.</p>
<p>Let us see what Outcome can do to help the application writer address some of these
issues, next.</p>
</div><p><small>Last revised: February 09, 2019 at 15:18:26 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/interop.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/value-or-error.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>

View File

@@ -0,0 +1,37 @@
<!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>The HTMLTidy library - 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="../../../tutorial/advanced/interop/httplib.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/filelib.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">The HTMLTidy library</h1></div></div></div>
<div class="code-snippet"><div class="highlight"><pre class="chroma"><code class="language-c++" data-lang="c++"><span class="c1">// There actually is a library for tidying HTML into XHTML called HTMLTidy
</span><span class="c1">// See http://www.html-tidy.org/
</span><span class="c1">// HTMLTidy is actually a great tool for dealing with 1990s-era tag soup
</span><span class="c1">// HTML, I highly recommend it.
</span><span class="c1"></span>
<span class="c1">// This isn&#39;t the API for Tidy, but let&#39;s assume it&#39;s a C library returning
</span><span class="c1">// errno domained error codes. out must be freed with free() after use.
</span><span class="c1"></span><span class="k">extern</span> <span class="s">&#34;C&#34;</span> <span class="kt">int</span> <span class="n">tidy_html</span><span class="p">(</span><span class="kt">char</span> <span class="o">**</span><span class="n">out</span><span class="p">,</span> <span class="n">size_t</span> <span class="o">*</span><span class="n">outlen</span><span class="p">,</span> <span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">in</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">inlen</span><span class="p">);</span>
</code></pre></div><a href="https://github.com/boostorg/outcome/tree/master/doc/src/snippets/finale.cpp#L154" class="code-snippet-url" target="_blank">View this code on Github</a></div>
<p>A C API may not initially appear to be a <code>T|E</code> based API, but if failure
returns some domained error code and causes no other effects, and success
returns some value, then it is effectively a &ldquo;split&rdquo; <code>T|E</code> API. The above
is an example of exactly that form of &ldquo;split&rdquo; <code>T|E</code> API.</p>
</div><p><small>Last revised: February 08, 2019 at 22:18:08 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/interop/httplib.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/filelib.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>

View File

@@ -0,0 +1,68 @@
<!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>value_or_error Concept - 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="../../../tutorial/advanced/interop/problem.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/httplib.html"><img src="../../../images/next.png" alt="Next"></a></div><div id="content">
<div class="titlepage"><div><div><h1 style="clear: both">value_or_error Concept</h1></div></div></div>
<p>Something not really mentioned until now is how Outcome interoperates with the proposed
<a href="https://wg21.link/P0323" class="api-reference" target="_blank"><i class="fa fa-book" aria-hidden="true"></i> P0323 <code>std::expected&lt;T, E&gt;</code></a>
, whose design lands in between <a href="../../../reference/aliases/unchecked.html" class="api-reference"><code>unchecked&lt;T, E = varies&gt;</code></a>
and <a href="../../../reference/aliases/checked.html" class="api-reference"><code>checked&lt;T, E = varies&gt;</code></a>
(both of which are type aliases hard coding no-value
policies <a href="../../../tutorial/essential/no-value/builtin.html">as previously covered in this tutorial</a>).</p>
<p>Expected and Outcome are <a href="../../../faq.html#why-doesn-t-outcome-duplicate-std-expected-t-e-s-design">isomorphic to one another in design intent</a>, but interoperation
for code using Expected and Outcome ought to be seamless thanks to the <a href="https://wg21.link/P0786">proposed <code>ValueOrError</code>
concept framework</a>, a subset of which Outcome implements.</p>
<p>The <a href="../../../reference/types/basic_result/explicit_valueorerror_converting_constructor.html" class="api-reference"><code>explicit basic_result(concepts::value_or_error&lt;T, E&gt; &amp;&amp;)</code></a>
and <a href="../../../reference/types/basic_outcome/explicit_valueorerror_converting_constructor.html" class="api-reference"><code>explicit basic_outcome(concepts::value_or_error&lt;T, E&gt; &amp;&amp;)</code></a>
constructors will explicitly construct from any type matching the <a href="../../../reference/types/basic_result/explicit_valueorerror_converting_constructor.html" class="api-reference"><code>concepts::value_or_error&lt;T, E&gt;</code></a>
concept, which includes <code>std::expected&lt;A, B&gt;</code>, if <code>A</code> is constructible to <code>X</code>, and <code>B</code> is
constructible to <code>Y</code>. The <code>value_or_error</code> concept in turn is true if and only if the input type has:</p>
<ol>
<li>A <code>.has_value()</code> observer returning a <code>bool</code>.</li>
<li><code>.value()</code> and <code>.error()</code> observers.</li>
</ol>
<h2 id="implementation">Implementation</h2>
<p>Outcome&rsquo;s machinery for implementing <code>concepts::value_or_error</code> conversion is user extensible by injection
of specialisations of the <a href="../../../reference/converters/value_or_error.html" class="api-reference"><code>value_or_error&lt;T, U&gt;</code></a>
type into the <code>BOOST_OUTCOME_V2_NAMESPACE::convert</code> namespace.</p>
<p>Outcome&rsquo;s default <code>convert::value_or_error&lt;T, U&gt;</code> implementation explicitly
excludes Outcome <code>result</code> and <code>outcome</code> types from the default mechanism as
there is a major gotcha: the <code>value_or_error</code> matched type&rsquo;s <code>.value()</code> is often
not callable in constexpr as it can throw, which makes this conversion mechanism
pretty much useless for constexpr code. Besides, <code>outcome</code> has a converting
constructor overload for <code>result</code> inputs which is constexpr capable.</p>
<p>Note that if you do enable <code>outcome</code> inputs, a <code>result</code> will match an input
<code>outcome</code>, but silently dropping any exception state. This is probably undesirable.</p>
<p>Examples of how to implement your own <code>convert::value_or_error&lt;T, U&gt;</code> converter
is demonstrated in the worked example, next.</p>
</div><p><small>Last revised: December 15, 2020 at 12:22:39 UTC</small></p>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../../../tutorial/advanced/interop/problem.html"><img src="../../../images/prev.png" alt="Prev"></a>
<a accesskey="u" href="../../../tutorial/advanced/interop.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="../../../tutorial/advanced/interop/httplib.html"><img src="../../../images/next.png" alt="Next"></a></div></body>
</html>