This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Tentatively Ready status.
expected may be ill-formedSection: 22.8.6.8 [expected.object.eq], 22.8.7.8 [expected.void.eq] Status: Tentatively Ready Submitter: Hewill Kang Opened: 2025-09-06 Last modified: 2025-10-16
Priority: Not Prioritized
View all issues with Tentatively Ready status.
Discussion:
These comparison functions all explicitly static_cast the result of the underlying comparison to
bool. However, the Constraints only require the implicit conversion, not the explicit one
(i.e., "convertible to bool" rather than "models boolean-testable").
#include <expected>
struct E1 {};
struct E2 {};
struct Bool {
operator bool() const;
explicit operator bool() = delete;
};
Bool operator==(E1, E2);
int main() {
std::unexpected e1{E1{}};
std::unexpected e2{E2{}};
return std::expected<int, E1>{e1} == e2; // fire
}
It is reasonable to specify return consistency with actual Constraints.
[2025-10-16; Reflector poll]
Set status to Tentatively Ready after five votes in favour during reflector poll.
Related to LWG 4366(i), but the wording styles are inconsistent.
optional uses "Effects: Equivalent to ..." and expected just uses
Returns:.
Proposed resolution:
This wording is relative to N5014.
Modify 22.8.6.8 [expected.object.eq] as indicated:
template<class T2> friend constexpr bool operator==(const expected& x, const T2& v);-3- Constraints:
[Note 1:T2is not a specialization ofexpected. The expression*x == vis well-formed and its result is convertible tobool.Tneed not be Cpp17EqualityComparable. — end note] -4- Returns: Ifx.has_value()istrue,; otherwise&& static_cast<bool>(*x == v)false.template<class E2> friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);-5- Constraints: The expression
-6- Returns: Ifx.error() == e.error()is well-formed and its result is convertible tobool.!x.has_value()istrue,; otherwise&& static_cast<bool>(x.error() == e.error())false.
Modify 22.8.7.8 [expected.void.eq] as indicated:
template<class T2, class E2> requires is_void_v<T2> friend constexpr bool operator==(const expected& x, const expected<T2, E2>& y);-1- Constraints: The expression
-2- Returns: Ifx.error() == y.error()is well-formed and its result is convertible tobool.x.has_value()does not equaly.has_value(),false; otherwise ifx.has_value()istrue,true; otherwise.|| static_cast<bool>(x.error() == y.error())template<class E2> friend constexpr bool operator==(const expected& x, const unexpected<E2>& e);-3- Constraints: The expression
-4- Returns: Ifx.error() == e.error()is well-formed and its result is convertible tobool.!x.has_value()istrue,; otherwise&& static_cast<bool>(x.error() == e.error())false.