[Issue 259] Comparing signed to unsigned does not generate an error

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Fri Apr 17 01:49:01 PDT 2015


https://issues.dlang.org/show_bug.cgi?id=259

Dominikus Dittes Scherkl <dominikus at scherkl.de> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |dominikus at scherkl.de

--- Comment #58 from Dominikus Dittes Scherkl <dominikus at scherkl.de> ---
The problem is still there, and the behaviour is completely inconsistent, so
braking any code isn't a problem I think because I cannot imagine that anybody
really relies on the strange behaviour:

unittest
{
    byte   a = -3;
    ubyte  b =  2;
    short  c = -3;
    ushort d =  2;
    int    e = -3;
    uint   f =  2;
    long   g = -3;
    ulong  h =  2;

    assert(a < b);
    assert(c < d);
    assert(e < f); // fails!!
    assert(g < h); // fails!!
    assert(a < h); // fails!!
    assert(b > g);
    assert(d > e);
}

So why don't we change to something that simply always works?

int opCmp(T, U)(const(T) a, const(U) b) pure @safe @nogc nothrow
   if(is(Unqual!T == Unqual!U) || isFloatingPoint!T || isFloatingPoint!U)
{
   // Should be buildin. Naive implementation:
   return a <= b ? a != b ? -1 : 0 : 1;
}

/// Returns negative value if a < b, 0 if they are equal or positive value if a
> b.
/// This will always yield a correct result, no matter which integral types are
compared.
/// It uses one extra comparison operation if and only if
/// one type is signed and the other unsigned but has bigger max.
int opCmp(T, U)(const(T) a, const(U) b) pure @safe @nogc nothrow
   if(isIntegral!T && isIntegral!U && !is(Unqual!T == Unqual!U))
{
   static if(T.sizeof == U.sizeof) alias C = Unsigned!T;
   else alias C = CommonType!(T, U); // this will be the larger type

   static if(isSigned!T && isUnsigned!U && T.sizeof <= U.sizeof)
   {
      return (a < 0) ? -1 : opCmp(cast(Unsigned!C)a, cast(C)b);
   }
   else static if(isUnsigned!T && isSigned!U && T.sizeof >= U.sizeof)
   {
      return (b < 0) ? 1 : opCmp(cast(C)a, cast(Unsigned!C)b);
   }
   else
   {
      // both signed or both unsigned or the unsigned type is smaller
      // and can therefore be safely cast to the signed type
      return opCmp(cast(C)a, cast(C)b);
   }
}

--


More information about the Digitalmars-d-bugs mailing list