WAT: opCmp and opEquals woes

Jonathan M Davis via Digitalmars-d digitalmars-d at puremagic.com
Wed Jul 23 17:31:54 PDT 2014


On Wednesday, 23 July 2014 at 16:47:40 UTC, H. S. Teoh via 
Digitalmars-d wrote:
> This morning, I discovered this major WAT in D:
>
> ----
> struct S {
>         int x;
>         int y;
>         int opCmp(S s) {
>                 return x - s.x; // compare only x
>         }
> }
>
> void main() {
>         auto s1 = S(1,2);
>         auto s2 = S(1,3);
>         auto s3 = S(2,1);
>
>         assert(s1 < s3); // OK
>         assert(s2 < s3); // OK
>         assert(s3 > s1); // OK
>         assert(s3 > s2); // OK
>         assert(s1 <= s2 && s2 >= s1); // OK
>         assert(s1 == s2); // FAIL -- WAT??
> }
> ----
>
> The reason for this is that the <, <=, >=, > operators are 
> defined in
> terms of opCmp (which, btw, is defined to return 0 when the 
> objects
> being compared are equal), but == is defined in terms of 
> opEquals. When
> opEquals is not defined, it defaults to the built-in compiler
> definition, which is a membership equality test, even if opCmp 
> *is*
> defined, and returns 0 when the objects are equal.
>
> Why isn't "a==b" rewritten as "a.opCmp(b)==0"?? I'm pretty sure 
> TDPL
> says this is the case (unfortunately I'm at work so I can't 
> check my
> copy of TDPL).
>
> https://issues.dlang.org/show_bug.cgi?id=13179
>
> :-(

I would argue that the compiler should still be generating 
opEquals even if opCmp is defined. Otherwise, even if opCmp is 
consistent with the built-in opEquals, you'll be forced to 
reimplement opEquals - and toHash if you're using that type as a 
key, since once you define opEquals, you have to define toHash.

If it makes sense for a type to define opCmp but not define 
opEquals (which I seriously question), then I think that it 
should be explicit, in which case, we can use @disable, e.g. 
something like

struct S
{
     @disable bool opEquals(ref S s);

     int opCmp(ref S S)
     {
         ...
     }

     ...
}

- Jonathan M Davis


More information about the Digitalmars-d mailing list