optional<const T>
doesn't compare with T
Section: 22.5.8 [optional.comp.with.t] Status: C++17 Submitter: Ville Voutilainen Opened: 2017-02-17 Last modified: 2021-06-06
Priority: Not Prioritized
View all other issues in [optional.comp.with.t].
View all issues with C++17 status.
Discussion:
Consider:
optional<const int> x = 42; int y = 666; x == y; // ill-formed
The comparison is ill-formed, because in [optional.comp_with_t]/1,
template <class T> constexpr bool operator==(const optional<T>& x, const T& v);
the T
is deduced to be both const int
and int
, which is ill-formed.
Since it became apparent that the root cause of this issue is also causing difficulties with e.g.
comparing optional<string>
with literals etc., here's a p/r that
adds requirements for optional
's comparisons with T
turns optional
-optional
comparisons into two-template-parameter
templates, allowing comparing mixed optionals
turns optional
-T
comparisons into two-template-parameter templates,
allowing comparing optionals with T
and types comparable with T
[Kona 2017-02-28]
Accepted as Immediate to avoid having break ABI later.
Proposed resolution:
This wording is relative to N4640.
Modify 22.5.2 [optional.syn], header <optional>
synopsis, as indicated:
[…] // 22.5.6 [optional.relops], relational operators template <class T, class U> constexpr bool operator==(const optional<T>&, const optional<TU>&); template <class T, class U> constexpr bool operator!=(const optional<T>&, const optional<TU>&); template <class T, class U> constexpr bool operator<(const optional<T>&, const optional<TU>&); template <class T, class U> constexpr bool operator>(const optional<T>&, const optional<TU>&); template <class T, class U> constexpr bool operator<=(const optional<T>&, const optional<TU>&); template <class T, class U> constexpr bool operator>=(const optional<T>&, const optional<TU>&); […] // [optional.comp_with_t], comparison with T template <class T, class U> constexpr bool operator==(const optional<T>&, constTU&); template <class T, class U> constexpr bool operator==(constTU&, const optional<T>&); template <class T, class U> constexpr bool operator!=(const optional<T>&, constTU&); template <class T, class U> constexpr bool operator!=(constTU&, const optional<T>&); template <class T, class U> constexpr bool operator<(const optional<T>&, constTU&); template <class T, class U> constexpr bool operator<(constTU&, const optional<T>&); template <class T, class U> constexpr bool operator<=(const optional<T>&, constTU&); template <class T, class U> constexpr bool operator<=(constTU&, const optional<T>&); template <class T, class U> constexpr bool operator>(const optional<T>&, constTU&); template <class T, class U> constexpr bool operator>(constTU&, const optional<T>&); template <class T, class U> constexpr bool operator>=(const optional<T>&, constTU&); template <class T, class U> constexpr bool operator>=(constTU&, const optional<T>&);
Modify 22.5.6 [optional.relops] as indicated:
template <class T, class U> constexpr bool operator==(const optional<T>& x, const optional<TU>& y);[…]
template <class T, class U> constexpr bool operator!=(const optional<T>& x, const optional<TU>& y);[…]
template <class T, class U> constexpr bool operator<(const optional<T>& x, const optional<TU>& y);[…]
template <class T, class U> constexpr bool operator>(const optional<T>& x, const optional<TU>& y);[…]
template <class T, class U> constexpr bool operator<=(const optional<T>& x, const optional<TU>& y);[…]
template <class T, class U> constexpr bool operator>=(const optional<T>& x, const optional<TU>& y);[…]
Modify [optional.comp_with_t] as indicated:
template <class T, class U> constexpr bool operator==(const optional<T>& x, constTU& v);-?- Requires: The expression
-1- Effects: Equivalent to:*x == v
shall be well-formed and its result shall be convertible tobool
. [Note:T
need not beEqualityComparable
. — end note]return bool(x) ? *x == v : false;
template <class T, class U> constexpr bool operator==(constTU& v, const optional<T>& x);-?- Requires: The expression
-2- Effects: Equivalent to:v == *x
shall be well-formed and its result shall be convertible tobool
.return bool(x) ? v == *x : false;
template <class T, class U> constexpr bool operator!=(const optional<T>& x, constTU& v);-?- Requires: The expression
-3- Effects: Equivalent to:*x != v
shall be well-formed and its result shall be convertible tobool
.return bool(x) ? *x != v : true;
template <class T, class U> constexpr bool operator!=(constTU& v, const optional<T>& x);-?- Requires: The expression
-4- Effects: Equivalent to:v != *x
shall be well-formed and its result shall be convertible tobool
.return bool(x) ? v != *x : true;
template <class T, class U> constexpr bool operator<(const optional<T>& x, constTU& v);-?- Requires: The expression
-5- Effects: Equivalent to:*x < v
shall be well-formed and its result shall be convertible tobool
.return bool(x) ? *x < v : true;
template <class T, class U> constexpr bool operator<(constTU& v, const optional<T>& x);-?- Requires: The expression
-6- Effects: Equivalent to:v < *x
shall be well-formed and its result shall be convertible tobool
.return bool(x) ? v < *x : false;
template <class T, class U> constexpr bool operator<=(const optional<T>& x, constTU& v);-?- Requires: The expression
-7- Effects: Equivalent to:*x <= v
shall be well-formed and its result shall be convertible tobool
.return bool(x) ? *x <= v : true;
template <class T, class U> constexpr bool operator<=(constTU& v, const optional<T>& x);-?- Requires: The expression
-8- Effects: Equivalent to:v <= *x
shall be well-formed and its result shall be convertible tobool
.return bool(x) ? v <= *x : false;
template <class T, class U> constexpr bool operator>(const optional<T>& x, constTU& v);-?- Requires: The expression
-9- Effects: Equivalent to:*x > v
shall be well-formed and its result shall be convertible tobool
.return bool(x) ? *x > v : false;
template <class T, class U> constexpr bool operator>(constTU& v, const optional<T>& x);-?- Requires: The expression
-10- Effects: Equivalent to:v > *x
shall be well-formed and its result shall be convertible tobool
.return bool(x) ? v > *x : true;
template <class T, class U> constexpr bool operator>=(const optional<T>& x, constTU& v);-?- Requires: The expression
-11- Effects: Equivalent to:*x >= v
shall be well-formed and its result shall be convertible tobool
.return bool(x) ? *x >= v : false;
template <class T, class U> constexpr bool operator>=(constTU& v, const optional<T>& x);-?- Requires: The expression
-12- Effects: Equivalent to:v >= *x
shall be well-formed and its result shall be convertible tobool
.return bool(x) ? v >= *x : true;