Module std.checkedint
This module defines facilities for efficient checking of integral operations
against overflow, casting with loss of precision, unexpected change of sign,
etc. The checking (and possibly correction) can be done at operation level, for
example opChecked!"+"(x, y, overflow) adds two integrals x and
y and sets overflow to true if an overflow occurred. The flag overflow
(a bool passed by reference) is not touched if the operation succeeded, so the
same flag can be reused for a sequence of operations and tested at the end.
Issuing individual checked operations is flexible and efficient but often
tedious. The Checked facility offers encapsulated integral wrappers that
do all checking internally and have configurable behavior upon erroneous
results. For example, Checked!int is a type that behaves like int but aborts
execution immediately whenever involved in an operation that produces the
arithmetically wrong result. The accompanying convenience function checked uses type deduction to convert a value x of integral type T to
Checked!T by means of checked(x). For example:
void main()
{
    import stdSimilarly, checked(-1) > uint(0) aborts execution (even though the built-in
comparison int(-1) > uint(0) is surprisingly true due to language's
conversion rules modeled after C). Thus, Checked!int is a virtually drop-in
replacement for int useable in debug builds, to be replaced by int in
release mode if efficiency demands it.
Checked  has customizable behavior with the help of a second type parameter,
Hook. Depending on what methods Hook defines, core operations on the
underlying integral may be verified for overflow or completely redefined. If
Hook defines no method at all and carries no state, there is no change in
behavior, i.e. Checked!(int, void) is a wrapper around int that adds no
customization at all.
This module provides a few predefined hooks (below) that add useful behavior to
Checked:
| Abort | fails every incorrect operation with a message to         stderrfollowed by a call toassert(0). It is the default
        second parameter, i.e.Checked!shortis the same asChecked!(short, Abort). | 
| Throw | fails every incorrect operation by throwing an exception. | 
| Warn | prints incorrect operations to stderrbut otherwise preserves the built-in behavior. | 
| ProperCompare | fixes the comparison operators ==,!=,<,<=,>, and>=to return correct results in all circumstances,
        at a slight cost in efficiency. For example,Checked!(uint, ProperCompare)(1) > -1istrue,
        which is not the case for the built-in comparison. Also, comparing
        numbers for equality with floating-point numbers only passes if the
        integral can be converted to the floating-point number precisely,
        so as to preserve transitivity of equality. | 
| WithNaN | reserves a special "Not a Number" (NaN) value akin to the homonym value
        reserved for floating-point values. Once a Checked!(X, WithNaN)gets this special value, it preserves and propagates it until
        reassigned.isNaNcan be used to query whether the object
        is not a number. | 
| Saturate | implements saturating arithmetic, i.e. Checked!(int, Saturate)"stops" atintfor all operations that would cause anintto
        overflow toward infinity, and atintfor all operations that would
        correspondingly overflow toward negative infinity. | 
These policies may be used alone, e.g. Checked!(uint, WithNaN) defines a
uint-like type that reaches a stable NaN state for all erroneous operations.
They may also be "stacked" on top of each other, owing to the property that a
checked integral emulates an actual integral, which means another checked
integral can be built on top of it. Some combinations of interest include:
| Checked!(Checked!int, ProperCompare) | 
| defines an intwith fixed
comparison operators that will fail withassert(0)upon overflow. (Recall thatAbortis the default policy.) The order in which policies are combined is
important because the outermost policy (ProperComparein this case) has the
first crack at intercepting an operator. The converse combinationChecked!(Checked!(int, ProperCompare))is meaningless becauseAbortwill
intercept comparison and will fail without givingProperComparea chance to
intervene. | 
| Checked!(Checked!(int, ProperCompare), WithNaN) | 
| defines an int-like
type that supports a NaN value. For values that are not NaN, comparison works
properly. Again the composition order is important;Checked!(Checked!(int,
WithNaN), ProperCompare)does not have good semantics becauseProperCompareintercepts comparisons before the numbers involved are tested for NaN. | 
The hook's members are looked up statically in a Design by Introspection manner
and are all optional. The table below illustrates the members that a hook type
may define and their influence over the behavior of the Checked type using it.
In the table, hook is an alias for Hook if the type Hook does not
introduce any state, or an object of type Hook otherwise.
| Hookmember | Semantics in Checked!(T, Hook) | 
|---|---|
| defaultValue | If defined, Hookis used as the
default initializer of the payload. | 
| min | If defined, Hookis used as the minimum value of
the payload. | 
| max | If defined, Hookis used as the maximum value of
the payload. | 
| hookOpCast | If defined, hookis forwarded
to unconditionally when the payload is to be cast to typeU. | 
| onBadCast | If defined and hookOpCastis not defined,onBadCast!U(get)is forwarded to when the payload is to be cast to typeUand the cast would lose information or force a change of sign. | 
| hookOpEquals | If defined, hookis
forwarded to unconditionally when the payload is compared for equality against
valuerhsof integral, floating point, or Boolean type. | 
| hookOpCmp | If defined, hookis
forwarded to unconditionally when the payload is compared for ordering against
valuerhsof integral, floating point, or Boolean type. | 
| hookOpUnary | If defined, hook(whereopis the operator symbol) is forwarded to for unary operators-and~. In
addition, for unary operators++and--,hookis
called, wherepayloadis a reference to the value wrapped byCheckedso the
hook can change it. | 
| hookOpBinary | If defined, hook(whereopis the operator symbol andrhsis the right-hand side operand) is
forwarded to unconditionally for binary operators+,-,*,/,%,^^,&,|,^,<<,>>, and>>>. | 
| hookOpBinaryRight | If defined, hook(whereopis the operator symbol andlhsis the left-hand side operand) is forwarded to unconditionally for binary
operators+,-,*,/,%,^^,&,|,^,<<,>>, and>>>. | 
| onOverflow | If defined, hookis forwarded
to for unary operators that overflow but only ifhookOpUnaryis not defined.
Unary~does not overflow; unary-overflows only when the most negative
value of a signed type is negated, and the result of the hook call is returned.
When the increment or decrement operators overflow, the payload is assigned the
result ofhook. When a binary operator overflows, the
result ofhookis returned, but only ifHookdoes
not definehookOpBinary. | 
| hookOpOpAssign | If defined, hook(whereopis the operator symbol andrhsis the right-hand side
operand) is forwarded to unconditionally for binary operators+=,-=,*=,/=,%=,^^=,&=,|=,^=,<<=,>>=, and>>>=. | 
| onLowerBound | If defined, hook(wherevalueis the value being assigned) is forwarded to when the result of
binary operators+=,-=,*=,/=,%=,^^=,&=,|=,^=,<<=,>>=,
and>>>=is smaller than the smallest value representable byT. | 
| onUpperBound | If defined, hook(wherevalueis the value being assigned) is forwarded to when the result of
binary operators+=,-=,*=,/=,%=,^^=,&=,|=,^=,<<=,>>=,
and>>>=is larger than the largest value representable byT. | 
| hookToHash | If defined, hook(wherepayloadis a reference to the value wrapped by Checked) is forwarded
to whentoHashis called on a Checked type. Custom hashing can be implemented
in aHook, otherwise the built-in hashing is used. | 
Example
int[] concatAndAdd(int[] a, int[] b, int offset)
{
    // Aborts on overflow on size computation
    auto r = new int[(checked(aExample
Saturate stops at an overflow
auto x = (cast(byte) 127)Example
WithNaN has a special "Not a Number" (NaN) value akin to the homonym value reserved for floating-point values
auto x = 100Example
ProperCompare fixes the comparison operators ==, !=, <, <=, >, and >= to return correct results
uint x = 1;
auto y = xExample
Throw fails every incorrect operation by throwing an exception
import stdFunctions
| Name | Description | 
|---|---|
| 
									checked(value)
								 | Convenience function that turns an integral into the corresponding Checkedinstance by using template argument deduction. The hook type may be specified
(by defaultAbort). | 
| 
									isNaN(x)
								 | Queries whether a Checked!(T, WithNaN)object is not a number (NaN). | 
| 
									opChecked(lhs, rhs, overflow)
								 | Defines binary operations with overflow checking for any two integral types.
The result type obeys the language rules (even when they may be
counterintuitive), and overflowis set if an overflow occurs (including
inadvertent change of signedness, e.g.-1is converted touint).
Conceptually the behavior is: | 
Structs
| Name | Description | 
|---|---|
| 
									Abort
								 | Force all integral errors to fail by printing an error message to stderrand
then abort the program.Abortis the default second argument forChecked. | 
| 
									Checked
								 | Checked integral type wraps an integral Tand customizes its behavior with the
help of aHooktype. The type wrapped must be one of the predefined integrals
(unqualified), or another instance ofChecked. | 
| 
									ProperCompare
								 | Hook that provides arithmetically correct comparisons for equality and ordering.
Comparing an object of type Checked!(X, ProperCompare)against another
integral (for equality or ordering) ensures that no surprising conversions from
signed to unsigned integral occur before the comparison. UsingChecked!(X,
ProperCompare)on either side of a comparison for equality against a
floating-point number makes sure the integral can be properly converted to the
floating point type, thus making sure equality is transitive. | 
| 
									Saturate
								 | Hook that implements saturation, i.e. any arithmetic operation that would
overflow leaves the result at its extreme value ( minormaxdepending on the
direction of the overflow). | 
| 
									Throw
								 | Force all integral errors to fail by throwing an exception of type Throw. The message coming with the error is similar to the one
printed byWarn. | 
| 
									Warn
								 | Hook that prints to stderra trace of all integral errors, without affecting
default behavior. | 
| 
									WithNaN
								 | Hook that reserves a special value as a "Not a Number" representative. For
signed integrals, the reserved value is T. For signed integrals, the
reserved value isT. |