ProtoObject and comparison for equality and ordering

H. S. Teoh hsteoh at quickfur.ath.cx
Wed May 15 16:36:27 UTC 2019


On Tue, May 14, 2019 at 08:32:32PM -0400, Andrei Alexandrescu via Digitalmars-d wrote:
[...]
> ---
> import std.stdio;
> 
> struct OverengineeredCmpResult {
>     enum R { lt, eq, gt, ionno }
>     private R payload;
>     int opCmp(int alwaysZero) {
>         writeln("b");
>         return 0;
>     }
> }
> 
> struct A {
>     OverengineeredCmpResult opCmp(A rhs) {
>         writeln("a");
>         return OverengineeredCmpResult(OverengineeredCmpResult.R.ionno);
>     }
> }
> 
> void main() {
>     A a, b;
>     if (a < b) {}
> }
> ---
[...]

FYI, even with the above amusingly elaborate hack, you still cannot
achieve proper 4-way comparison results.  Consider: what should
OverengineeredCmpResult.opCmp return for payload == ionno, such that <,
<=, >, >=, ==, != would all produce the correct result?

Answer: it's not possible unless you return float, because x < y
translates to x.opCmp(y) < 0, and x > y translates to x.opCmp(y) > 0, so
the only way to represent an incomparable state is for opCmp to return
some value z for which z < 0 and z > 0 are *both* false.  There is no
integer value that fits this description; the only candidate is
float.nan. Substituting the return value of opCmp with a custom struct
doesn't fix this problem; it only defers it to the custom struct's
opCmp, which suffers from the same problem.

tl;dr: it's currently *not possible* to represent an incomparable state
in opCmp with anything other than float.nan (or double.nan, etc.). No
amount of hackery with opCmp returning custom structs is going to fix
this without using float.nan at *some* point.


T

-- 
There's light at the end of the tunnel. It's the oncoming train.


More information about the Digitalmars-d mailing list