On Thursday, 17 March 2016 at 09:59:41 UTC, Dominikus Dittes Scherkl wrote:
Or you can use an improved opCmp implementation in the compiler, that only add additional runtime cost, [...]

The compiler could statically fix two cases, ALWAYS without runtime cost. I think that FPC does this: operand widening by promoting the unsigned operand to a signed one of a wider type, POC with a template:

import std.traits;

bool safeIntegralCmp(string op, L, R)(auto ref L lhs, auto ref R rhs)
if (isIntegral!R && isIntegral!L)
{
    // safe
    static if (is(Unqual!L == Unqual!R))
    {
        mixin("return lhs" ~ op ~ "rhs;");
    }
    else
    {
        // promote unsigned to bigger signed
        static if (isSigned!L && R.sizeof < 8)
        {
            long widenedRhs = rhs;
            mixin("return lhs" ~ op ~ "widenedRhs;");
        }
        else static if (isSigned!R && L.sizeof < 8)
        {
            long widenedLhs = lhs;
            mixin("return widened" ~ op ~ "rhs;");
        }
        // not fixable by operand widening
        else
        {
pragma(msg, "warning, comparing a" ~ L.stringof ~ " with a" ~ R.stringof
                ~ " may result into wrong results");
            mixin("return lhs" ~ op ~ "rhs;");
        }
    }
}

unittest
{
    int a = -1; uint b;
    assert(a > b); // wrong result
assert(safeIntegralCmp!">"(a,b) == false); // fixed by promotion

    long aa = -1; ulong bb;
    assert(aa > bb); // wrong result
assert(safeIntegralCmp!">"(aa,bb) == true); // not staticaly fixable, warning
}

The case where an implicit widening is done a warning could also be emitted (operand bla bla widened).



Reply via email to