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.
optional<T> to T may be ill-formedSection: 22.5.9 [optional.comp.with.t] Status: Tentatively Ready Submitter: Hewill Kang Opened: 2025-09-06 Last modified: 2025-10-16
Priority: Not Prioritized
View all other issues in [optional.comp.with.t].
View all issues with Tentatively Ready status.
Discussion:
When comparing an optional with its value type, the current wording specifies that the result is the
ternary expression of x.has_value() ? *x == v : false, where *x == v returns a result that can be
implicitly converted to bool.
bool (which is common), the ternary operation
will be ill-formed due to ambiguity (demo):
#include <optional>
struct Bool {
Bool(bool);
operator bool() const;
};
struct S {
Bool operator==(S) const;
};
int main() {
return std::optional<S>{} == S{}; // fire
}
[2025-10-16; Reflector poll]
Set status to Tentatively Ready after seven votes in favour during reflector poll.
"Alternatively could keep the conditional operator but cast one side to bool,
but that would do an explicit conversion, which might not be what we want."
"Should just require boolean-testable."
Proposed resolution:
This wording is relative to N5014.
Modify 22.5.9 [optional.comp.with.t] as indicated:
template<class T, class U> constexpr bool operator==(const optional<T>& x, const U& v);-1- Constraints:
[Note 1:Uis not a specialization ofoptional. The expression*x == vis well-formed and its result is convertible tobool.Tneed not be Cpp17EqualityComparable. — end note] -2- Effects: Equivalent to:return x.has_value() ? *x == v : false;if (x.has_value()) return *x == v; return false;template<class T, class U> constexpr bool operator==(const T& v, const optional<U>& x);-3- Constraints:
-4- Effects: Equivalent to:Tis not a specialization ofoptional. The expressionv == *xis well-formed and its result is convertible tobool.return x.has_value() ? v == *x : false;if (x.has_value()) return v == *x; return false;template<class T, class U> constexpr bool operator!=(const optional<T>& x, const U& v);-5- Constraints:
-6- Effects: Equivalent to:Uis not a specialization ofoptional. The expression*x != vis well-formed and its result is convertible tobool.return x.has_value() ? *x != v : true;if (x.has_value()) return *x != v; return true;template<class T, class U> constexpr bool operator!=(const T& v, const optional<U>& x);-7- Constraints:
-8- Effects: Equivalent to:Tis not a specialization ofoptional. The expressionv != *xis well-formed and its result is convertible tobool.return x.has_value() ? v != *x : true;if (x.has_value()) return v != *x; return true;template<class T, class U> constexpr bool operator<(const optional<T>& x, const U& v);-9- Constraints:
-10- Effects: Equivalent to:Uis not a specialization ofoptional. The expression*x < vis well-formed and its result is convertible tobool.return x.has_value() ? *x < v : true;if (x.has_value()) return *x < v; return true;template<class T, class U> constexpr bool operator<(const T& v, const optional<U>& x);-11- Constraints:
-12- Effects: Equivalent to:Tis not a specialization ofoptional. The expressionv < *xis well-formed and its result is convertible tobool.return x.has_value() ? v < *x : false;if (x.has_value()) return v < *x; return false;template<class T, class U> constexpr bool operator>(const optional<T>& x, const U& v);-13- Constraints:
-14- Effects: Equivalent to:Uis not a specialization ofoptional. The expression*x > vis well-formed and its result is convertible tobool.return x.has_value() ? *x > v : false;if (x.has_value()) return *x > v; return false;template<class T, class U> constexpr bool operator>(const T& v, const optional<U>& x);-15- Constraints:
-16- Effects: Equivalent to:Tis not a specialization ofoptional. The expressionv > *xis well-formed and its result is convertible tobool.return x.has_value() ? v > *x : true;if (x.has_value()) return v > *x; return true;template<class T, class U> constexpr bool operator<=(const optional<T>& x, const U& v);-17- Constraints:
-18- Effects: Equivalent to:Uis not a specialization ofoptional. The expression*x <= vis well-formed and its result is convertible tobool.return x.has_value() ? *x <= v : true;if (x.has_value()) return *x <= v; return true;template<class T, class U> constexpr bool operator<=(const T& v, const optional<U>& x);-19- Constraints:
-20- Effects: Equivalent to:Tis not a specialization ofoptional. The expressionv <= *xis well-formed and its result is convertible tobool.return x.has_value() ? v <= *x : false;if (x.has_value()) return v <= *x; return false;template<class T, class U> constexpr bool operator>=(const optional<T>& x, const U& v);-21- Constraints:
-22- Effects: Equivalent to:Uis not a specialization ofoptional. The expression*x >= vis well-formed and its result is convertible tobool.return x.has_value() ? *x >= v : false;if (x.has_value()) return *x >= v; return false;template<class T, class U> constexpr bool operator>=(const T& v, const optional<U>& x);-23- Constraints:
-24- Effects: Equivalent to:Tis not a specialization ofoptional. The expressionv >= *xis well-formed and its result is convertible tobool.return x.has_value() ? v >= *x : true;if (x.has_value()) return v >= *x; return true;