C++ Logo

std-proposals

Advanced search

Re: nullptr_t and nullopt_t should both have operator<=> and operator== to enable the *_with concepts

From: Barry Revzin <barry.revzin_at_[hidden]>
Date: Fri, 9 Jul 2021 16:11:24 -0500
On Fri, Jul 9, 2021 at 2:04 PM Ville Voutilainen via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On Fri, 9 Jul 2021 at 21:51, Nevin Liber via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
> > That same argument applies to comparing two nullptr_t objects, and yet
> we can equality compare them.
>
> Alright. So nullptr_it has equality, but no ordering, and this
> proposal gives it ordering. It's a funny ordering tho,
> since the ordering just tells us that all nullptr_t objects are equal.
> I'm not sure I see the use of that. Same goes
> for ordering nullopt objects.
>

First, We do actually have a singular type in the standard library that has
this kind of ordering: std::monostate. It might be facially weird but it's
also pretty sensible.

Second, std::nullopt_t isn't just a tag type. It largely behaves as an
instance of optional<T>, for all T. It's not exactly that, because C++
doesn't work that way (as opposed to in Rust where None actually *is* an
instance of Option<T>, for whichever T), but it's close enough. In that
sense, comparing nullopt_t to nullopt_t makes as much sense as comparing
any other optional<T> to any other optional<T> (and arguably more sense
than comparing an optional<T> to either a T or an optional<U>).

Third, std::nullptr_t actually did used to have relational operators
defined on it. There were two Core Issues (583 and 1512, neither of which
mention nullptr), which were resolved by N3478 - but that paper also
removed relational comparisons between two nullptrs. What makes this case
interesting is that the motivation here was to make "p > nullptr"
ill-formed - this isn't the same kind of issue that we have in optional,
where "o > nullopt" is fine (if... weird), so while the nullopt comparisons
do make things more uniform, since optional<T>(nullopt) == nullopt works so
why not just nullopt == nullopt, here we'd be in a case where "nullptr >
nullptr" works but not "(T*)nullptr > nullptr". So I don't know how I feel
about this case, but regardless of my personal feelings, given that we *did*
have this functionality and it was *explicitly removed*, the paper
definitely needs to go into the history of *why* it was removed and thus
why we want to add it back. I've CCed Jens, who wrote N3478.

Barry

Received on 2021-07-09 16:11:39