![]() |
Safe Numerics |
Up until now, we've focused on detecting when incorrect results are produced and handling these occurances either by throwing an exception or invoking some designated function. We've achieved our goal of enforcing arithmetically correct behavior - but at what cost. For many C++ programers any runtime penalty is unacceptable. Whether or not one agrees with this tradeoff, its a fact that many C++ programmers feel this way. So the question arises as to how we alter our program to minimize or eliminate any runtime penalty.
The first step is to determine what parts of a program might invoke
exceptions. The following program is similar to previous examples but uses a
special exception policy: trap_exception.
#include <iostream>
#include "../include/safe_integer.hpp"
#include "../include/exception.hpp" // include exception policies
#include "safe_format.hpp" // prints out range and value of any type
using safe_t = boost::numeric::safe<
int,
boost::numeric::native,
boost::numeric::trap_exception // note use of "trap_exception" policy!
>;
safe_t f(const safe_t & x, const safe_t & y){
// each statement below will fail to compile !
safe_t z = x + y;
std::cout << "(x + y)" << safe_format(x + y) << std::endl;
std::cout << "(x - y)" << safe_format(x - y) << std::endl;
return z;
}
int main(int argc, const char * argv[]){
std::cout << "example 81:\n";
safe_t x(INT_MAX); // will fail to compile
safe_t y(2); // will fail to compile
std::cout << "x" << safe_format(x) << std::endl;
std::cout << "y" << safe_format(y) << std::endl;
std::cout << "z" << safe_format(f(x, y)) << std::endl;
return 0;
}
Now,
any expression which MIGHT fail at runtime is flagged with a
compile time error. There is no longer any need for try/catch
blocks. Since this program does not compile, the library absolutely guarantees that no
arithmetic expression will yield incorrect results .
This is our original goal. Now all we need to do is make the program work.
There are a couple of ways to do this.