On opCmp

anonymous via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Fri Feb 27 05:44:58 PST 2015


On Friday, 27 February 2015 at 11:04:51 UTC, Nordlöw wrote:
> Is there a more compact way to describe the opCmp function in 
> the following struct
>
> struct Hit
> {
>     size_t count; // number of walkers that found this node
>     NWeight rank; // rank (either minimum distance or maximum 
> strength)
>
>     auto opCmp(const Hit rhs) const
>     {
>         if      (this.count < rhs.count)
>         {
>             return -1;
>         }
>         else if (this.count > rhs.count)
>         {
>             return +1;
>         }
>         else
>         {
>             if      (this.rank < rhs.rank)
>             {
>                 return -1;
>             }
>             else if (this.rank > rhs.rank)
>             {
>                 return +1;
>             }
>             else
>             {
>                 return 0;
>             }
>         }
>     }
> }
>
> by reusing something like
>
>     auto opCmp(const Hit rhs) const
>     {
>         if      (this.count < rhs.count)
>         {
>             return -1;
>         }
>         else if (this.count > rhs.count)
>         {
>             return +1;
>         }
>         else
>         {
>             return this.rank.standardOpCmp(rhs.rank)
>         }
>     }

Two things come to mind:

A) std.algorithm.cmp

----
auto opCmp(const Hit rhs) const
{
     import std.algorithm: cmp;
     import std.range: only;
     if(auto c = cmp(only(count), only(rhs.count)))
     {
         return c;
     }
     else /* 'count' values are equal. */
     {
         return cmp(only(rank), only(rhs.rank));
     }
}
----

Maybe there should be a std.algorithm.cmp for non-ranges, too, so 
that `only` wouldn't be needed here.

B) std.typecons.Tuple has an opCmp that compares all fields in 
order.

----
auto opCmp(const Hit rhs) const
{
     import std.typecons: tuple;
     return tuple(count, rank).opCmp(tuple(rhs.count, rhs.rank));
}
----

This exact behaviour is not documented, though. So I guess it 
should not be relied on. Maybe the documentation should be more 
specific. In the meantime, you could duplicate the functionality 
in a function of your own:

----
import std.typecons: Tuple;

/** Put a proper, specific description here.
*/
int cmpTuples(Types ...)(Tuple!Types a, Tuple!Types b)
{
     // copied from std.typecons.Tuple.opCmp
     foreach (i, Unused; Types)
     {
         if (a[i] != b[i])
         {
             return a[i] < b[i] ? -1 : 1;
         }
     }
     return 0;
}

struct Hit
{
     size_t count;
     NWeight rank;

     auto opCmp(const Hit rhs) const
     {
         import std.typecons: tuple;
         return cmpTuples(tuple(count, rank), tuple(rhs.count, 
rhs.rank));
     }
}
----



More information about the Digitalmars-d-learn mailing list