On Mon, Jun 24, 2019 at 10:26 AM Bjorn Reese via Std-Discussion <std-discussion@lists.isocpp.org> wrote:
On 6/24/19 3:59 PM, Johan Williamsson via Std-Discussion wrote:

> What's the rationale behind the decision to allow comparisons between
> values and optional values without at least throwing an exception if the
> optional value is not assigned?

Quoting N3672, section "Relational operators":

  "One of the design goals of optional is that objects of type
   optional<T> should be valid elements in STL containers and usable with
   STL algorithms (at least if objects of type T are). Equality
   comparison is essential for optional<T> to model concept Regular. C++
   does not have concepts, but being regular is still essential for the
   type to be effectively used with STL. Ordering is essential if we want
   to store optional values in ordered associative containers. A number
   of ways of including the disengaged state in comparisons have been
   suggested. The ones proposed, have been crafted such that the axioms
   of equivalence and strict weak ordering are preserved: disengaged
   optional<T> is simply treated as an additional and unique value of T
   equal only to itself; this value is always compared as less than any
   value of T"
Std-Discussion mailing list

Further down in the quoted section of the proposal, the mixed comparison operators are discussed explicitly:

The mixed relational operators, especially these representing order, between optional<T> and T have been accused of being dangerous. In code examples like the following, it may be unclear if the author did not really intend to compare two T's.
auto count = get_optional_count();
if (count < 20) {} // or did you mean: *count < 20 ?
if (count == nullopt || *count < 20) {} // verbose, but unambiguous
Given that optional<T> is comparable and implicitly constructible from T, the mixed comparison is there already. We would have to artificially create the mixed overloads only for them to cause controlled compilation errors. A consistent approach to prohibiting mixed relational operators would be to also prohibit the convesion from T or to also prohibit homogenous relational operators for optional<T>; we do not want to do either, for other reasons discussed in this proposal. Also, mixed relational operations are available in Boost.Optional and were found useful by the users. Mixed operators come as something natural when we consider the model "T with one additional value".

The authors do not seem to have considered the possibility of having the mixed comparison operators throw an exception upon encountering a disengaged optional, but they did consider the possibility of having them simply cause a compilation error. We don't know why, but it seems to me that, if you really believe that this usage is almost always a bug, then you should want that bug to be caught at compile time. But it doesn't appear that the authors shared your view that it's almost always a bug. Instead, they claimed that some users of Boost.Optional found the mixed comparison operators useful.

Brian Bi