Date: Mon, 24 Jun 2019 10:37:32 -0500
On Mon, Jun 24, 2019 at 10:26 AM Bjorn Reese via Std-Discussion <
std-discussion_at_[hidden]> 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
> Std-Discussion_at_[hidden]
> http://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>
Further down in the quoted section of the proposal
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3672.html#rationale.relops>,
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.
std-discussion_at_[hidden]> 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
> Std-Discussion_at_[hidden]
> http://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
>
Further down in the quoted section of the proposal
<http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3672.html#rationale.relops>,
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*
Received on 2019-06-24 10:39:35