<?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-02-15 Tue 08:58 -->
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>P2505R1 Monadic Functions for <code>std::expected</code></title>
<meta name="generator" content="Org mode" />
<meta name="author" content="Jeff Garland" />
<style type="text/css">
 <!--/*--><![CDATA[/*><!--*/
  .title  { text-align: center;
             margin-bottom: .2em; }
  .subtitle { text-align: center;
              font-size: medium;
              font-weight: bold;
              margin-top:0; }
  .todo   { font-family: monospace; color: red; }
  .done   { font-family: monospace; color: green; }
  .priority { font-family: monospace; color: orange; }
  .tag    { background-color: #eee; font-family: monospace;
            padding: 2px; font-size: 80%; font-weight: normal; }
  .timestamp { color: #bebebe; }
  .timestamp-kwd { color: #5f9ea0; }
  .org-right  { margin-left: auto; margin-right: 0px;  text-align: right; }
  .org-left   { margin-left: 0px;  margin-right: auto; text-align: left; }
  .org-center { margin-left: auto; margin-right: auto; text-align: center; }
  .underline { text-decoration: underline; }
  #postamble p, #preamble p { font-size: 90%; margin: .2em; }
  p.verse { margin-left: 3%; }
  pre {
    border: 1px solid #ccc;
    box-shadow: 3px 3px 3px #eee;
    padding: 8pt;
    font-family: monospace;
    overflow: auto;
    margin: 1.2em;
  }
  pre.src {
    position: relative;
    overflow: visible;
    padding-top: 1.2em;
  }
  pre.src:before {
    display: none;
    position: absolute;
    background-color: white;
    top: -10px;
    right: 10px;
    padding: 3px;
    border: 1px solid black;
  }
  pre.src:hover:before { display: inline;}
  /* Languages per Org manual */
  pre.src-asymptote:before { content: 'Asymptote'; }
  pre.src-awk:before { content: 'Awk'; }
  pre.src-C:before { content: 'C'; }
  /* pre.src-C++ doesn't work in CSS */
  pre.src-clojure:before { content: 'Clojure'; }
  pre.src-css:before { content: 'CSS'; }
  pre.src-D:before { content: 'D'; }
  pre.src-ditaa:before { content: 'ditaa'; }
  pre.src-dot:before { content: 'Graphviz'; }
  pre.src-calc:before { content: 'Emacs Calc'; }
  pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
  pre.src-fortran:before { content: 'Fortran'; }
  pre.src-gnuplot:before { content: 'gnuplot'; }
  pre.src-haskell:before { content: 'Haskell'; }
  pre.src-hledger:before { content: 'hledger'; }
  pre.src-java:before { content: 'Java'; }
  pre.src-js:before { content: 'Javascript'; }
  pre.src-latex:before { content: 'LaTeX'; }
  pre.src-ledger:before { content: 'Ledger'; }
  pre.src-lisp:before { content: 'Lisp'; }
  pre.src-lilypond:before { content: 'Lilypond'; }
  pre.src-lua:before { content: 'Lua'; }
  pre.src-matlab:before { content: 'MATLAB'; }
  pre.src-mscgen:before { content: 'Mscgen'; }
  pre.src-ocaml:before { content: 'Objective Caml'; }
  pre.src-octave:before { content: 'Octave'; }
  pre.src-org:before { content: 'Org mode'; }
  pre.src-oz:before { content: 'OZ'; }
  pre.src-plantuml:before { content: 'Plantuml'; }
  pre.src-processing:before { content: 'Processing.js'; }
  pre.src-python:before { content: 'Python'; }
  pre.src-R:before { content: 'R'; }
  pre.src-ruby:before { content: 'Ruby'; }
  pre.src-sass:before { content: 'Sass'; }
  pre.src-scheme:before { content: 'Scheme'; }
  pre.src-screen:before { content: 'Gnu Screen'; }
  pre.src-sed:before { content: 'Sed'; }
  pre.src-sh:before { content: 'shell'; }
  pre.src-sql:before { content: 'SQL'; }
  pre.src-sqlite:before { content: 'SQLite'; }
  /* additional languages in org.el's org-babel-load-languages alist */
  pre.src-forth:before { content: 'Forth'; }
  pre.src-io:before { content: 'IO'; }
  pre.src-J:before { content: 'J'; }
  pre.src-makefile:before { content: 'Makefile'; }
  pre.src-maxima:before { content: 'Maxima'; }
  pre.src-perl:before { content: 'Perl'; }
  pre.src-picolisp:before { content: 'Pico Lisp'; }
  pre.src-scala:before { content: 'Scala'; }
  pre.src-shell:before { content: 'Shell Script'; }
  pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
  /* additional language identifiers per "defun org-babel-execute"
       in ob-*.el */
  pre.src-cpp:before  { content: 'C++'; }
  pre.src-abc:before  { content: 'ABC'; }
  pre.src-coq:before  { content: 'Coq'; }
  pre.src-groovy:before  { content: 'Groovy'; }
  /* additional language identifiers from org-babel-shell-names in
     ob-shell.el: ob-shell is the only babel language using a lambda to put
     the execution function name together. */
  pre.src-bash:before  { content: 'bash'; }
  pre.src-csh:before  { content: 'csh'; }
  pre.src-ash:before  { content: 'ash'; }
  pre.src-dash:before  { content: 'dash'; }
  pre.src-ksh:before  { content: 'ksh'; }
  pre.src-mksh:before  { content: 'mksh'; }
  pre.src-posh:before  { content: 'posh'; }
  /* Additional Emacs modes also supported by the LaTeX listings package */
  pre.src-ada:before { content: 'Ada'; }
  pre.src-asm:before { content: 'Assembler'; }
  pre.src-caml:before { content: 'Caml'; }
  pre.src-delphi:before { content: 'Delphi'; }
  pre.src-html:before { content: 'HTML'; }
  pre.src-idl:before { content: 'IDL'; }
  pre.src-mercury:before { content: 'Mercury'; }
  pre.src-metapost:before { content: 'MetaPost'; }
  pre.src-modula-2:before { content: 'Modula-2'; }
  pre.src-pascal:before { content: 'Pascal'; }
  pre.src-ps:before { content: 'PostScript'; }
  pre.src-prolog:before { content: 'Prolog'; }
  pre.src-simula:before { content: 'Simula'; }
  pre.src-tcl:before { content: 'tcl'; }
  pre.src-tex:before { content: 'TeX'; }
  pre.src-plain-tex:before { content: 'Plain TeX'; }
  pre.src-verilog:before { content: 'Verilog'; }
  pre.src-vhdl:before { content: 'VHDL'; }
  pre.src-xml:before { content: 'XML'; }
  pre.src-nxml:before { content: 'XML'; }
  /* add a generic configuration mode; LaTeX export needs an additional
     (add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
  pre.src-conf:before { content: 'Configuration File'; }

  table { border-collapse:collapse; }
  caption.t-above { caption-side: top; }
  caption.t-bottom { caption-side: bottom; }
  td, th { vertical-align:top;  }
  th.org-right  { text-align: center;  }
  th.org-left   { text-align: center;   }
  th.org-center { text-align: center; }
  td.org-right  { text-align: right;  }
  td.org-left   { text-align: left;   }
  td.org-center { text-align: center; }
  dt { font-weight: bold; }
  .footpara { display: inline; }
  .footdef  { margin-bottom: 1em; }
  .figure { padding: 1em; }
  .figure p { text-align: center; }
  .equation-container {
    display: table;
    text-align: center;
    width: 100%;
  }
  .equation {
    vertical-align: middle;
  }
  .equation-label {
    display: table-cell;
    text-align: right;
    vertical-align: middle;
  }
  .inlinetask {
    padding: 10px;
    border: 2px solid gray;
    margin: 10px;
    background: #ffffcc;
  }
  #org-div-home-and-up
   { text-align: right; font-size: 70%; white-space: nowrap; }
  textarea { overflow-x: auto; }
  .linenr { font-size: smaller }
  .code-highlighted { background-color: #ffff00; }
  .org-info-js_info-navigation { border-style: none; }
  #org-info-js_console-label
    { font-size: 10px; font-weight: bold; white-space: nowrap; }
  .org-info-js_search-highlight
    { background-color: #ffff00; color: #000000; font-weight: bold; }
  .org-svg { width: 90%; }
  /*]]>*/-->
</style>
<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">P2505R1 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="#org3dd5de3">Introduction</a></li>
<li><a href="#orgeac7d99">Motivation and Scope</a></li>
<li><a href="#org859cf8f">Design Considerations</a>
<ul>
<li><a href="#org27b7a48"><code>expected&lt;void, E&gt;</code></a></li>
<li><a href="#org7501ee0"><code>transform_or</code> function</a></li>
<li><a href="#orgc294337">changing of error return types</a></li>
</ul>
</li>
<li><a href="#orgef22059">Other Languages</a></li>
<li><a href="#orgadc39d8">Implementations</a></li>
<li><a href="#org8bd6a42">Wording</a>
<ul>
<li><a href="#org297c411">Feature Test Macro</a></li>
<li><a href="#orgc4ee019">Class template expected [expected.expected]</a></li>
<li><a href="#org0c1f537">Add a new sub-clause Monadic operations for [expected.monadic] between [expected.observe] and [expected.equality]</a></li>
<li><a href="#org8d1592a">Partial specialization of expected for void types [expected.void]</a></li>
<li><a href="#org54283b5">Partial specialization of expected for void [expected.void.observe]</a></li>
</ul>
</li>
<li><a href="#org8470d49">Acknowledgements</a></li>
<li><a href="#orgaea3dca">Revision History</a></li>
<li><a href="#org8a63904">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-org3dd5de3" class="outline-2">
<h2 id="org3dd5de3">Introduction</h2>
<div class="outline-text-2" id="text-org3dd5de3">
<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-orgeac7d99" class="outline-2">
<h2 id="orgeac7d99">Motivation and Scope</h2>
<div class="outline-text-2" id="text-orgeac7d99">
<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 on the R0, this draft also proposes the addition of a fourth function for <code>expected</code> to facilitate additional cases:
</p>

<ul class="org-ul">
<li><code>transform_or</code> apply a function to change the value, otherwise call a function with error type</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>
For more examples see: <a href="https://godbolt.org/z/va5fzx11f">https://godbolt.org/z/va5fzx11f</a>
</p>
</div>
</div>

<div id="outline-container-org859cf8f" class="outline-2">
<h2 id="org859cf8f">Design Considerations</h2>
<div class="outline-text-2" id="text-org859cf8f">
</div>
<div id="outline-container-org27b7a48" class="outline-3">
<h3 id="org27b7a48"><code>expected&lt;void, E&gt;</code></h3>
<div class="outline-text-3" id="text-org27b7a48">
<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-org7501ee0" class="outline-3">
<h3 id="org7501ee0"><code>transform_or</code> function</h3>
<div class="outline-text-3" id="text-org7501ee0">
<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>.
</p>
</div>
</div>

<div id="outline-container-orgc294337" class="outline-3">
<h3 id="orgc294337">changing of error return types</h3>
<div class="outline-text-3" id="text-orgc294337">
<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_or</code> overloads only.
</p>
</div>
</div>
</div>

<div id="outline-container-orgef22059" class="outline-2">
<h2 id="orgef22059">Other Languages</h2>
<div class="outline-text-2" id="text-orgef22059">
<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-orgadc39d8" class="outline-2">
<h2 id="orgadc39d8">Implementations</h2>
<div class="outline-text-2" id="text-orgadc39d8">
<p>
This has been 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>. The author is unaware of another expected implementation that adds these functions. 
</p>
</div>
</div>

<div id="outline-container-org8bd6a42" class="outline-2">
<h2 id="org8bd6a42">Wording</h2>
<div class="outline-text-2" id="text-org8bd6a42">
</div>
<div id="outline-container-org297c411" class="outline-3">
<h3 id="org297c411">Feature Test Macro</h3>
<div class="outline-text-3" id="text-org297c411">
<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-orgc4ee019" class="outline-3">
<h3 id="orgc4ee019">Class template expected [expected.expected]</h3>
<div class="outline-text-3" id="text-orgc4ee019">
<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: #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_or(<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_or(<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_or(<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_or(<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.mod], modifiers</span>
</pre>
</div>
</div>
</div>

<div id="outline-container-org0c1f537" class="outline-3">
<h3 id="org0c1f537">Add a new sub-clause Monadic operations for [expected.monadic] between [expected.observe] and [expected.equality]</h3>
<div class="outline-text-3" id="text-org0c1f537">
<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_same_v&lt;U::error_type, E&gt;</code> is true. E and U model <code>copy_constructible</code>.
</p>

<p>
<i>Mandates:</i> U is a specialization of <code>expected</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> (*<span style="color: #a020f0;">this</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>), value());
}
<span style="color: #a020f0;">else</span> { 
   <span style="color: #a020f0;">return</span> *<span style="color: #a020f0;">this</span>;
}
</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(value())&gt;&gt;</code>.
</p>

<p>
<i>Constraints:</i> <code>is_same_v&lt;U::error_type, E&gt;</code> is true. E and U model <code>move_constructible</code>.
</p>

<p>
<i>Mandates:</i> U is a specialization of <code>expected</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> (*<span style="color: #a020f0;">this</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(value()));
}
<span style="color: #a020f0;">else</span> { 
   <span style="color: #a020f0;">return</span> <span style="color: #008b8b;">std</span>::move(*<span style="color: #a020f0;">this</span>);
}
</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 U be <code>remove_cvref_t&lt;invoke_result_t&lt;F, decltype(error())&gt;&gt;</code>. 
</p>

<p>
<i>Constraints:</i> <code>is_same_v&lt;U::value_type, T&gt;</code> is true. U and E model <code>copy_constructible</code>.
</p>

<p>
<i>Mandates:</i> U is a specialization of <code>expected</code>.
</p>

<p>
Effects: Equivalent to:
</p>
<div class="org-src-container">
<pre class="src src-C++"><span style="color: #a020f0;">if</span> (*<span style="color: #a020f0;">this</span>) {
    <span style="color: #a020f0;">return</span> U(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 U be <code>remove_cvref_t&lt;invoke_result_t&lt;F, decltype(error())&gt;&gt;</code>. 
</p>

<p>
<i>Constraints:</i> <code>is_same_v&lt;U::value_type, T&gt;</code> is true. U and E model <code>move_constructible</code>.
</p>

<p>
<i>Mandates:</i> U is a specialization of <code>expected</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> (*<span style="color: #a020f0;">this</span>) { 
   <span style="color: #a020f0;">return</span> <span style="color: #008b8b;">std</span>::move(*<span style="color: #a020f0;">this</span>);
}
<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>::<span style="color: #228b22;">move</span>(<span style="color: #a0522d;">error</span>())));
}
</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(error())&gt;&gt;</code>. 
</p>

<p>
<i>Constraints:</i> <code>is_same_v&lt;U::error_type, E&gt;</code> is true. E and U model <code>copy_constructible</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> (*<span style="color: #a020f0;">this</span>) {
   <span style="color: #a020f0;">return</span> <span style="color: #228b22;">expected</span>&lt;U,E&gt;(in_place, 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> *<span style="color: #a020f0;">this</span>;
}
</pre>
</div>

<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(error())&gt;&gt;</code>. 
</p>

<p>
<i>Constraints:</i> <code>is_same_v&lt;U::error_type, E&gt;</code> is true. E and U model <code>move_constructible</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> (*<span style="color: #a020f0;">this</span>) { 
   <span style="color: #a020f0;">return</span> <span style="color: #228b22;">expected</span>&lt;U,E&gt;(in_place, 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> <span style="color: #008b8b;">std</span>::move(*<span style="color: #a020f0;">this</span>);
}
</pre>
</div>
<p>
1 <code>template &lt;class F&gt; constexpr auto transform_or(F&amp;&amp; f) &amp;;</code>
</p>

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

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

<p>
<i>Constraints:</i> <code>is_same_v&lt;U::value_type, T&gt;</code> is true. U and E model <code>copy_constructible</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> (*<span style="color: #a020f0;">this</span>) { 
    <span style="color: #a020f0;">return</span> *<span style="color: #a020f0;">this</span>;
} 
<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: #228b22;">error</span>()));
}
</pre>
</div>
<p>
1 <code>template &lt;class F&gt; constexpr auto transform_or(F&amp;&amp; f) &amp;&amp;;</code>
</p>

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

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

<p>
<i>Constraints:</i> <code>is_same_v&lt;U::value_type, T&gt;</code> is true. U and E model <code>move_constructible</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> (*<span style="color: #a020f0;">this</span>) { 
   <span style="color: #a020f0;">return</span> <span style="color: #008b8b;">std</span>::move(*<span style="color: #a020f0;">this</span>);
}
<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>::<span style="color: #228b22;">move</span>(<span style="color: #a0522d;">error</span>())));
}
</pre>
</div>
</div>
</div>

<div id="outline-container-org8d1592a" class="outline-3">
<h3 id="org8d1592a">Partial specialization of expected for void types [expected.void]</h3>
<div class="outline-text-3" id="text-org8d1592a">
<p>
After �.�.8.6, observers &#x2013; add
</p>

<div class="org-src-container">
<pre class="src src-C++"><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_or(<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_or(<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_or(<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_or(<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-org54283b5" class="outline-3">
<h3 id="org54283b5">Partial specialization of expected for void [expected.void.observe]</h3>
<div class="outline-text-3" id="text-org54283b5">
<p>
After section �.�.8.5 Observers [expected.void.observe]
</p>

<p>
Add section �.�.8.6 Monadic [expected.void.monadic]
</p>

<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>
3 <code>template &lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) &amp;&amp;;</code>
</p>

<p>
4 <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,void&gt;&gt;</code>. 
</p>

<p>
<i>Constraints:</i> <code>is_same_v&lt;U::error_type, E&gt;</code> is true. E models <code>copy_constructible</code> for the first two overloads and <code>move_constructible</code> for the second two overloads. [ <i>Note:</i> U will implicitly model either copy or move constructible since U is <code>expected&lt;void, E&gt;</code> &#x2013; <i>end note</i> ].
</p>

<p>
<i>Mandates:</i> U is a specialization of <code>expected</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> (*<span style="color: #a020f0;">this</span>) { 
   <span style="color: #a020f0;">return</span> <span style="color: #008b8b;">std</span>::move(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> <span style="color: #008b8b;">std</span>::move(*<span style="color: #a020f0;">this</span>);
}
</pre>
</div>

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

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

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

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

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

<p>
<i>Constraints:</i>  E models <code>copy_constructible</code> for the first two overloads and <code>move_constructible</code> for the second two overloads.
</p>

<p>
<i>Mandates:</i> U is a specialization of <code>expected</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> (*<span style="color: #a020f0;">this</span>) { 
    <span style="color: #a020f0;">return</span> <span style="color: #008b8b;">std</span>::move(*<span style="color: #a020f0;">this</span>);
} 
<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>)());
}
</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>
3 <code>template &lt;class F&gt; constexpr auto transform(F&amp;&amp; f) &amp;&amp;;</code>
</p>

<p>
4 <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,void&gt;&gt;</code>. 
</p>

<p>
<i>Constraints:</i> <code>is_same_v&lt;U::error_type, E&gt;</code> is true. E models <code>copy_constructible</code> for the first two overloads and <code>move_constructible</code> for the second two overloads.
</p>

<p>
<i>Effects:</i> Equivalent to:
</p>
<div class="org-src-container">
<pre class="src src-C++"><span style="color: #a020f0;">if</span> (*<span style="color: #a020f0;">this</span>) {
   <span style="color: #a020f0;">return</span> <span style="color: #228b22;">expected</span>&lt;U,E&gt;(in_place, 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> <span style="color: #008b8b;">std</span>::move(*<span style="color: #a020f0;">this</span>);
}
</pre>
</div>

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

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

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

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

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

<p>
<i>Constraints:</i>  <code>is_same_v&lt;U::error_type, E&gt;</code> is true. E models <code>copy_constructible</code> for the first two overloads and <code>move_constructible</code> for the second two overloads.
</p>

<p>
<i>Mandates:</i> U is a specialization of <code>expected</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> (*<span style="color: #a020f0;">this</span>) { 
    <span style="color: #a020f0;">return</span> <span style="color: #008b8b;">std</span>::move(*<span style="color: #a020f0;">this</span>);
} 
<span style="color: #a020f0;">else</span> { 
   <span style="color: #a020f0;">return</span> <span style="color: #008b8b;">std</span>::move(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: #228b22;">error</span>())));
}
</pre>
</div>
</div>
</div>
</div>

<div id="outline-container-org8470d49" class="outline-2">
<h2 id="org8470d49">Acknowledgements</h2>
<div class="outline-text-2" id="text-org8470d49">
<ul class="org-ul">
<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.</li>
</ul>
</div>
</div>
<div id="outline-container-orgaea3dca" class="outline-2">
<h2 id="orgaea3dca">Revision History</h2>
<div class="outline-text-2" id="text-orgaea3dca">
<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>
</table>
</div>
</div>

<div id="outline-container-org8a63904" class="outline-2">
<h2 id="org8a63904">References</h2>
<div class="outline-text-2" id="text-org8a63904">
<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>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-02-15 Tue 08:58</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
</body>
</html>
