implementing default opCmp

Steven Schveighoffer schveiguy at gmail.com
Thu Nov 19 14:12:16 UTC 2020


On 11/18/20 6:02 PM, Paul Backus wrote:
> On Wednesday, 18 November 2020 at 22:29:17 UTC, Steven Schveighoffer wrote:
>> I have a struct like this:
>>
>> struct S
>> {
>>    int x;
>>    int y;
>> }
>>
>> and I want a default comparison. The problem is, that comparison 
>> doesn't have a default, and requires I implement opCmp. While this is 
>> useful for the compiler, there's no default I know of that is an easy 
>> one-liner.
> 
> Here's a stab at a totally generic version that I haven't unit tested at 
> all, except to verify that it works for your example struct S:
> 
> auto cmp(T, U)(auto ref T lhs, auto ref U rhs)
> {
>      import core.lifetime: forward;
> 
>      static if (__traits(compiles, lhs.opCmp(rhs)))
>          return forward!lhs.opCmp(forward!rhs);
>      else static if (__traits(compiles, rhs.opCmp(lhs)))
>          return -forward!rhs.opCmp(forward!lhs);
>      else
>          return lhs < rhs ? -1 : lhs > rhs ? 1 : 0;
> }
> 
> mixin template defaultOpCmp()
> {
>      import std.traits: isAggregateType;
> 
>      static assert(isAggregateType!(typeof(this)),
>          "opCmp can only be overloaded for aggregate types.");
> 
>      auto opCmp()(auto ref typeof(this) other)
>      {
>          import std.traits: ReturnType, CommonType, Fields;
>          import std.meta: Map = staticMap;
> 
>          alias cmpType(T) = ReturnType!((T lhs, T rhs) => cmp(lhs, rhs));
>          alias Result = CommonType!(Map!(cmpType, Fields!(typeof(this))));
> 
>          Result result;
> 
>          static foreach (i, _; typeof(this).tupleof)
>              if (result == 0)
>                  result = cmp(this.tupleof[i], other.tupleof[i]);
> 
>          return result;
>      }
> }

Yeah, something like this might be useful in druntime. But it makes you 
wonder if we wouldn't be better off without opCmp but instead with 
opBinary(string s : "<") and friends.

One thing that sucks is that opCmp might do more operations than are 
necessary for the actual comparison, because it has to generate the 
numeric result.

-Steve


More information about the Digitalmars-d-learn mailing list