<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<!-- 2022-06-17 Fri 05:16 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>P2505R4 Monadic Functions for <code>std::expected</code></title>
<meta name="generator" content="Org mode" />
<meta name="author" content="Jeff Garland" />
<link rel="stylesheet" type="text/css" href="https://fniessen.github.io/org-html-themes/src/readtheorg_theme/css/htmlize.css"/>
<link rel="stylesheet" type="text/css" href="https://fniessen.github.io/org-html-themes/src/readtheorg_theme/css/readtheorg.css"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script type="text/javascript" src="https://fniessen.github.io/org-html-themes/src/lib/js/jquery.stickytableheaders.min.js"></script>
<script type="text/javascript" src="https://fniessen.github.io/org-html-themes/src/readtheorg_theme/js/readtheorg.js"></script>
<script type="text/javascript">
/*
@licstart  The following is the entire license notice for the
JavaScript code in this tag.

Copyright (C) 2012-2019 Free Software Foundation, Inc.

The JavaScript code in this tag is free software: you can
redistribute it and/or modify it under the terms of the GNU
General Public License (GNU GPL) as published by the Free Software
Foundation, either version 3 of the License, or (at your option)
any later version.  The code is distributed WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the GNU GPL for more details.

As additional permission under GNU GPL version 3 section 7, you
may distribute non-source (e.g., minimized or compacted) forms of
that code without the copy of the GNU GPL normally required by
section 4, provided you include this license notice and a URL
through which recipients can access the Corresponding Source.


@licend  The above is the entire license notice
for the JavaScript code in this tag.
*/
<!--/*--><![CDATA[/*><!--*/
 function CodeHighlightOn(elem, id)
 {
   var target = document.getElementById(id);
   if(null != target) {
     elem.cacheClassElem = elem.className;
     elem.cacheClassTarget = target.className;
     target.className = "code-highlighted";
     elem.className   = "code-highlighted";
   }
 }
 function CodeHighlightOff(elem, id)
 {
   var target = document.getElementById(id);
   if(elem.cacheClassElem)
     elem.className = elem.cacheClassElem;
   if(elem.cacheClassTarget)
     target.className = elem.cacheClassTarget;
 }
/*]]>*///-->
</script>
</head>
<body>
<div id="content">
<h1 class="title">P2505R4 Monadic Functions for <code>std::expected</code></h1>
<div id="table-of-contents">
<h2>Table of Contents</h2>
<div id="text-table-of-contents">
<ul>
<li><a href="#orgefab892">Introduction</a></li>
<li><a href="#org8cd6000">Motivation and Scope</a></li>
<li><a href="#orgc58c9fe">Design Considerations</a>
<ul>
<li><a href="#org149cc0f"><code>expected&lt;void, E&gt;</code></a></li>
<li><a href="#org90a5b0c"><code>transform</code> to <code>expected&lt;void, E&gt;</code> return</a></li>
<li><a href="#org4e91148"><code>transform_error</code> function</a></li>
<li><a href="#org8636701">Changing of error return types</a></li>
<li><a href="#orgea68796">Use of deducing-this in the specification</a></li>
<li><a href="#org98e7fda">Adding <code>error_or</code> functions</a></li>
<li><a href="#org69f9e69">Free versus member functions</a></li>
</ul>
</li>
<li><a href="#orga46970a">Other Languages</a></li>
<li><a href="#org76f1262">Implementations</a></li>
<li><a href="#orgfc6b8c3">Wording</a>
<ul>
<li><a href="#orgba93247">Feature Test Macro</a></li>
<li><a href="#org8400a76">Class template expected [expected.expected]</a></li>
<li><a href="#org4569073">Add following at the end [expected.object.observe] Observers:</a></li>
<li><a href="#orgd056f38">Add a new sub-clause [expected.object.monadic] Monadic operations between [expected.object.observe] and [expected.object.eq]</a></li>
<li><a href="#orgc486397">Partial specialization of expected for void types [expected.void]</a></li>
<li><a href="#org5f71333">Add following at the end [expected.void.observe] Observers:</a></li>
<li><a href="#org7e20a61">Add a new section [expected.void.monadic] Monadic operations [expected.void.observe] and [expected.void.eq]</a></li>
</ul>
</li>
<li><a href="#orgddfce02">Acknowledgements</a></li>
<li><a href="#org20bf67f">Revision History</a></li>
<li><a href="#orgdd0f0c6">References</a></li>
</ul>
</div>
</div>
<p>
<b>Authors:</b>
    Jeff Garland
</p>

<p>
<b>Audience:</b>
    LEWG, LWG
</p>

<p>
<b>Project:</b>
    ISO/IEC JTC1/SC22/WG21 14882: Programming Language — C++
</p>

<p>
<b>Contact:</b>
    jeff@crystalclearsoftware.com
</p>


<div id="outline-container-orgefab892" class="outline-2">
<h2 id="orgefab892">Introduction</h2>
<div class="outline-text-2" id="text-orgefab892">
<p>
With the final plenary vote of <a href="https://wg21.link/P0798">P0798 Monadic Functions for std::optional</a> complete, we now have an design inconsistency with <code>std::expected</code>. <a href="https://wg21.link/P0323">P0323 std::expected</a> has now also been voted into the working draft for C++23. This proposal corrects the inconsistency by adding 4 functions to <code>std::expected</code> and is targeted at C++23.  The author believes this should be treated as a consistency/bug fix still in scope for C++23.
</p>

<p>
The intent from P0798 clearly states that <code>std::expected</code> should gain the same functions:
</p>
<blockquote>
<p>
There is a proposal for std::expected which would benefit from many of these same ideas. If the idea to add monadic interfaces to standard library classes on a case-by-case basis is chosen rather than a unified non-member function interface, then compatibility between this proposal and the std::expected one should be maintained
</p>
</blockquote>
</div>
</div>
<div id="outline-container-org8cd6000" class="outline-2">
<h2 id="org8cd6000">Motivation and Scope</h2>
<div class="outline-text-2" id="text-org8cd6000">
<p>
The following 3 functions are added to <code>std::optional</code>, but are currently not part of <code>std::expected</code>.  
</p>

<ul class="org-ul">
<li><code>and_then</code>     compose a chain of functions returning an expected</li>
<li><code>or_else</code>      returns if it has a value, otherwise it calls a function with the error type</li>
<li><code>transform</code>    apply a function to change the value (and possibly the type)</li>
</ul>

<p>
After feedback, this draft also proposes the addition of two additional functions for <code>expected</code> to facilitate additional cases:
</p>

<ul class="org-ul">
<li><code>transform_error</code> apply a function to change the value, otherwise call a function with error type</li>
<li><code>error_or</code>        a value to return when there is not an error</li>
</ul>

<p>
For example, given the following:
</p>
<div class="org-src-container">
<pre class="src src-C++"><span style="color: #a020f0;">using</span> <span style="color: #228b22;">time_expected</span> = <span style="color: #228b22;">expected</span>&lt;<span style="color: #008b8b;">boost</span>::<span style="color: #008b8b;">posix_time</span>::ptime, <span style="color: #008b8b;">std</span>::string&gt;;

<span style="color: #228b22;">time_expected</span> <span style="color: #0000ff;">from_iso_str</span>( <span style="color: #008b8b;">std</span>::<span style="color: #228b22;">string</span> <span style="color: #a0522d;">time</span> )
{
  <span style="color: #a020f0;">try</span> {
    <span style="color: #228b22;">ptime</span> <span style="color: #a0522d;">t</span>  = <span style="color: #008b8b;">boost</span>::<span style="color: #008b8b;">posix_time</span>::from_iso_string( time );
    <span style="color: #a020f0;">return</span> t;
  }
  <span style="color: #a020f0;">catch</span>( <span style="color: #008b8b;">std</span>::exception&amp; e )
  {
     <span style="color: #a020f0;">return</span> unexpected( e.what() + <span style="color: #8b2252;">" str was: "</span>s + time);
  }
}

<span style="color: #b22222;">// </span><span style="color: #b22222;">for use with transform</span>
<span style="color: #228b22;">ptime</span> <span style="color: #0000ff;">next_day</span>( <span style="color: #008b8b;">boost</span>::<span style="color: #008b8b;">posix_time</span>::<span style="color: #228b22;">ptime</span> <span style="color: #a0522d;">t</span> )
{
   <span style="color: #a020f0;">return</span> t + <span style="color: #008b8b;">boost</span>::<span style="color: #008b8b;">gregorian</span>::days(1);
}

<span style="color: #b22222;">// </span><span style="color: #b22222;">for use with or_else</span>
<span style="color: #228b22;">void</span> <span style="color: #0000ff;">print_error</span>( <span style="color: #008b8b;">std</span>::<span style="color: #228b22;">string</span> <span style="color: #a0522d;">error</span> )
{
   cout &lt;&lt; error &lt;&lt; endl;
}


<span style="color: #b22222;">//</span><span style="color: #b22222;">valid iso string</span>
<span style="color: #a020f0;">const</span> <span style="color: #008b8b;">std</span>::<span style="color: #228b22;">string</span> <span style="color: #0000ff;">ts</span> ( <span style="color: #8b2252;">"20210726T000000"</span> );
</pre>
</div>

<p>
Before the change we'd write this:
</p>

<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col  class="org-left" />
</colgroup>
<tbody>
<tr>
<td class="org-left">Before</td>
</tr>
</tbody>
</table>
<div class="org-src-container">
<pre class="src src-C++"><span style="color: #228b22;">time_expected</span> <span style="color: #a0522d;">d</span> = from_iso_str( ts );
<span style="color: #a020f0;">if</span> (d)
{
   <span style="color: #228b22;">ptime</span> <span style="color: #a0522d;">t</span> = next_day( *d );
} 
<span style="color: #a020f0;">else</span>
{
   print_error( d.error() );
}
</pre>
</div>

<p>
And after, this:
</p>

<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col  class="org-left" />
</colgroup>
<tbody>
<tr>
<td class="org-left">After</td>
</tr>
</tbody>
</table>

<div class="org-src-container">
<pre class="src src-C++"><span style="color: #b22222;">// </span><span style="color: #b22222;">chain a series of functions until there's an error</span>
<span style="color: #a020f0;">auto</span> <span style="color: #228b22;">d</span> = from_iso_str ( ts )
               .or_else( print_error )
               .transform( next_day ) ;
</pre>
</div>

<p>
Jonathan Wakely has a live demo illustrating the api here <a href="https://godbolt.org/z/3a1j6d63a">https://godbolt.org/z/3a1j6d63a</a>.
For more examples see: <a href="https://godbolt.org/z/K7rbhx9oo">https://godbolt.org/z/K7rbhx9oo</a>.
</p>
</div>
</div>

<div id="outline-container-orgc58c9fe" class="outline-2">
<h2 id="orgc58c9fe">Design Considerations</h2>
<div class="outline-text-2" id="text-orgc58c9fe">
</div>
<div id="outline-container-org149cc0f" class="outline-3">
<h3 id="org149cc0f"><code>expected&lt;void, E&gt;</code></h3>
<div class="outline-text-3" id="text-org149cc0f">
<p>
Compared with <code>optional</code>, <code>expected</code> provides the capability for <code>void</code> as a function return type. This complicates the design compared to <code>optional</code>.  As currently specified the <code>void</code> specialization of <code>expected</code>, <code>expected&lt;void, T&gt;</code> removes the <code>value_or</code> function since <code>void</code> cannot be initialized to anything else.
</p>

<p>
While the primary implementation for this paper excludes <code>transform</code> for <code>expected&lt;void, E&gt;</code> and the original version removed this overload, feedback from reviewers suggested the overload is valuable.  Thus the new version allows for this overload.
</p>
</div>
</div>

<div id="outline-container-org90a5b0c" class="outline-3">
<h3 id="org90a5b0c"><code>transform</code> to <code>expected&lt;void, E&gt;</code> return</h3>
<div class="outline-text-3" id="text-org90a5b0c">
<p>
Consider the following code.
</p>

<div class="org-src-container">
<pre class="src src-c++"><span style="color: #a020f0;">struct</span> <span style="color: #228b22;">E</span>{};
<span style="color: #a020f0;">auto</span> <span style="color: #228b22;">x</span> = <span style="color: #228b22;">expected</span>&lt;<span style="color: #228b22;">int</span>, E&gt;(4).transform([](<span style="color: #228b22;">int</span>){});
</pre>
</div>

<p>
The original specifications and implementations would fail to compile this code. A reasonable alternative is to return <code>expected&lt;void, E&gt;</code>.  The specification has been changed to allow this behavior.
</p>
</div>
</div>

<div id="outline-container-org4e91148" class="outline-3">
<h3 id="org4e91148"><code>transform_error</code> function</h3>
<div class="outline-text-3" id="text-org4e91148">
<p>
The R0 version of this paper did not include this function to match optional, but several reviewers noted the important utility of this case. Note that in the reference implementation of this paper, the function is called <code>map_error</code>.  The R1 version of the paper names the function <code>transform_error</code> after discussions with various reviewers.
</p>
</div>
</div>

<div id="outline-container-org8636701" class="outline-3">
<h3 id="org8636701">Changing of error return types</h3>
<div class="outline-text-3" id="text-org8636701">
<p>
One complication of the monadic functions for <code>expected</code> as compared to <code>optional</code> is the ability to change the return error return type on subsequent function calls.  Optional, of course, can only return <code>std::nullopt_t</code>. 
</p>

<p>
Thus we would like to support use cases like the following:
</p>

<pre class="example">

std::expected&lt;SomeUserType, InternalError&gt; initialize();

std::expected&lt;SomeUserType, UserError&gt;
makeUserError(InternalError err) 
{ 
   return std::unexpected( UserError(err) ); 
};

std::expected&lt;SomeUserType, UserError&gt; result = initialize().or_else( makeUserError );

</pre>

<p>
Note that the changing of the error type applies to the <code>or_else</code> and <code>transform_error</code> overloads only.
</p>
</div>
</div>

<div id="outline-container-orgea68796" class="outline-3">
<h3 id="orgea68796">Use of deducing-this in the specification</h3>
<div class="outline-text-3" id="text-orgea68796">
<p>
This question has been asked several times including in the LEWG 2022-05-03 meeting.  While less concise, the author prefers to keep the specification consistent with the rest of the c++23 library and especially <code>std::optional</code>.  Limited access to compilers that implement deducing-this make it difficult to confirm correct behavior of a deducing-this based specification.  In addition, the current specification does not preclude changing to a deducing-this based consistently with other library facilities in a future release.
</p>
</div>
</div>

<div id="outline-container-org98e7fda" class="outline-3">
<h3 id="org98e7fda">Adding <code>error_or</code> functions</h3>
<div class="outline-text-3" id="text-org98e7fda">
<p>
It has been suggested that <code>error_or</code> functions be added to the proposal.  While the author is sympathetic to the suggestion, since consistency with <code>optional</code> for c++23 is the intent these are not proposed. These can be added later or if LEWG would prefer the author can investigate adding them in this cycle.
</p>

<p>
At 2022-06-07 LEWG telecom poll was taken to add this function.  The wording is added in R4 of the paper.
</p>

<p>
POLL: Add <code>error_or</code> to <code>expected</code> for C++23.
</p>

<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col  class="org-right" />

<col  class="org-right" />

<col  class="org-right" />

<col  class="org-right" />

<col  class="org-right" />
</colgroup>
<thead>
<tr>
<th scope="col" class="org-right">Strongly Favor</th>
<th scope="col" class="org-right">Weakly Favor</th>
<th scope="col" class="org-right">Neutral</th>
<th scope="col" class="org-right">Weakly Against</th>
<th scope="col" class="org-right">Strongly Against</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-right">4</td>
<td class="org-right">7</td>
<td class="org-right">2</td>
<td class="org-right">2</td>
<td class="org-right">0</td>
</tr>
</tbody>
</table>

<p>
Attendance: 21
</p>

<p>
Author Position: N
</p>

<p>
Outcome: Consensus in favor.
</p>

<p>
As an example usage consider the following code:
</p>
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col  class="org-left" />
</colgroup>
<tbody>
<tr>
<td class="org-left">Before</td>
</tr>
</tbody>
</table>
<div class="org-src-container">
<pre class="src src-C++"><span style="color: #b22222;">//</span><span style="color: #b22222;">before</span>
<span style="color: #228b22;">file</span> <span style="color: #0000ff;">create_file</span>(<span style="color: #228b22;">char</span> <span style="color: #a020f0;">const</span>*, <span style="color: #008b8b;">std</span>::<span style="color: #228b22;">error_code</span>&amp;);
<span style="color: #228b22;">bool</span> <span style="color: #0000ff;">test_and_report</span>(<span style="color: #a020f0;">const</span> <span style="color: #228b22;">error_code</span>&amp;);

<span style="color: #008b8b;">std</span>::<span style="color: #228b22;">error_code</span> <span style="color: #a0522d;">ec</span>;
<span style="color: #228b22;">file</span> <span style="color: #a0522d;">f</span> = create_file(<span style="color: #8b2252;">"file"</span>, ec);
<span style="color: #a020f0;">if</span> (test_and_report(ec)) { <span style="color: #a020f0;">return</span>; }

</pre>
</div>

<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col  class="org-left" />
</colgroup>
<tbody>
<tr>
<td class="org-left">After</td>
</tr>
</tbody>
</table>
<div class="org-src-container">
<pre class="src src-C++"><span style="color: #228b22;">expected</span>&lt;file, error_code&gt; <span style="color: #0000ff;">create_file</span>(<span style="color: #228b22;">char</span> <span style="color: #a020f0;">const</span>*);
<span style="color: #228b22;">bool</span> <span style="color: #0000ff;">test_and_report</span>(<span style="color: #a020f0;">const</span> <span style="color: #228b22;">error_code</span>&amp;);

<span style="color: #a020f0;">auto</span> <span style="color: #228b22;">f</span> = create_file(<span style="color: #8b2252;">"file"</span>);

<span style="color: #a020f0;">if</span> (test_and_report(f.error_or({}))) { <span style="color: #a020f0;">return</span>; }

</pre>
</div>
</div>
</div>


<div id="outline-container-org69f9e69" class="outline-3">
<h3 id="org69f9e69">Free versus member functions</h3>
<div class="outline-text-3" id="text-org69f9e69">
<p>
One design question that has been raised is the use of member functions instead of free functions. The author is sympathetic to this view, but believes this can only be done by changing both <code>optional</code> and <code>expected</code>.  The expressed benefits of free functions would be:
</p>

<ul class="org-ul">
<li>better compatibility with future library facilities</li>
<li>more generic code &#x2013; singular specification</li>
</ul>

<p>
While in theory, free functions provide consistency with some future version of the library where functions such as <code>then</code> and <code>upon_error</code> from P2300 <code>std::execution</code> would be part of the standard library.  However, <code>then</code> is specified using concepts such as <code>std::execution::sender</code> which are not appropriate for a generalized <code>then</code> functions for <code>optional</code> and <code>expected</code>. In fact, attempting to specify this as free functions now might trample on names for future library free functions.
</p>

<p>
Since the author is unaware of any existing practice with providing these functions and the purpose of the paper is consistency with monadic optional functions already voted into the working draft, the author will not pursue this option.  A fully thought out paper with existing practice would be required to make this change.
</p>

<p>
Note that the author's experience with <code>std::expected</code> implementing json parsing is that <code>expected</code> would be extremely cumbersome for the task without these functions. So shipping C++23 without these functions for an unclear future benefit would be a major mistake for users.
</p>
</div>
</div>
</div>

<div id="outline-container-orga46970a" class="outline-2">
<h2 id="orga46970a">Other Languages</h2>
<div class="outline-text-2" id="text-orga46970a">
<p>
Rust provides a result type with similar functions monadic functions.
</p>

<p>
<a href="https://doc.rust-lang.org/std/result/enum.Result.html">https://doc.rust-lang.org/std/result/enum.Result.html</a>
</p>
</div>
</div>

<div id="outline-container-org76f1262" class="outline-2">
<h2 id="org76f1262">Implementations</h2>
<div class="outline-text-2" id="text-org76f1262">
<p>
Jonathan Wakely has implemented the full proposal here <a href="https://github.com/jwakely/gcc/blob/expected/libstdc%2B%2B-v3/include/std/expected">https://github.com/jwakely/gcc/blob/expected/libstdc%2B%2B-v3/include/std/expected</a>.
</p>

<p>
The core of the proposal was originally implemented by Sy Brand <a href="https://github.com/TartanLlama/expected">https://github.com/TartanLlama/expected</a> with <a href="https://tl.tartanllama.xyz/en/latest/api/expected.html#tl-expected">documentation here</a>. 
</p>

<p>
Rishabh Dwivedi has also implemented the proposal based on the draft wording <a href="https://github.com/RishabhRD/expected">https://github.com/RishabhRD/expected</a>. 
</p>
</div>
</div>

<div id="outline-container-orgfc6b8c3" class="outline-2">
<h2 id="orgfc6b8c3">Wording</h2>
<div class="outline-text-2" id="text-orgfc6b8c3">
</div>
<div id="outline-container-orgba93247" class="outline-3">
<h3 id="orgba93247">Feature Test Macro</h3>
<div class="outline-text-3" id="text-orgba93247">
<p>
Update the <code>__cpp_lib_expected</code> feature test macro from P0323.  Although this could be considered optional since expected is not yet a c++ feature in any implementations.
</p>
</div>
</div>

<div id="outline-container-org8400a76" class="outline-3">
<h3 id="org8400a76">Class template expected [expected.expected]</h3>
<div class="outline-text-3" id="text-org8400a76">
<p>
After <code>value_or</code> functions add the new functions:
</p>

<div class="org-src-container">
<pre class="src src-C++"><span style="color: #a020f0;">template</span>&lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">U</span>&gt; constexpr <span style="color: #228b22;">T</span> <span style="color: #0000ff;">value_or</span>(<span style="color: #228b22;">U</span>&amp;&amp;) &amp;&amp;;
<span style="color: #a020f0;">template</span>&lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">G</span> = <span style="color: #228b22;">E</span>&gt; constexpr <span style="color: #228b22;">E</span> <span style="color: #0000ff;">error_or</span>(<span style="color: #228b22;">G</span>&amp;&amp;) <span style="color: #a020f0;">const</span>&amp;;
<span style="color: #a020f0;">template</span>&lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">G</span> = <span style="color: #228b22;">E</span>&gt; constexpr <span style="color: #228b22;">E</span> <span style="color: #0000ff;">error_or</span>(<span style="color: #228b22;">G</span>&amp;&amp;) &amp;&amp;;

<span style="color: #b22222;">// </span><span style="color: #b22222;">[expected.monadic], monadic operations</span>
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> and_then(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) &amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> and_then(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) &amp;&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> and_then(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) <span style="color: #a020f0;">const</span>&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> and_then(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) <span style="color: #a020f0;">const</span>&amp;&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> or_else(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) &amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> or_else(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) &amp;&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> or_else(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) <span style="color: #a020f0;">const</span>&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> or_else(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) <span style="color: #a020f0;">const</span>&amp;&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> transform(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) &amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> transform(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) &amp;&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> transform(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) <span style="color: #a020f0;">const</span>&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> transform(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) <span style="color: #a020f0;">const</span>&amp;&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> transform_error(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) &amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> transform_error(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) &amp;&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> transform_error(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) <span style="color: #a020f0;">const</span>&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> transform_error(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) <span style="color: #a020f0;">const</span>&amp;&amp;;
<span style="color: #b22222;">// </span><span style="color: #b22222;">[expected.object.swap], swap</span>
</pre>
</div>
</div>
</div>

<div id="outline-container-org4569073" class="outline-3">
<h3 id="org4569073">Add following at the end [expected.object.observe] Observers:</h3>
<div class="outline-text-3" id="text-org4569073">
<p>
1 <code>template &lt;class G = E&gt; constexpr E error_or(G&amp;&amp; e) const&amp;;</code>
</p>

<p>
<i>Mandates:</i> <code>is_copy_constructible_v&lt;E&gt;</code> is <code>true</code> and <code>is_convertible&lt;G, E&gt;</code> is <code>true</code>.
</p>

<p>
<i>Returns:</i> <code>std::forward&lt;G&gt;(e)</code> if <code>has_value()</code> is <code>true</code>, <code>error()</code> otherwise.
</p>

<p>
2 <code>template &lt;class G = E&gt; constexpr E error_or(G&amp;&amp; e) i&amp;&amp;;</code>
</p>

<p>
<i>Mandates:</i> <code>is_move_constructible_v&lt;E&gt;</code> is <code>true</code> and <code>is_convertible&lt;G, E&gt;</code> is <code>true</code>.
</p>

<p>
<i>Returns:</i> <code>std::forward&lt;G&gt;(e)</code> if <code>has_value()</code> is <code>true</code>, <code>std::move(error())</code> otherwise.
</p>
</div>
</div>

<div id="outline-container-orgd056f38" class="outline-3">
<h3 id="orgd056f38">Add a new sub-clause [expected.object.monadic] Monadic operations between [expected.object.observe] and [expected.object.eq]</h3>
<div class="outline-text-3" id="text-orgd056f38">
<p>
1 <code>template &lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) &amp;;</code>
</p>

<p>
2 <code>template &lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) const&amp;;</code>
</p>

<p>
Let U be <code>remove_cvref_t&lt;invoke_result_t&lt;F, decltype(value())&gt;&gt;</code>.
</p>

<p>
<i>Constraints:</i> <code>is_copy_constructible_v&lt;E&gt;</code> is <code>true</code>
</p>

<p>
<i>Mandates:</i> U is a specialization of <code>expected</code> and <code>is_same_v&lt;U::error_type, E&gt;</code> is <code>true</code>,
</p>

<p>
<i>Effects:</i> Equivalent to:
</p>
<div class="org-src-container">
<pre class="src src-C++"><span style="color: #a020f0;">if</span> (has_value()) { 
   <span style="color: #a020f0;">return</span> invoke(<span style="color: #008b8b;">std</span>::<span style="color: #228b22;">forward</span>&lt;F&gt;(<span style="color: #a0522d;">f</span>), value());
}
<span style="color: #a020f0;">else</span> { 
   <span style="color: #a020f0;">return</span> U(unexpect, error());
}
</pre>
</div>

<p>
1 <code>template &lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) &amp;&amp;;</code>
</p>

<p>
2 <code>template &lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) const&amp;&amp;;</code>
</p>

<p>
Let U be <code>remove_cvref_t&lt;invoke_result_t&lt;F, decltype(std::move(value()))&gt;&gt;</code>.
</p>

<p>
<i>Constraints:</i> <code>is_move_constructible_v&lt;E&gt;</code> is <code>true</code>
</p>

<p>
<i>Mandates:</i> U is a specialization of <code>expected</code> and <code>is_same_v&lt;U::error_type, E&gt;</code> is <code>true</code>, 
</p>

<p>
<i>Effects:</i> Equivalent to:
</p>
<div class="org-src-container">
<pre class="src src-C++"><span style="color: #a020f0;">if</span> (has_value()) { 
   <span style="color: #a020f0;">return</span> invoke(<span style="color: #008b8b;">std</span>::<span style="color: #228b22;">forward</span>&lt;F&gt;(<span style="color: #a0522d;">f</span>), <span style="color: #008b8b;">std</span>::move(value()));
}
<span style="color: #a020f0;">else</span> {
   <span style="color: #a020f0;">return</span> U(unexpect, <span style="color: #008b8b;">std</span>::move(error()));
}
</pre>
</div>
<p>
1 <code>template &lt;class F&gt; constexpr auto or_else(F&amp;&amp; f) &amp;;</code>
</p>

<p>
2 <code>template &lt;class F&gt; constexpr auto or_else(F&amp;&amp; f) const&amp;;</code>
</p>

<p>
Let G be <code>remove_cvref_t&lt;invoke_result_t&lt;F, decltype(std::move(error()))&gt;&gt;</code>.
</p>

<p>
<i>Constraints:</i>  <code>is_copy_constructible_v&lt;T&gt;</code> is <code>true</code>. 
</p>

<p>
<i>Mandates:</i> G is a specialization of <code>expected</code> and  <code>is_same_v&lt;G::value_type, T&gt;</code> is <code>true</code>, 
</p>

<p>
Effects: Equivalent to:
</p>
<div class="org-src-container">
<pre class="src src-C++"><span style="color: #a020f0;">if</span> (has_value()) {
    <span style="color: #a020f0;">return</span> G(in_place, value());
} <span style="color: #a020f0;">else</span> {
    <span style="color: #a020f0;">return</span> invoke(<span style="color: #008b8b;">std</span>::<span style="color: #228b22;">forward</span>&lt;F&gt;(), error());
}
</pre>
</div>

<p>
1 <code>template &lt;class F&gt; constexpr auto or_else(F&amp;&amp; f) &amp;&amp;;</code>
</p>

<p>
2 <code>template &lt;class F&gt; constexpr auto or_else(F&amp;&amp; f) const&amp;&amp;;</code>
</p>

<p>
Let G be <code>remove_cvref_t&lt;invoke_result_t&lt;F, decltype(std::move(error()))&gt;&gt;</code>. 
</p>

<p>
<i>Constraints:</i> <code>is_move_constructible_v&lt;T&gt;</code> is <code>true</code>
</p>

<p>
<i>Mandates:</i> G is a specialization of <code>expected</code> and <code>is_same_v&lt;G::value_type, T&gt;</code> is <code>true</code>.
</p>

<p>
<i>Effects:</i> Equivalent to:
</p>
<div class="org-src-container">
<pre class="src src-C++"><span style="color: #a020f0;">if</span> (has_value()) { 
   <span style="color: #a020f0;">return</span> G(in_place, <span style="color: #008b8b;">std</span>::move(value()));
}
<span style="color: #a020f0;">else</span> { 
   <span style="color: #a020f0;">return</span> invoke(<span style="color: #008b8b;">std</span>::<span style="color: #228b22;">forward</span>&lt;F&gt;(<span style="color: #a0522d;">f</span>), <span style="color: #008b8b;">std</span>::move(error()));
}
</pre>
</div>
<p>
1 <code>template &lt;class F&gt; constexpr auto transform(F&amp;&amp; f) &amp;;</code>
</p>

<p>
2 <code>template &lt;class F&gt; constexpr auto transform(F&amp;&amp; f) const&amp;;</code>
</p>

<p>
Let U be <code>remove_cvref_t&lt;invoke_result_t&lt;F, decltype(value())&gt;&gt;</code>.
</p>

<p>
<i>Mandates:</i> U is <code>void</code> or a non-array object type other than <code>in_place_t</code>, <code>unexpect_t</code>, or a specialization of <code>unexpected</code>. If <code>is_void_v&lt;U&gt;</code> is <code>false</code>, the declaration <code>U u(invoke(std::forward&lt;F&gt;(f), value()));</code> is well-formed.
</p>

<p>
<i>Constraints:</i>
</p>
<ul class="org-ul">
<li><code>is_copy_constructible_v&lt;E&gt;</code> is <code>true</code>, and</li>
</ul>

<p>
<i>Effects:</i> 
</p>
<ul class="org-ul">
<li>If <code>has_value()</code> is <code>false</code>, returns <code>expected&lt;U,E&gt;(unexpect, error())</code>, otherwise</li>
<li>if <code>is_void_v&lt;U&gt;</code> is <code>false</code>, returns an <code>expected&lt;U, E&gt;</code> object whose <code>has_val</code> member is <code>true</code> and <code>val</code> member is direct-non-list-initialized with <code>invoke(std::forward&lt;F&gt;(f), value())</code>, otherwise</li>
<li>evaluates <code>invoke(std::forward&lt;F&gt;(f), value())</code> and then returns <code>expected&lt;U,E&gt;()</code>.</li>
</ul>


<p>
1 <code>template &lt;class F&gt; constexpr auto transform(F&amp;&amp; f) &amp;&amp;;</code>
</p>

<p>
2 <code>template &lt;class F&gt; constexpr auto transform(F&amp;&amp; f) const&amp;&amp;;</code>
</p>

<p>
Let U be <code>remove_cvref_t&lt;invoke_result_t&lt;F, decltype(std::move(value()))&gt;&gt;</code>.
</p>

<p>
<i>Mandates:</i> U is <code>void</code> or a non-array object type other than <code>in_place_t</code>, <code>unexpect_t</code>, or a specialization of <code>unexpected</code>. If <code>is_void_v&lt;U&gt;</code> is <code>false</code>, the declaration <code>U u(invoke(std::forward&lt;F&gt;(f), std::move(value())));</code> is well-formed.
</p>

<p>
<i>Constraints:</i> <code>is_move_constructible_v&lt;E&gt;</code> is <code>true</code>, and
</p>

<p>
<i>Effects:</i> 
</p>
<ul class="org-ul">
<li>If <code>has_value()</code> is <code>false</code>, returns <code>expected&lt;U,E&gt;(unexpect, std::move(error()))</code>, otherwise</li>
<li>if <code>is_void_v&lt;U&gt;</code> is <code>false</code>, returns an <code>expected&lt;U, E&gt;</code> object whose <code>has_val</code> member is <code>true</code> and <code>val</code> member is direct-non-list-initialized with <code>invoke(std::forward&lt;F&gt;(f), std::move(value()))</code>, otherwise</li>
<li>evaluates <code>invoke(std::forward&lt;F&gt;(f), std::move(value()))</code> and then returns <code>expected&lt;U,E&gt;()</code>.</li>
</ul>

<p>
1 <code>template &lt;class F&gt; constexpr auto transform_error(F&amp;&amp; f) &amp;;</code>
</p>

<p>
2 <code>template &lt;class F&gt; constexpr auto transform_error(F&amp;&amp; f) const&amp;;</code>
</p>

<p>
Let G be <code>remove_cvref_t&lt;invoke_result_t&lt;F, decltype(error())&gt;&gt;</code>. 
</p>

<p>
<i>Mandates:</i> G is a non-array object type other than <code>in_place_t</code>, <code>unexpect_t</code>, or a specialization of <code>unexpected</code>. The declaration <code>G g(invoke(std::forward&lt;F&gt;(f), error()));</code> is well-formed.
</p>

<p>
<i>Constraints:</i> <code>is_copy_constructible_v&lt;T&gt;</code> is <code>true</code>
</p>

<p>
<i>Returns:</i> 
</p>
<ul class="org-ul">
<li>If <code>has_value()</code> is <code>true</code>,  <code>expected&lt;T,G&gt;(in_place, value())</code>, otherwise</li>
<li>an <code>expected&lt;T, G&gt;</code> object whose <code>has_val</code> member is <code>false</code> and <code>unex</code> member is direct-non-list-initialized with <code>invoke(std::forward&lt;F&gt;(f), error())</code>, otherwise</li>
</ul>

<p>
1 <code>template &lt;class F&gt; constexpr auto transform_error(F&amp;&amp; f) &amp;&amp;;</code>
</p>

<p>
2 <code>template &lt;class F&gt; constexpr auto transform_error(F&amp;&amp; f) const&amp;&amp;;</code>
</p>

<p>
Let G be <code>remove_cvref_t&lt;invoke_result_t&lt;F, decltype(std::move(error()))&gt;&gt;</code>.
</p>

<p>
<i>Mandates:</i> G is a non-array object type other than <code>in_place_t</code>, <code>unexpect_t</code>, or a specialization of <code>unexpected</code>. The declaration <code>G g(invoke(std::forward&lt;F&gt;(f), std::move(error())));</code> is well-formed.
</p>

<p>
<i>Constraints:</i> <code>is_move_constructible_v&lt;T&gt;</code> is <code>true</code>, and
</p>

<p>
<i>Returns:</i> 
</p>
<ul class="org-ul">
<li>If <code>has_value()</code> is <code>true</code>,  <code>expected&lt;T,G&gt;(in_place, std::move(value()))</code>, otherwise</li>
<li>an <code>expected&lt;T, G&gt;</code> object whose <code>has_val</code> member is <code>false</code> and <code>unex</code> member is direct-non-list-initialized with <code>invoke(std::forward&lt;F&gt;(f), std::move(error()))</code></li>
</ul>
</div>
</div>

<div id="outline-container-orgc486397" class="outline-3">
<h3 id="orgc486397">Partial specialization of expected for void types [expected.void]</h3>
<div class="outline-text-3" id="text-orgc486397">
<p>
After error functions add the new functions:
</p>

<div class="org-src-container">
<pre class="src src-C++">constexpr <span style="color: #228b22;">E</span>&amp;&amp; <span style="color: #0000ff;">error</span>() &amp;&amp;;
<span style="color: #a020f0;">template</span>&lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">G</span> = <span style="color: #228b22;">E</span>&gt; constexpr <span style="color: #228b22;">E</span> <span style="color: #0000ff;">error_or</span>(<span style="color: #228b22;">G</span>&amp;&amp;) <span style="color: #a020f0;">const</span>&amp;;
<span style="color: #a020f0;">template</span>&lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">G</span> = <span style="color: #228b22;">E</span>&gt; constexpr <span style="color: #228b22;">E</span> <span style="color: #0000ff;">error_or</span>(<span style="color: #228b22;">G</span>&amp;&amp;) &amp;&amp;;

<span style="color: #b22222;">// </span><span style="color: #b22222;">&#65533;.&#65533;.8.7, monadic</span>
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> and_then(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) &amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> and_then(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) &amp;&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> and_then(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) <span style="color: #a020f0;">const</span>&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> and_then(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) <span style="color: #a020f0;">const</span>&amp;&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> or_else(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) &amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> or_else(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) &amp;&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> or_else(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) <span style="color: #a020f0;">const</span>&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> or_else(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) <span style="color: #a020f0;">const</span>&amp;&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> transform(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) &amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> transform(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) &amp;&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> transform(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) <span style="color: #a020f0;">const</span>&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> transform(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) <span style="color: #a020f0;">const</span>&amp;&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> transform_error(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) &amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> transform_error(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) &amp;&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> transform_error(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) <span style="color: #a020f0;">const</span>&amp;;
<span style="color: #a020f0;">template</span> &lt;<span style="color: #a020f0;">class</span> <span style="color: #228b22;">F</span>&gt; <span style="color: #228b22;">constexpr</span> <span style="color: #a020f0;">auto</span> transform_error(<span style="color: #228b22;">F</span>&amp;&amp; <span style="color: #a0522d;">f</span>) <span style="color: #a020f0;">const</span>&amp;&amp;;
</pre>
</div>
</div>
</div>

<div id="outline-container-org5f71333" class="outline-3">
<h3 id="org5f71333">Add following at the end [expected.void.observe] Observers:</h3>
<div class="outline-text-3" id="text-org5f71333">
<p>
1 <code>template &lt;class G = E&gt; constexpr E error_or(G&amp;&amp; e) const&amp;;</code>
</p>

<p>
<i>Mandates:</i> <code>is_copy_constructible_v&lt;E&gt;</code> is <code>true</code> and <code>is_convertible&lt;G, E&gt;</code> is <code>true</code>.
</p>

<p>
<i>Returns:</i> <code>std::forward&lt;G&gt;(e)</code> if <code>has_value()</code> is <code>true</code>, <code>error()</code> otherwise.
</p>

<p>
2 <code>template &lt;class G = E&gt; constexpr E error_or(G&amp;&amp; e) i&amp;&amp;;</code>
</p>

<p>
<i>Mandates:</i> <code>is_move_constructible_v&lt;E&gt;</code> is <code>true</code> and <code>is_convertible&lt;G, E&gt;</code> is <code>true</code>.
</p>

<p>
<i>Returns:</i> <code>std::forward&lt;G&gt;(e)</code> if <code>has_value()</code> is <code>true</code>, <code>std::move(error())</code> otherwise.
</p>
</div>
</div>

<div id="outline-container-org7e20a61" class="outline-3">
<h3 id="org7e20a61">Add a new section [expected.void.monadic] Monadic operations [expected.void.observe] and [expected.void.eq]</h3>
<div class="outline-text-3" id="text-org7e20a61">
<p>
1 <code>template &lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) &amp;;</code>
</p>

<p>
2 <code>template &lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) const&amp;;</code>
</p>

<p>
Let U be <code>remove_cvref_t&lt;invoke_result_t&lt;F&gt;&gt;</code>.
</p>

<p>
<i>Constraints:</i> <code>is_copy_constructible_v&lt;E&gt;</code> is <code>true</code>.
</p>

<p>
<i>Mandates:</i> U is a specialization of <code>expected</code> and  <code>is_same_v&lt;U::error_type, E&gt;</code> is <code>true</code>.
</p>

<p>
<i>Effects:</i> Equivalent to:
</p>
<div class="org-src-container">
<pre class="src src-C++"><span style="color: #a020f0;">if</span> (has_value()) { 
   <span style="color: #a020f0;">return</span> invoke(<span style="color: #008b8b;">std</span>::<span style="color: #228b22;">forward</span>&lt;F&gt;(<span style="color: #a0522d;">f</span>));
}
<span style="color: #a020f0;">else</span> { 
   <span style="color: #a020f0;">return</span> U(unexpect, error());
}
</pre>
</div>

<p>
1 <code>template &lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) &amp;&amp;;</code>
</p>

<p>
2 <code>template &lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) const&amp;&amp;;</code>
</p>

<p>
Let U be <code>remove_cvref_t&lt;invoke_result_t&lt;F&gt;&gt;</code>.
</p>

<p>
<i>Constraints:</i> <code>is_move_constructible_v&lt;E&gt;</code> is <code>true</code>
</p>

<p>
<i>Mandates:</i> U is a specialization of <code>expected</code> and <code>is_same_v&lt;U::error_type, E&gt;</code> is <code>true</code>.
</p>

<p>
<i>Effects:</i> Equivalent to:
</p>
<div class="org-src-container">
<pre class="src src-C++"><span style="color: #a020f0;">if</span> (has_value()) { 
   <span style="color: #a020f0;">return</span> invoke(<span style="color: #008b8b;">std</span>::<span style="color: #228b22;">forward</span>&lt;F&gt;(<span style="color: #a0522d;">f</span>));
}
<span style="color: #a020f0;">else</span> {
   <span style="color: #a020f0;">return</span> U(unexpect, <span style="color: #008b8b;">std</span>::move(error()));
}
</pre>
</div>
<p>
1 <code>template &lt;class F&gt; constexpr auto or_else(F&amp;&amp; f) &amp;;</code>
</p>

<p>
2 <code>template &lt;class F&gt; constexpr auto or_else(F&amp;&amp; f) const&amp;;</code>
</p>

<p>
Let G be <code>remove_cvref_t&lt;invoke_result_t&lt;F, decltype(std::move(error()))&gt;&gt;</code>.
</p>

<p>
<i>Mandates:</i> G is a specialization of <code>expected</code> and <code>is_same_v&lt;G::value_type, T&gt;</code> is <code>true</code>.
</p>

<p>
Effects: Equivalent to:
</p>
<div class="org-src-container">
<pre class="src src-C++"><span style="color: #a020f0;">if</span> (has_value()) {
    <span style="color: #a020f0;">return</span> G();
} <span style="color: #a020f0;">else</span> {
    <span style="color: #a020f0;">return</span> invoke(<span style="color: #008b8b;">std</span>::<span style="color: #228b22;">forward</span>&lt;F&gt;(), error());
}
</pre>
</div>

<p>
1 <code>template &lt;class F&gt; constexpr auto or_else(F&amp;&amp; f) &amp;&amp;;</code>
</p>

<p>
2 <code>template &lt;class F&gt; constexpr auto or_else(F&amp;&amp; f) const&amp;&amp;;</code>
</p>

<p>
Let G be <code>remove_cvref_t&lt;invoke_result_t&lt;F, decltype(std::move(error()))&gt;&gt;</code>. 
</p>

<p>
<i>Mandates:</i> G is a specialization of <code>expected</code> and <code>is_same_v&lt;G::value_type, T&gt;</code> is <code>true</code>.
</p>

<p>
<i>Effects:</i> Equivalent to:
</p>
<div class="org-src-container">
<pre class="src src-C++"><span style="color: #a020f0;">if</span> (has_value()) { 
   <span style="color: #a020f0;">return</span> G();
}
<span style="color: #a020f0;">else</span> { 
   <span style="color: #a020f0;">return</span> invoke(<span style="color: #008b8b;">std</span>::<span style="color: #228b22;">forward</span>&lt;F&gt;(<span style="color: #a0522d;">f</span>), <span style="color: #008b8b;">std</span>::move(error()));
}
</pre>
</div>
<p>
1 <code>template &lt;class F&gt; constexpr auto transform(F&amp;&amp; f) &amp;;</code>
</p>

<p>
2 <code>template &lt;class F&gt; constexpr auto transform(F&amp;&amp; f) const&amp;;</code>
</p>

<p>
Let U be <code>remove_cvref_t&lt;invoke_result_t&lt;F&gt;&gt;</code>.
</p>

<p>
<i>Mandates:</i> U is <code>void</code> or a non-array object type other than <code>in_place_t</code>, <code>unexpect_t</code>, or a specialization of <code>unexpected</code>. If <code>is_void_v&lt;U&gt;</code> is <code>false</code>, the declaration <code>U u(invoke(std::forward&lt;F&gt;(f)));</code> is well-formed.
</p>

<p>
<i>Constraints:</i> <code>is_copy_constructible_v&lt;E&gt;</code> is <code>true</code>
</p>

<p>
<i>Effects:</i> 
</p>
<ul class="org-ul">
<li>If <code>has_value()</code> is <code>false</code>, returns <code>expected&lt;U,E&gt;(unexpect, error())</code>, otherwise</li>
<li>if <code>is_void_v&lt;U&gt;</code> is <code>false</code>, returns an <code>expected&lt;U, E&gt;</code> object whose <code>has_val</code> member is <code>true</code> and <code>val</code> member is direct-non-list-initialized with <code>invoke(std::forward&lt;F&gt;(f))</code>, otherwise</li>
<li>evaluates <code>invoke(std::forward&lt;F&gt;(f))</code> and then returns <code>expected&lt;U,E&gt;()</code>.</li>
</ul>


<p>
1 <code>template &lt;class F&gt; constexpr auto transform(F&amp;&amp; f) &amp;&amp;;</code>
</p>

<p>
2 <code>template &lt;class F&gt; constexpr auto transform(F&amp;&amp; f) const&amp;&amp;;</code>
</p>

<p>
Let U be <code>remove_cvref_t&lt;invoke_result_t&lt;F&gt;&gt;</code>.
</p>

<p>
<i>Mandates:</i> U is <code>void</code> or a non-array object type other than <code>in_place_t</code>, <code>unexpect_t</code>, or a specialization of <code>unexpected</code>. If <code>is_void_v&lt;U&gt;</code> is <code>false</code>, the declaration <code>U u(invoke(std::forward&lt;F&gt;(f)));</code> is well-formed.
</p>

<p>
<i>Constraints:</i> <code>is_move_constructible_v&lt;E&gt;</code> is <code>true</code>, and
</p>

<p>
<i>Effects:</i> 
</p>
<ul class="org-ul">
<li>If <code>has_value()</code> is <code>false</code>, returns <code>expected&lt;U,E&gt;(unexpect, std::move(error()))</code>, otherwise</li>
<li>if <code>is_void_v&lt;U&gt;</code> is <code>false</code>, returns an <code>expected&lt;U, E&gt;</code> object whose <code>has_val</code> member is <code>true</code> and <code>val</code> member is direct-non-list-initialized with <code>invoke(std::forward&lt;F&gt;(f))</code>, otherwise</li>
<li>evaluates <code>invoke(std::forward&lt;F&gt;(f))</code> and then returns <code>expected&lt;U,E&gt;()</code>.</li>
</ul>

<p>
1 <code>template &lt;class F&gt; constexpr auto transform_error(F&amp;&amp; f) &amp;;</code>
</p>

<p>
2 <code>template &lt;class F&gt; constexpr auto transform_error(F&amp;&amp; f) const&amp;;</code>
</p>

<p>
Let G be <code>remove_cvref_t&lt;invoke_result_t&lt;F, decltype(error())&gt;&gt;</code>. 
</p>

<p>
<i>Mandates:</i> G is a non-array object type other than <code>in_place_t</code>, <code>unexpect_t</code>, or a specialization of <code>unexpected</code>. The declaration <code>G g(invoke(std::forward&lt;F&gt;(f), error()));</code> is well-formed.
</p>

<p>
<i>Returns:</i> 
</p>
<ul class="org-ul">
<li>If <code>has_value()</code> is <code>true</code>,  <code>expected&lt;T,G&gt;()</code>, otherwise</li>
<li>an <code>expected&lt;T, G&gt;</code> object whose <code>has_val</code> member is <code>false</code> and <code>unex</code> member is direct-non-list-initialized with <code>invoke(std::forward&lt;F&gt;(f), error())</code>, otherwise</li>
</ul>

<p>
1 <code>template &lt;class F&gt; constexpr auto transform_error(F&amp;&amp; f) &amp;&amp;;</code>
</p>

<p>
2 <code>template &lt;class F&gt; constexpr auto transform_error(F&amp;&amp; f) const&amp;&amp;;</code>
</p>

<p>
Let G be <code>remove_cvref_t&lt;invoke_result_t&lt;F, decltype(std::move(error()))&gt;&gt;</code>.
</p>

<p>
<i>Mandates:</i> G is a non-array object type other than <code>in_place_t</code>, <code>unexpect_t</code>, or a specialization of <code>unexpected</code>. The declaration <code>G g(invoke(std::forward&lt;F&gt;(f), std::move(error())));</code> is well-formed.
</p>

<p>
<i>Returns:</i> 
</p>
<ul class="org-ul">
<li>If <code>has_value()</code> is <code>true</code>,  <code>expected&lt;T,G&gt;()</code>, otherwise</li>
<li>an <code>expected&lt;T, G&gt;</code> object whose <code>has_val</code> member is <code>false</code> and <code>unex</code> member is direct-non-list-initialized with <code>invoke(std::forward&lt;F&gt;(f), std::move(error()))</code></li>
</ul>
</div>
</div>
</div>

<div id="outline-container-orgddfce02" class="outline-2">
<h2 id="orgddfce02">Acknowledgements</h2>
<div class="outline-text-2" id="text-orgddfce02">
<ul class="org-ul">
<li>Thanks to Jonathan Wakely for implementation and wording feedback.</li>
<li>Thanks to Tomasz Kaminski for extensive wording input and suggestions on <code>error_or</code>.</li>
<li>Thanks to Sy Brand for the original work on optional and expected.</li>
<li>Thanks to Broneck Kozicki for early feedback.</li>
<li>Thanks to Arthur O'Dwyer for design and wording feedback.</li>
<li>Thanks to Barry Revzin for design and wording feedback as well as shepherding in LEWG.</li>
</ul>
</div>
</div>
<div id="outline-container-org20bf67f" class="outline-2">
<h2 id="org20bf67f">Revision History</h2>
<div class="outline-text-2" id="text-org20bf67f">
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">


<colgroup>
<col  class="org-right" />

<col  class="org-right" />

<col  class="org-left" />
</colgroup>
<thead>
<tr>
<th scope="col" class="org-right">Version</th>
<th scope="col" class="org-right">Date</th>
<th scope="col" class="org-left">Changes</th>
</tr>
</thead>
<tbody>
<tr>
<td class="org-right">0</td>
<td class="org-right">2021-12-12</td>
<td class="org-left">Initial Draft</td>
</tr>
</tbody>
<tbody>
<tr>
<td class="org-right">1</td>
<td class="org-right">2022-02-10</td>
<td class="org-left">added <code>transform_or</code></td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">allow <code>transform</code> on <code>expected&lt;void, E&gt;</code></td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">updated status of P0323 to plenary approved</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">improved examples</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">added missing overloads for <code>or_else</code></td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left"><code>or_else</code> signature and wording fixes</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">added design discussion of changing return types</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">variety of wording fixes</td>
</tr>
</tbody>
<tbody>
<tr>
<td class="org-right">2</td>
<td class="org-right">2022-04-15</td>
<td class="org-left">updates to reference Wakely implmentation and examples</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">remove unneeded invoke calls from void overloads</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left"><code>expected.object.swap</code> instead of modifiers in synopsis</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">change constraint wording to use <code>is_copy_constructible_v</code> form for consistency</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">change Let U for move overloads to <code>decltype(std::move(...))</code></td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">fix <code>transform_error</code> and <code>or_else</code> constraints to be T instead of E</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">rename <code>transform_or</code> to <code>transform_error</code></td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">remove the <code>is_same_v</code> constraint on <code>transform_error</code></td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">change <code>tranform_error</code> true case to return <code>expected&lt;T,U&gt;</code></td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">remove note: U will implicitly model either copy or move constructible&#x2026;</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">change all the <code>if (*this)</code> to <code>if (has_value())</code> to match latest expected wording</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">remove the <code>in_place</code> tag in <code>transform</code> overloads</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">remove void from <code>invoke_results</code> for <code>expected&lt;void,E&gt; and_then</code> and <code>transform</code>.</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">change error returns for <code>and_then~/~transform</code> to <code>return U(unexpect, error())</code></td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">change Let U to Let G for <code>transform_error</code> and <code>or_else</code> for less confusion</td>
</tr>
</tbody>
<tbody>
<tr>
<td class="org-right">3</td>
<td class="org-right">2022-06-05</td>
<td class="org-left">Add a design discussion of why deducing-this is not utilized</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">Add a discussion of free function versus member functions</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">mandate <code>transform</code> return type not be <code>unexpected</code>, <code>inplace_t</code>, etc</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">design discussion and wording for <code>transform</code> to <code>expected&lt;void, E&gt;</code></td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">design discussion of <code>error_or</code> functions</td>
</tr>
</tbody>
<tbody>
<tr>
<td class="org-right">4</td>
<td class="org-right">2022-06-15</td>
<td class="org-left">Add an <code>error_or</code> function that mirrors <code>value_or</code> for basic case</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">Update design section and intro with <code>error_or</code> information</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">Incorporate wording suggestions from Tomasz K.</td>
</tr>

<tr>
<td class="org-right">&#xa0;</td>
<td class="org-right">&#xa0;</td>
<td class="org-left">Add link to Rishabh D. implementation</td>
</tr>
</tbody>
</table>
</div>
</div>


<div id="outline-container-orgdd0f0c6" class="outline-2">
<h2 id="orgdd0f0c6">References</h2>
<div class="outline-text-2" id="text-orgdd0f0c6">
<ol class="org-ol">
<li>[P0798] Sy Brand "Monadic Functions for std::optional" <a href="https://wg21.link/P0798">https://wg21.link/P0798</a></li>
<li>C++ draft [optional.nomadic] <a href="http://eel.is/c++draft/optional.monadic">http://eel.is/c++draft/optional.monadic</a></li>
<li>[P0323] Vicente Botet, JF Bastien, Jonathan Wakely  std::expected <a href="https://wg21.link/P0323">https://wg21.link/P0323</a></li>
<li>Sy Brand expected  <a href="https://github.com/TartanLlama/expected">https://github.com/TartanLlama/expected</a></li>
<li>Sy Brand expected docs <a href="https://tl.tartanllama.xyz/en/latest/api/expected.html#tl-expected">https://tl.tartanllama.xyz/en/latest/api/expected.html#tl-expected</a></li>
<li>Jonathan Wakely full implemenation <a href="https://github.com/jwakely/gcc/blob/expected/libstdc%2B%2B-v3/include/std/expected">https://github.com/jwakely/gcc/blob/expected/libstdc%2B%2B-v3/include/std/expected</a></li>
<li>Jonathan Wakely live demo <a href="https://godbolt.org/z/3a1j6d63a">https://godbolt.org/z/3a1j6d63a</a></li>
<li>Rust Result <a href="https://doc.rust-lang.org/std/result/enum.Result.html">https://doc.rust-lang.org/std/result/enum.Result.html</a></li>
<li>More complete examples <a href="https://godbolt.org/z/va5fzx11f">https://godbolt.org/z/va5fzx11f</a></li>
</ol>
</div>
</div>
</div>
<div id="postamble" class="status">
<p class="author">Author: Jeff Garland</p>
<p class="date">Created: 2022-06-17 Fri 05:16</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
</body>
</html>
