// Mixing standard signed and unsigned types is dangerous, but... int ba = -1; uint bb = 0; assert(ba > bb); auto bc = ba + bb; assert(is(typeof(bc) == uint)); assert(bc == 4294967295u); // ...with SmartInt, mixed signed/unsigned operations "just work": import checkedint.throws : SmartInt; // use IntFlagPolicy.throws SmartInt!int ma = -1; SmartInt!uint mb = 0; assert(ma < mb); auto mc = ma + mb; assert(is(typeof(mc) == SmartInt!int)); assert(mc != 4294967295u); assert(mc == -1);
// When IntFlagPolicy.throws is used, failed SmartInt operations will throw a CheckedIntException. import checkedint.throws : SmartInt; SmartInt!uint ma = 1; SmartInt!uint mb = 0; bool overflow = false; try { SmartInt!uint mc = mb - ma; assert(false); } catch (CheckedIntException e) { assert(e.intFlags == IntFlag.negOver); overflow = true; } assert(overflow); bool div0 = false; try { // With standard integers, this would crash the program with an unrecoverable FPE... SmartInt!uint mc = ma / mb; assert(false); } catch (CheckedIntException e) { // ...but with SmartInt, it just throws a normal Exception. assert(e.intFlags == IntFlag.div0); div0 = true; } assert(div0);
// When IntFlagPolicy.sticky is used, failed SmartInt operations set one or more bits in IntFlags.local. import checkedint.sticky : SmartInt; SmartInt!uint ma = 1; SmartInt!uint mb = 0; SmartInt!uint mc; mc = mb - ma; assert(IntFlags.local == IntFlag.over); // With standard integers, this would crash the program with an unrecoverable FPE... mc = ma / mb; // ...but with SmartInt, it just sets a bit in IntFlags.local. assert(IntFlags.local & IntFlag.div0); // Each flag will remain set until cleared: assert(IntFlags.local.clear() == (IntFlag.over | IntFlag.div0)); assert(!IntFlags.local);
Wrapper for any basic integral type N that uses the checked operations from smartOp and bounds checks assignments with checkedint.to().