| ## Safe Numerics

### Using safe_range and safe_literal

When trying to avoid arithmetic errors of the above type, programmers will select data types which are wide enough to hold values large enough to be certain that results won't overflow, but are not so large as to make the program needlessly inefficient. In the example below, we presume we know that the values we want to work with fall in the range [-24,82]. So we "know" the program will always result in a correct result. But since we trust no one, and since the program could change and the expressions be replaced with other ones, we'll still use the `loose_trap_policy` exception policy to verify at compile time that what we "know" to be true is in fact true.

    //  Copyright (c) 2018 Robert Ramey
    //
    // Distributed under the Boost Software License, Version 1.0. (See
    // accompanying file LICENSE_1_0.txt or copy at
    // http://www.boost.org/LICENSE_1_0.txt)

    #include <iostream>

    #include <boost/safe_numerics/safe_integer_range.hpp>
    #include <boost/safe_numerics/safe_integer_literal.hpp>
    #include <boost/safe_numerics/exception.hpp>
    #include <boost/safe_numerics/native.hpp>
    #include "safe_format.hpp" // prints out range and value of any type

    using namespace boost::safe_numerics;

    // create a type for holding small integers in a specific range
    using safe_t = safe_signed_range<
        -24,
        82,
        native,           // C++ type promotion rules work OK for this example
        loose_trap_policy // catch problems at compile time
    >;

    // create a type to hold one specific value
    template<int I>
    using const_safe_t = safe_signed_literal<I, native, loose_trap_policy>;

    // We "know" that C++ type promotion rules will work such that
    // addition will never overflow. If we change the program to break this,
    // the usage of the loose_trap_policy promotion policy will prevent compilation.
    int main(int, const char *[]){
        std::cout << "example 83:\n";

        constexpr const const_safe_t<10> x;
        std::cout << "x = " << safe_format(x) << std::endl;
        constexpr const const_safe_t<67> y;
        std::cout << "y = " << safe_format(y) << std::endl;
        auto zx = x + y;
        const safe_t z = zx;
        //auto z = x + y;
        std::cout << "x + y = " << safe_format(x + y) << std::endl;
        std::cout << "z = " << safe_format(z) << std::endl;
        return 0;
    }

- ``safe_signed_range`` defines a type which is limited to the indicated range. Out of range assignments will be detected at compile time if possible (as in this case) or at run time if necessary.

- A safe range could be defined with the same minimum and maximum value effectively restricting the type to holding one specific value. This is what `safe_signed_literal` does.

- Defining constants with `safe_signed_literal` enables the library to correctly anticipate the correct range of the results of arithmetic expressions at compile time.

- The usage of ``loose_trap_policy`` will mean that any assignment to z which could be outside its legal range will result in a compile time error.

- All safe integer operations are implemented as constant expressions. The usage of `constexpr` will guarantee that `z` will be available at compile time for any subsequent use.

- So if this program compiles, it's guaranteed to return a valid result.

The output uses a custom output manipulator, `safe_format`, for safe types to display the underlying type and its range as well as current value. This program produces the following run time output.

    example 83:
    x = <signed char>[10,10] = 10
    y = <signed char>[67,67] = 67
    x + y = <int>[77,77] = 77
    z = <signed char>[-24,82] = 77

Take note of the various variable types:

- `x` and `y` are safe types with fixed ranges which encompass one single value. They can hold only that value which they have been assigned at compile time.

- `The sum x + y can also be determined at compile time.`

- The type of z is defined so that It can hold only values in the closed range -24,82. We can assign the sum of x + y because it is in the range that `z` is guaranteed to hold. If the sum could not be be guaranteed to fall in the range of `z`, we would get a compile time error due to the fact we are using the `loose_trap_policy` exception policy.

All this information regarding the range and values of variables has been determined at compile time. There is no runtime overhead. The usage of safe types does not alter the calculations or results in anyway. So `safe_t` and `const_safe_t` could be redefined to `int` and `const int` respectively and the program would operate identically - although it might We could compile the program for another machine - as is common when building embedded systems and know (assuming the target machine architecture was the same as our native one) that no erroneous results would ever be produced.