Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1882a7d

Browse files
committed
New issue from Hewill: "Heterogeneous comparison of expected may be ill-formed"
1 parent 8fcbda3 commit 1882a7d

File tree

1 file changed

+122
-0
lines changed

1 file changed

+122
-0
lines changed

xml/issue4366.xml

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
<?xml version='1.0' encoding='utf-8' standalone='no'?>
2+
<!DOCTYPE issue SYSTEM "lwg-issue.dtd">
3+
4+
<issue num="4366" status="New">
5+
<title>Heterogeneous comparison of `expected` may be ill-formed</title>
6+
<section>
7+
<sref ref="[expected.object.eq]"/><sref ref="[expected.void.eq]"/>
8+
</section>
9+
<submitter>Hewill Kang</submitter>
10+
<date>06 Sep 2025</date>
11+
<priority>99</priority>
12+
13+
<discussion>
14+
<p>
15+
These comparison functions all explicitly `static_cast` the result of the underlying comparison to
16+
`bool`. However, the <i>Constraints</i> only require the implicit conversion, not the explicit one
17+
(i.e., "convertible to `bool`" rather than "models <code><i>boolean-testable</i></code>").
18+
<p/>
19+
This means that in some pathological cases it will lead to hard errors
20+
(<a href="https://godbolt.org/z/b9ehzv3h4">demo</a>):
21+
</p>
22+
<blockquote><pre>
23+
#include &lt;expected&gt;
24+
25+
struct E1 {};
26+
struct E2 {};
27+
28+
struct Bool {
29+
operator bool() const;
30+
explicit operator bool() = delete;
31+
};
32+
Bool operator==(E1, E2);
33+
34+
int main() {
35+
std::unexpected e1{E1{}};
36+
std::unexpected e2{E2{}};
37+
return std::expected&lt;int, E1&gt;{e1} == e2; // <span style="color:#C80000;font-weight:bold">fire</span>
38+
}
39+
</pre></blockquote>
40+
<p>
41+
It is reasonable to specify return consistency with actual <i>Constraints</i>.
42+
</p>
43+
</discussion>
44+
45+
<resolution>
46+
<p>
47+
This wording is relative to <paper num="N5014"/>.
48+
</p>
49+
50+
<ol>
51+
52+
<li><p>Modify <sref ref="[expected.object.eq]"/> as indicated:</p>
53+
54+
<blockquote>
55+
<pre>
56+
template&lt;class T2&gt; friend constexpr bool operator==(const expected&amp; x, const T2&amp; v);
57+
</pre>
58+
<blockquote>
59+
<p>
60+
-3- <i>Constraints</i>: `T2` is not a specialization of `expected`. The expression `*x == v` is well-formed
61+
and its result is convertible to `bool`.
62+
<p/>
63+
[<i>Note 1</i>: <code>T</code> need not be <i>Cpp17EqualityComparable</i>. &mdash; <i>end note</i>]
64+
<p/>
65+
-4- <i>Returns</i>: <ins>If</ins> `x.has_value()` <ins>is `true`,</ins>
66+
<code><del>&amp;&amp; static_cast&lt;bool&gt;(</del>*x == v<del>)</del></code><ins>; otherwise `false`</ins>.
67+
</p>
68+
</blockquote>
69+
<pre>
70+
template&lt;class E2&gt; friend constexpr bool operator==(const expected&amp; x, const unexpected&lt;E2&gt;&amp; e);
71+
</pre>
72+
<blockquote>
73+
<p>
74+
-5- <i>Constraints</i>: The expression `x.error() == e.error()` is well-formed and its result is convertible
75+
to `bool`.
76+
<p/>
77+
-6- <i>Returns</i>: <ins>If</ins> `!x.has_value()` <ins>is `true`,</ins>
78+
<code><del>&amp;&amp; static_cast&lt;bool&gt;(</del>x.error() == e.error()<del>)</del></code><ins>; otherwise `false`</ins>.
79+
</p>
80+
</blockquote>
81+
</blockquote>
82+
83+
</li>
84+
85+
<li><p>Modify <sref ref="[expected.void.eq]"/> as indicated:</p>
86+
87+
<blockquote>
88+
<pre>
89+
template&lt;class T2, class E2&gt; requires is_void_v&lt;T2&gt;
90+
friend constexpr bool operator==(const expected&amp; x, const expected&lt;T2, E2&gt;&amp; y);
91+
</pre>
92+
<blockquote>
93+
<p>
94+
-1- <i>Constraints</i>: The expression `x.error() == y.error()` is well-formed and its result
95+
is convertible to `bool`.
96+
<p/>
97+
-2- <i>Returns</i>: If `x.has_value()` does not equal `y.has_value()`, `false`;
98+
otherwise <ins>if</ins> `x.has_value()` <ins>is `true`, `true`; otherwise</ins>
99+
<code><del>|| static_cast&lt;bool&gt;(</del>x.error() == y.error()<del>)</del></code>.
100+
</p>
101+
</blockquote>
102+
<pre>
103+
template&lt;class E2&gt;
104+
friend constexpr bool operator==(const expected&amp; x, const unexpected&lt;E2&gt;&amp; e);
105+
</pre>
106+
<blockquote>
107+
<p>
108+
-3- <i>Constraints</i>: The expression `x.error() == e.error()` is well-formed and its
109+
result is convertible to `bool`.
110+
<p/>
111+
-4- <i>Returns</i>: <ins>If</ins> `!x.has_value()` <ins>is `true`,</ins>
112+
<code><del>&amp;&amp; static_cast&lt;bool&gt;(</del>x.error() == e.error()<del>)</del></code>
113+
<ins>; otherwise `false`</ins>.
114+
</p>
115+
</blockquote>
116+
</blockquote>
117+
118+
</li>
119+
120+
</ol></resolution>
121+
122+
</issue>

0 commit comments

Comments
 (0)