C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Let spaceship return an int

From: Chris Gary <cgary512_at_[hidden]>
Date: Sun, 24 Sep 2023 15:39:20 -0600
>
> Oh, so what you're saying is that basically every single argument you
> made in this thread thus far was a subterfuge. All that talk about
> `int` being "easier to use," or "It must be possible to effectively
> use the language without the library" and so forth was just a
> smokescreen.
>

`int` *is *easier to work with. There was no smokescreen. What happened:
Architecture astronomy.

What I thought was implied: Any value *not* in the set {-1,0,1} is
undefined for an int compare. Sign of difference. All things are integers.
Map into the larger set before comparing elements. Heterogeneous
comparisons are otherwise meaningless. NaN <=> NaN -> Undefined -->
Undefined is NaN for a ternary, so we still have false for all relational
operators.

There is a branch-free way to test for set containment, any compiler can
implement the implied rules without any more overhead than the existing
solution, and doing away with another need for an import or an #include is
always a good thing.

I feel as though I'm having to spell out my position over and over again,
so its a bit aggravating.


On Sun, Sep 24, 2023 at 3:22 PM Jason McKesson via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On Sun, Sep 24, 2023 at 4:57 PM Chris Gary via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
> >
> >
> >> What does that mean for NaN <=> 1.0 ?
> >
> >
> > NaN <op> NaN is false for <op> : (arg,arg) -> bool
> > NaN <=> NaN -> -2
> > ..which could be reserved for a ternary, meaning "undefined". Or, any
> value not, -1, 0, 1.
>
> That's not a reasonable answer. People almost never check such integer
> values for exact equivalence with -1 or 1. It's always a comparison
> with zero. Indeed, famous 3-way comparison functions like `strlen`
> *explicitly* do not return exactly -1 or 1; they only return values
> which compare less than, equal to, or greater than 0.
>
> So `NaN <=> NaN` returning -2 should also mean that `NaN < NaN ==
> true`. Which it doesn't.
>
> > I proposed int as to avoid exactly what happened in this thread anyway.
> > So, in better disclosure, I've had success in the past with a "rich"
> enum ternary type made for an override of a "Compare" function.
> >
> > Here's a snippet:
> >
> > `
> > enum class Relation : int
> > {
> > Undefined = -2,
> > Less = -1,
> > Equal = 0,
> > Greater = 1
> > };
> >
> > inline constexpr Relation ClampToValid( Relation r ) noexcept
> > {
> > const auto u = (int)r + 1;
> > const auto v = 2 - u;
> > const auto w = u | ((u|v) >> (bitCount<int>-1));
> > return (Relation)( w - 1 );
> > }
> >
> > // Relational operators that take "Relation" etc...
> > `
> > Now, if <=> could just return `int` or anything that can round-trip to
> an `int` implicitly, and enum classes could expose implicit conversions,
> this could all be safely encapsulated without creating incorrect code that
> tries to compare a `Relation` value and not getting the magic `undefined`
> result - everything would get mapped into to the set {-2,-1,0,1} before
> comparison. The "sign of difference" rule still applies everywhere, and
> comparisons are allowed to return any other random value to mean
> "undefined". In cases where the meaning of the return value means more than
> just "undefined", and the code still assumes the semantics of "Relation",
> it wasn't written to deal with the failure anyway (generally, just capture
> the original int and propagate an error/throw an exception).
>
> Oh, so what you're saying is that basically every single argument you
> made in this thread thus far was a subterfuge. All that talk about
> `int` being "easier to use," or "It must be possible to effectively
> use the language without the library" and so forth was just a
> smokescreen.
>
> Being able to make the spaceship operator do the above is what you
> really wanted.
>
> To which I say that the above code is a very good example of why we
> *should not* use integers. Why? Because of what I said at first.
>
> `strong_ordering` and the rest of those types are explicitly *not*
> convertible from integers. Given an object of an ordering type, the
> only things you can test it against are other ordering values or a
> zero-equivalent value. Not only does this make 3-way comparison
> consistent (you can only compare the result against zero), it prevents
> exactly the NaN issue above. If a comparison returns
> `partial_ordering::unordered`, comparing it against 0 will always be
> false.
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2023-09-24 21:39:31