Why is this not a warning?

Dominikus Dittes Scherkl via Digitalmars-d digitalmars-d at puremagic.com
Thu Mar 17 02:59:41 PDT 2016


On Thursday, 17 March 2016 at 09:13:34 UTC, tsbockman wrote:
> On Thursday, 17 March 2016 at 06:55:34 UTC, Shachar Shemesh 
> wrote:
>> On 16/03/16 23:50, tsbockman wrote:
>>> On Wednesday, 16 March 2016 at 16:40:49 UTC, Shachar Shemesh 
>>> wrote:
>>>> ...
>>>>
>>>> People who are marginally familiar with integer promotion 
>>>> will not be
>>>> surprised to know that the program prints "256". What is 
>>>> surprising to
>>>> me is that this produced neither error nor warning.
>>>>
>>>> The comparable program in C++, when compiled with gcc, 
>>>> correctly warns
>>>> about signed/unsigned comparison (though, to be fair, it 
>>>> seems that
>>>> clang doesn't).
>>>
>>> While this particular issue can and should be addressed in 
>>> the compiler
>>> (see my other reply), in the mean time how about trying out my
>>> `checkedint` DUB package?
>>
>> I'm afraid that paying run-time cost to verify correctness is 
>> out of the question for the type of product weka is building.
>
> You could use the `DebugInt` wrapper. It aliases to `SafeInt` 
> in debug and unittest mode, to find problems (many, including 
> the specific one in this thread, are detected at compile time). 
> Then, in release mode, it aliases to the built-in types for 
> maximum speed.
>
> Also, for almost all real world programs only a small 
> percentage of the code actually affects performance much. Using 
> `SafeInt` or `SmartInt`*everywhere* in a release build will 
> reduce performance by about 30% - but using it *almost* 
> everywhere, except in the program's hot spots, shouldn't 
> measurably reduce performance at all.

Or you can use an improved opCmp implementation in the compiler, 
that only add additional runtime cost, if someone is stupid 
enough to compare signed with unsigned values - but yield the 
correct result:

int opCmp(T)(const(T) a, const(T) b) pure @safe @nogc nothrow 
if(isNumeric!T)
{
    // Should be buildin. Naïve 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.
/// For comparison with floating point values the buildin
/// operations have no problem, so we don't handle them here.
int opCmp(T, U)(const(T) a, const(U) b) pure @safe @nogc nothrow
    if(isIntegral!T && isIntegral!U && !is(Unqual!T == Unqual!U))
{
    alias C = CommonType!(T, U);
    static if(isSigned!T && isUnsigned!U && T.sizeof <= U.sizeof)
       return (a < 0) ? -1 : opCmp(cast(U)a, b);
    else static if(isUnsigned!T && isSigned!U && T.sizeof >= 
U.sizeof)
       return (b < 0) ? 1 : opCmp(a, cast(T)b);
    else return opCmp(cast(C)a, cast(C)b);
}

unittest
{
    byte  a = -2;
    short c = -2;
    int   e = -2;
    long  g = -2;
    ubyte  b = 4;
    ushort d = 4;
    uint   f = 4;
    ulong  h = 4;
    assert(opCmp(a, b) < 0);
    assert(opCmp(c, d) < 0);
    assert(opCmp(e, f) < 0);
    assert(opCmp(g, h) < 0);
    assert(opCmp(a, h) < 0);
    assert(opCmp(b, g) > 0);
    assert(opCmp(d, e) > 0);
    // compiler test:
    assert(a < b);
    assert(c < d);
    assert(e < f); // fails
    assert(g < h); // fails
    assert(a < h); // fails
    assert(b > g);
    assert(d > e);
}



More information about the Digitalmars-d mailing list