Skip to content

Commit 0eb0702

Browse files
committed
New issue from Hewill: "Comparison of optional<T> to T may be ill-formed"
1 parent 5cc76c5 commit 0eb0702

File tree

1 file changed

+251
-0
lines changed

1 file changed

+251
-0
lines changed

xml/issue4370.xml

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
<?xml version='1.0' encoding='utf-8' standalone='no'?>
2+
<!DOCTYPE issue SYSTEM "lwg-issue.dtd">
3+
4+
<issue num="4370" status="New">
5+
<title>Comparison of <code>optional&lt;T&gt;</code> to <code>T</code> may be ill-formed</title>
6+
<section>
7+
<sref ref="[optional.comp.with.t]"/>
8+
</section>
9+
<submitter>Hewill Kang</submitter>
10+
<date>06 Sep 2025</date>
11+
<priority>99</priority>
12+
13+
<discussion>
14+
<p>
15+
When comparing an `optional` with its value type, the current wording specifies that the result is the
16+
ternary expression of `x.has_value() ? *x == v : false`, where `*x == v` returns a result that can be
17+
implicitly converted to `bool`.
18+
<p/>
19+
However, when the result can also be constructed using `bool` (which is common), the ternary operation
20+
will be ill-formed due to ambiguity (<a href="https://godbolt.org/z/r55Wh51Y8">demo</a>):
21+
</p>
22+
<blockquote><pre>
23+
#include &lt;optional&gt;
24+
25+
struct Bool {
26+
Bool(bool);
27+
operator bool() const;
28+
};
29+
30+
struct S {
31+
Bool operator==(S) const;
32+
};
33+
34+
int main() {
35+
return std::optional&lt;S&gt;{} == S{}; // <span style="color:#C80000;font-weight:bold">fire</span>
36+
}
37+
</pre></blockquote>
38+
</discussion>
39+
40+
<resolution>
41+
<p>
42+
This wording is relative to <paper num="N5014"/>.
43+
</p>
44+
45+
<ol>
46+
47+
<li><p>Modify <sref ref="[optional.comp.with.t]"/> as indicated:</p>
48+
49+
<blockquote>
50+
<pre>
51+
template&lt;class T, class U&gt; constexpr bool operator==(const optional&lt;T&gt;&amp; x, const U&amp; v);
52+
</pre>
53+
<blockquote>
54+
<p>
55+
-1- <i>Constraints</i>: `U` is not a specialization of `optional`. The expression `*x == v` is well-formed
56+
and its result is convertible to `bool`.
57+
<p/>
58+
[<i>Note 1</i>: `T` need not be <i>Cpp17EqualityComparable</i>. &mdash; end note]
59+
<p/>
60+
-2- <i>Effects</i>: Equivalent to: <del>`return x.has_value() ? *x == v : false;`</del>
61+
</p>
62+
<blockquote><pre>
63+
<ins>if (x.has_value())
64+
return *x == v;
65+
return false;</ins>
66+
</pre></blockquote>
67+
</blockquote>
68+
<pre>
69+
template&lt;class T, class U&gt; constexpr bool operator==(const T&amp; v, const optional&lt;U&gt;&amp; x);
70+
</pre>
71+
<blockquote>
72+
<p>
73+
-3- <i>Constraints</i>: `T` is not a specialization of `optional`. The expression `v == *x` is well-formed
74+
and its result is convertible to `bool`.
75+
<p/>
76+
-4- <i>Effects</i>: Equivalent to: <del>`return x.has_value() ? v == *x : false;`</del>
77+
</p>
78+
<blockquote><pre>
79+
<ins>if (x.has_value())
80+
return v == *x;
81+
return false;</ins>
82+
</pre></blockquote>
83+
</blockquote>
84+
<pre>
85+
template&lt;class T, class U&gt; constexpr bool operator!=(const optional&lt;T&gt;&amp; x, const U&amp; v);
86+
</pre>
87+
<blockquote>
88+
<p>
89+
-5- <i>Constraints</i>: `U` is not a specialization of `optional`. The expression `*x != v` is well-formed
90+
and its result is convertible to `bool`.
91+
<p/>
92+
-6- <i>Effects</i>: Equivalent to: <del>`return x.has_value() ? *x != v : true;`</del>
93+
</p>
94+
<blockquote><pre>
95+
<ins>if (x.has_value())
96+
return *x != v;
97+
return true;</ins>
98+
</pre></blockquote>
99+
</blockquote>
100+
<pre>
101+
template&lt;class T, class U&gt; constexpr bool operator!=(const T&amp; v, const optional&lt;U&gt;&amp; x);
102+
</pre>
103+
<blockquote>
104+
<p>
105+
-7- <i>Constraints</i>: `T` is not a specialization of `optional`. The expression `v != *x` is well-formed
106+
and its result is convertible to `bool`.
107+
<p/>
108+
-8- <i>Effects</i>: Equivalent to: <del>`return x.has_value() ? v != *x : true;`</del>
109+
</p>
110+
<blockquote><pre>
111+
<ins>if (x.has_value())
112+
return v != *x;
113+
return true;</ins>
114+
</pre></blockquote>
115+
</blockquote>
116+
<pre>
117+
template&lt;class T, class U&gt; constexpr bool operator&lt;(const optional&lt;T&gt;&amp; x, const U&amp; v);
118+
</pre>
119+
<blockquote>
120+
<p>
121+
-9- <i>Constraints</i>: `U` is not a specialization of `optional`. The expression <code>*x &lt; v</code> is well-formed
122+
and its result is convertible to `bool`.
123+
<p/>
124+
-10- <i>Effects</i>: Equivalent to: <del><code>return x.has_value() ? *x &lt; v : true;</code></del>
125+
</p>
126+
<blockquote><pre>
127+
<ins>if (x.has_value())
128+
return *x &lt; v;
129+
return true;</ins>
130+
</pre></blockquote>
131+
</blockquote>
132+
<pre>
133+
template&lt;class T, class U&gt; constexpr bool operator&lt;(const T&amp; v, const optional&lt;U&gt;&amp; x);
134+
</pre>
135+
<blockquote>
136+
<p>
137+
-11- <i>Constraints</i>: `T` is not a specialization of `optional`. The expression <code>v &lt; *x</code>
138+
is well-formed and its result is convertible to `bool`.
139+
<p/>
140+
-12- <i>Effects</i>: Equivalent to: <del><code>return x.has_value() ? v &lt; *x : false;</code></del>
141+
</p>
142+
<blockquote><pre>
143+
<ins>if (x.has_value())
144+
return v &lt; *x;
145+
return false;</ins>
146+
</pre></blockquote>
147+
</blockquote>
148+
<pre>
149+
template&lt;class T, class U&gt; constexpr bool operator&gt;(const optional&lt;T&gt;&amp; x, const U&amp; v);
150+
</pre>
151+
<blockquote>
152+
<p>
153+
-13- <i>Constraints</i>: `U` is not a specialization of `optional`. The expression <code>*x &gt; v</code> is
154+
well-formed and its result is convertible to `bool`.
155+
<p/>
156+
-14- <i>Effects</i>: Equivalent to: <del><code>return x.has_value() ? *x &gt; v : false;</code></del>
157+
</p>
158+
<blockquote><pre>
159+
<ins>if (x.has_value())
160+
return *x &gt; v;
161+
return false;</ins>
162+
</pre></blockquote>
163+
</blockquote>
164+
<pre>
165+
template&lt;class T, class U&gt; constexpr bool operator&gt;(const T&amp; v, const optional&lt;U&gt;&amp; x);
166+
</pre>
167+
<blockquote>
168+
<p>
169+
-15- <i>Constraints</i>: `T` is not a specialization of `optional`. The expression <code>v &gt; *x</code>
170+
is well-formed and its result is convertible to `bool`.
171+
<p/>
172+
-16- <i>Effects</i>: Equivalent to: <del><code>return x.has_value() ? v &gt; *x : true;</code></del>
173+
</p>
174+
<blockquote><pre>
175+
<ins>if (x.has_value())
176+
return v &gt; *x;
177+
return true;</ins>
178+
</pre></blockquote>
179+
</blockquote>
180+
<pre>
181+
template&lt;class T, class U&gt; constexpr bool operator&lt;=(const optional&lt;T&gt;&amp; x, const U&amp; v);
182+
</pre>
183+
<blockquote>
184+
<p>
185+
-17- <i>Constraints</i>: `U` is not a specialization of `optional`. The expression <code>*x &lt;= v</code>
186+
is well-formed and its result is convertible to `bool`.
187+
<p/>
188+
-18- <i>Effects</i>: Equivalent to: <del><code>return x.has_value() ? *x &lt;= v : true;</code></del>
189+
</p>
190+
<blockquote><pre>
191+
<ins>if (x.has_value())
192+
return *x &lt;= v;
193+
return true;</ins>
194+
</pre></blockquote>
195+
</blockquote>
196+
<pre>
197+
template&lt;class T, class U&gt; constexpr bool operator&lt;=(const T&amp; v, const optional&lt;U&gt;&amp; x);
198+
</pre>
199+
<blockquote>
200+
<p>
201+
-19- <i>Constraints</i>: `T` is not a specialization of `optional`. The expression <code>v &lt;= *x</code>
202+
is well-formed and its result is convertible to `bool`.
203+
<p/>
204+
-20- <i>Effects</i>: Equivalent to: <del><code>return x.has_value() ? v &lt;= *x : false;</code></del>
205+
</p>
206+
<blockquote><pre>
207+
<ins>if (x.has_value())
208+
return v &lt;= *x;
209+
return false;</ins>
210+
</pre></blockquote>
211+
</blockquote>
212+
<pre>
213+
template&lt;class T, class U&gt; constexpr bool operator&gt;=(const optional&lt;T&gt;&amp; x, const U&amp; v);
214+
</pre>
215+
<blockquote>
216+
<p>
217+
-21- <i>Constraints</i>: `U` is not a specialization of `optional`. The expression <code>*x &gt;= v</code>
218+
is well-formed and its result is convertible to `bool`.
219+
<p/>
220+
-22- <i>Effects</i>: Equivalent to: <del><code>return x.has_value() ? *x &gt;= v : false;</code></del>
221+
</p>
222+
<blockquote><pre>
223+
<ins>if (x.has_value())
224+
return *x &gt;= v;
225+
return false;</ins>
226+
</pre></blockquote>
227+
</blockquote>
228+
<pre>
229+
template&lt;class T, class U&gt; constexpr bool operator&gt;=(const T&amp; v, const optional&lt;U&gt;&amp; x);
230+
</pre>
231+
<blockquote>
232+
<p>
233+
-23- <i>Constraints</i>: `T` is not a specialization of `optional`. The expression <code>v &gt;= *x</code>
234+
is well-formed and its result is convertible to `bool`.
235+
<p/>
236+
-24- <i>Effects</i>: Equivalent to: <del><code>return x.has_value() ? v &gt;= *x : true;</code></del>
237+
</p>
238+
<blockquote><pre>
239+
<ins>if (x.has_value())
240+
return v &gt;= *x;
241+
return true;</ins>
242+
</pre></blockquote>
243+
</blockquote>
244+
245+
</blockquote>
246+
247+
</li>
248+
249+
</ol></resolution>
250+
251+
</issue>

0 commit comments

Comments
 (0)