| ## Safe Numerics

### Mixing Approaches

For purposes of exposition, we've divided the discussion of how to eliminate runtime penalties by the different approaches available. A realistic program could likely include all techniques mentioned above. Consider the following:

    //  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 <stdexcept>
    #include <iostream>
    #include <sstream>

    #include <boost/safe_numerics/safe_integer.hpp>
    #include <boost/safe_numerics/safe_integer_range.hpp>
    #include <boost/safe_numerics/native.hpp>
    #include <boost/safe_numerics/exception.hpp>

    #include "safe_format.hpp" // prints out range and value of any type

    using namespace boost::safe_numerics;

    using safe_t = safe_signed_range<
        -24,
        82,
        native,
        loose_exception_policy
    >;

    // define variables used for input
    using input_safe_t = safe_signed_range<
        -24,
        82,
        native, // we don't need automatic in this case
        loose_exception_policy // assignment of out of range value should throw
    >;

    // function arguments can never be outside of limits
    auto f(const safe_t & x, const safe_t & y){
        auto z = x + y;  // we know that this cannot fail
        std::cout << "z = " << safe_format(z) << std::endl;
        std::cout << "(x + y) = " << safe_format(x + y) << std::endl;
        std::cout << "(x - y) = " << safe_format(x - y) << std::endl;
        return z;
    }

    bool test(const char * test_string){
        std::istringstream sin(test_string);
        input_safe_t x, y;
        try{
            std::cout << "type in values in format x y:" << test_string << std::endl;
            sin >> x >> y; // read varibles, maybe throw exception
        }
        catch(const std::exception & e){
            // none of the above should trap. Mark failure if they do
            std::cout << e.what() << '\n' << "input failure" << std::endl;
            return false;
        }
        std::cout << "x" << safe_format(x) << std::endl;
        std::cout << "y" << safe_format(y) << std::endl;
        std::cout << safe_format(f(x, y)) << std::endl;
        std::cout << "input success" << std::endl;
        return true;
    }

    int main(){
        std::cout << "example 84:\n";
        bool result =
            !  test("123 125")
            && test("0 0")
            && test("-24 82")
        ;
        std::cout << (result ? "Success!" : "Failure") << std::endl;
        return result ? EXIT_SUCCESS : EXIT_FAILURE;
    }

- As before, we define a type `safe_t` to reflect our view of legal values for this program. This uses the `automatic` type promotion policy as well as the `loose_trap_policy` exception policy to enforce elimination of runtime penalties.

- The function `f` accepts only arguments of type `safe_t` so there is no need to check the input values. This performs the functionality of programming by contract with no runtime cost.

- In addition, we define `input_safe_t` to be used when reading variables from the program console. Clearly, these can only be checked at runtime so they use the throw_exception policy. When variables are read from the console they are checked for legal values. We need no ad hoc code to do this, as these types are guaranteed to contain legal values and will throw an exception when this guarantee is violated. In other words, we automatically get checking of input variables with no additional programming.

- On calling of the function `f`, arguments of type `input_safe_t` are converted to values of type `safe_t` . In this particular example, it can be determined at compile time that construction of an instance of a `safe_t` from an `input_safe_t` can never fail. Hence, no `try/catch` block is necessary. The usage of the `loose_trap_policy` policy for `safe_t` types guarantees this to be true at compile time.

Here is the output from the program when values 12 and 32 are input from the console:

    example 84:
    type in values in format x y:33 45
    x<signed char>[-24,82] = 33
    y<signed char>[-24,82] = 45
    z = <short>[-48,164] = 78
    (x + y) = <short>[-48,164] = 78
    (x - y) = <signed char>[-106,106] = -12
    <short>[-48,164] = 78