...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
Safe Numerics |
C++ contains signed and unsigned integer types. In spite of their names, they function differently which often produces surprising results for some operands. Program errors from this behavior can be exceedingly difficult to find. This has lead to recommendations of various ad hoc "rules" to avoid these problems. It's not always easy to apply these "rules" to existing code without creating even more bugs. Here is a typical example of this problem:
// 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 <cstdint> #include <boost/safe_numerics/safe_integer.hpp> using namespace std; using namespace boost::safe_numerics; void f(const unsigned int & x, const int8_t & y){ cout << x * y << endl; } void safe_f( const safe<unsigned int> & x, const safe<int8_t> & y ){ cout << x * y << endl; } int main(){ cout << "example 4: "; cout << "mixing types produces surprising results" << endl; try { std::cout << "Not using safe numerics" << std::endl; // problem: mixing types produces surprising results. f(100, 100); // works as expected f(100, -100); // wrong result - unnoticed cout << "error NOT detected!" << endl;; } catch(const std::exception & e){ // never arrive here cout << "error detected:" << e.what() << endl;; } try { // solution: use safe types std::cout << "Using safe numerics" << std::endl; safe_f(100, 100); // works as expected safe_f(100, -100); // throw error cout << "error NOT detected!" << endl;; } catch(const std::exception & e){ cout << "error detected:" << e.what() << endl;; } return 0; }
Here is the output of the above program:
example 4: mixing types produces surprising results Not using safe numerics 10000 4294957296 error NOT detected! Using safe numerics 10000 error detected!converted negative value to unsigned: domain error
This solution is simple, just replace instances of int
with safe<int>
.