On Wed, 26 Nov 2008 18:24:17 +0300, Andrei Alexandrescu
<[EMAIL PROTECTED]> wrote:
Also consider:
auto delta = a1.length - a2.length;
What should the type of delta be? Well, it depends. In my scheme that
wouldn't even compile, which I think is a good thing; you must decide
whether prior information makes it an unsigned or a signed integral.
Sure, it shouldn't compile. But explicit casting to either type won't
help. Let's say you expect that a1.length > a2.length and thus expect a
strictly positive result. Putting an explicit cast will not detect (but
suppress) an error and give you an erroneous result silently.
Putting an assert(a1.length > a2.length) might help, but the check will be
unavailable unless code is compiled with asserts enabled.
A better solution would be to write code as follows:
auto delta = unsigned(a1.length - a2.length); // returns an unsigned
value, throws on overflow (i.e., "2 - 4")
auto delta = signed(a1.length - a2.length); // returns result as a signed
value. Throws on overflow (i.e., "int.min - 1")
auto delta = a1.length - a2.length; // won't compile
// this one is also handy:
auto newLength = checked(a1.length - 1); // preserves type of a1.length,
be it int or uint, throws on overflow
I have previously shown an implementation of unsigned/signed:
import std.stdio;
int signed(lazy int dg)
{
auto result = dg();
asm {
jo overflow;
}
return result;
overflow:
throw new Exception("Integer overflow occured");
}
int main()
{
int t = int.max;
try
{
int s = signed(t + 1);
writefln("Result is %d", s);
}
catch(Exception e)
{
writefln("Whoops! %s", e.toString());
}
return 0;
}
But Andrei has correctly pointed out that it has a problem - it may throw
without a reason:
int i = int.max + 1; // sets an overflow flag
auto result = expectSigned(1); // raises an exception
Overflow flag may also be cleared in a complex expression:
auto result = expectUnsigned(1 + (uint.max + 1)); // first add will
overflow and second one clears the flag -> no exception as a result
A possible solution is to make the compiler aware of this construct and
disallow passing none (case 2) or more that one operation (case 1) to the
method.