<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8">
<title>Constrain std::expected equality operators</title>
  <style type='text/css'>
  body {font-variant-ligatures: none;}
  p {text-align:justify}
  li {text-align:justify}
  blockquote.note, div.note
  {
          background-color:#E0E0E0;
          padding-left: 15px;
          padding-right: 15px;
          padding-top: 1px;
          padding-bottom: 1px;
  }
  p code {color:navy}
  ins p code {background-color:PaleGreen}
  p ins code {background-color:PaleGreen}
  p del code {background-color:LightPink}
  ins {background-color:PaleGreen}
  del {background-color:LightPink}
  table#boilerplate { border:0 }
  table#boilerplate td { padding-left: 2em }
  table.bordered, table.bordered th, table.bordered td {
    border: 1px solid;
    text-align: center;
  }
  ins.block {background-color:PaleGreen; text-decoration: none}
  del.block {background-color:LightPink; text-decoration: none}
  #hidedel:checked ~ * del, #hidedel:checked ~ * del * { display:none; visibility:hidden }
  </style>
<meta property="og:title" content="Constrain std::expected equality operators">
<meta property="og:type" content="website">
<meta property="og:image" content="https://isocpp.org/assets/images/cpp_logo.png">
<meta property="og:url" content="https://wg21.link/<tr><td>Document number</td><td>P3379R0</td></tr>">
</head><body>
<table id="boilerplate">
<tr><td>Document number</td><td>P3379R0</td></tr>
<tr><td>Date</td><td>2024-08-23</td></tr>
<tr><td>Project</td><td>Programming Language C++, Library Evolution Working Group</td></tr>
<tr><td>Reply-to</td><td>Jonathan Wakely &lt;cxx&#x40;kayari.org&gt;</td></tr>
</table><hr>
<h1>Constrain std::expected equality operators</h1>
<h2>Revision History</h2>

<ul>
<li>Initial revision</li>
</ul>


<h2>Introduction</h2>

<p><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2944r3.html" title="Comparisons for reference_wrapper">P2944R3</a> (Comparisons for <code>reference_wrapper</code>)
added constraints to the relational operators for <code>pair</code>, <code>tuple</code>,
<code>optional</code>, and <code>variant</code>, but missed <code>expected</code> out. We should fix that.</p>

<h2>Discussion</h2>

<p>We needed LWG issue <a href="https://cplusplus.github.io/LWG/issue4072">4072</a> to
fix the constraints for <code>std::optional</code>. We should do the same here.</p>

<p>This has been implemented and tested in libstdc++.</p>

<h2>Proposed wording</h2>

<p>The edits are shown relative to <a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4988.pdf" title="Working Draft - Programming Languages -- C++">N4988</a>.</p>

<p>Update the value of the <code>__cpp_lib_constrained_equality</code> feature test macro
in [version.syn].</p>

<p>Change <em>Mandates</em>: to <em>Constraints</em>: in [expected.object.eq]:</p>

<p><strong>22.8.6.8 Equality operators [expected.object.eq]</strong></p>

<pre><code>template&lt;class T2, class E2&gt; requires (!is_void_v&lt;T2&gt;)
  friend constexpr bool operator==(const expected&amp; x, const expected&lt;T2, E2&gt;&amp; y);
</code></pre>

<p>-1- <del><em>Mandates</em></del> <ins><em>Constraints</em></ins>:
The expressions <code>*x == *y</code> and <code>x.error() == y.error()</code> are well-formed
and their results are convertible to <code>bool</code>.</p>

<p>-2- <em>Returns</em>: If <code>x.has_value()</code> does not equal <code>y.has_value()</code>, <code>false</code>;
otherwise if <code>x.has_value()</code> is <code>true</code>, <code>*x == *y</code>;
otherwise <code>x.error() == y.error()</code>.</p>

<pre><code>template&lt;class T2&gt; friend constexpr bool operator==(const expected&amp; x, const T2&amp; v);
</code></pre>

<p>-3- <del><em>Mandates</em></del> <ins><em>Constraints</em></ins>:
<ins><code>T2</code> is not a specialization of <code>expected</code>.</ins>
The expression <code>*x == v</code> is well-formed and its result is convertible to <code>bool</code>.</p>

<p>[<em>Note 1</em>: <code>T</code> need not be <em>Cpp17EqualityComparable</em>. — <em>end note</em>]</p>

<p>-4- <em>Returns</em>: <code>x.has_value() &amp;&amp; static_cast&lt;bool&gt;(*x == v)</code>.</p>

<pre><code>template&lt;class E2&gt; friend constexpr bool operator==(const expected&amp; x, const unexpected&lt;E2&gt;&amp; e);
</code></pre>

<p>-5- <del><em>Mandates</em></del> <ins><em>Constraints</em></ins>:
The expression <code>x.error() == e.error()</code> is well-formed
and its result is convertible to <code>bool</code>.</p>

<p>-6- <em>Returns</em>: <code>!x.has_value() &amp;&amp; static_cast&lt;bool&gt;(x.error() == e.error())</code>.</p>

<p>Change <em>Mandates</em>: to <em>Constraints</em>: in [expected.void.eq]:</p>

<p><strong>22.8.7.8 Equality operators [expected.void.eq]</strong></p>

<pre><code>template&lt;class T2, class E2&gt; requires is_void_v&lt;T2&gt;
  friend constexpr bool operator==(const expected&amp; x, const expected&lt;T2, E2&gt;&amp; y);
</code></pre>

<p>-1- <del><em>Mandates</em></del> <ins><em>Constraints</em></ins>:
The expression <code>x.error() == y.error()</code> is well-formed
and its result is convertible to <code>bool</code>.</p>

<p>-2- <em>Returns</em>: If <code>x.has_value()</code> does not equal <code>y.has_value()</code>, <code>false</code>;
otherwise <code>x.has_value() || static_cast&lt;bool&gt;(x.error() == y.error())</code>.</p>

<pre><code>template&lt;class E2&gt;
  friend constexpr bool operator==(const expected&amp; x, const unexpected&lt;E2&gt;&amp; e);
</code></pre>

<p>-3- <del><em>Mandates</em></del> <ins><em>Constraints</em></ins>:
The expression <code>x.error() == e.error()</code> is well-formed
and its result is convertible to <code>bool</code>.</p>

<p>-4- <em>Returns</em>: <code>!x.has_value() &amp;&amp; static_cast&lt;bool&gt;(x.error() == e.error())</code>.</p>

<h2>References</h2>

<p><a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/n4988.pdf" title="Working Draft - Programming Languages -- C++">N4988</a>, Working Draft - Programming Languages -- C++, Thomas Köppe, 2024.<br/>
<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2944r3.html" title="Comparisons for reference_wrapper">P2944R3</a>, Comparisons for <code>reference_wrapper</code>, Barry Revzin, 2024.</p>
</body></html>
