#ifndef BOOST_NUMERIC_CHECKED_DEFAULT_HPP #define BOOST_NUMERIC_CHECKED_DEFAULT_HPP // Copyright (c) 2017 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) // contains operation implementation of arithmetic operators // on built-in types. The default implementation is to just // invoke the operation with no checking. These are overloaded // for specific types such as integer, etc. // implement the equivant of template partial specialization for functions // what we need is // a) a default implementation of add, subtract, etc which just // implements the standard operations and returns the result // b) specific implementations to be called from safe implementation // such as safe ... and someday maybe money ... // // What we need is partial function specialization - but this doesn't // exist in C++ (yet?). But particial specialization of structures DOES // exist. So put our functions into a class which can then be // partially specialized. Finally. add a function interface to so that // data types can be deduced from the function call. We now have // the equivalent of partial function template specialization. // usage example: checked::add(t, u) ... #include #include "checked_result.hpp" namespace boost { namespace safe_numerics { // main function object which contains functions which handle // primitives which haven't been overriden. For now, these // implement the default operation. But I see this as an indicator // that there is more work to be done. For example float * int should // never be called because promotions on operands should occur before // the operation is invoked. So rather than returning the default operation // it should trap with a static_assert. This occurs at compile time while // calculating result interval. This needs more investigation. template< typename R, R Min, R Max, typename T, class F = make_checked_result, class Default = void > struct heterogeneous_checked_operation { constexpr static checked_result cast(const T & t) /* noexcept */ { return static_cast(t); } }; template< typename R, class F = make_checked_result, class Default = void > struct checked_operation{ constexpr static checked_result minus(const R & t) noexcept { return - t; } constexpr static checked_result add(const R & t, const R & u) noexcept { return t + u; } constexpr static checked_result subtract(const R & t, const R & u) noexcept { return t - u; } constexpr static checked_result multiply(const R & t, const R & u) noexcept { return t * u; } constexpr static checked_result divide(const R & t, const R & u) noexcept { return t / u; } constexpr static checked_result modulus(const R & t, const R & u) noexcept { return t % u; } constexpr static boost::logic::tribool less_than(const R & t, const R & u) noexcept { return t < u; } constexpr static boost::logic::tribool greater_than(const R & t, const R & u) noexcept { return t > u; } constexpr static boost::logic::tribool equal(const R & t, const R & u) noexcept { return t < u; } constexpr static checked_result left_shift(const R & t, const R & u) noexcept { return t << u; } constexpr static checked_result right_shift(const R & t, const R & u) noexcept { return t >> u; } constexpr static checked_result bitwise_or(const R & t, const R & u) noexcept { return t | u; } constexpr static checked_result bitwise_xor(const R & t, const R & u) noexcept { return t ^ u; } constexpr static checked_result bitwise_and(const R & t, const R & u) noexcept { return t & u; } constexpr static checked_result bitwise_not(const R & t) noexcept { return ~t; } }; namespace checked { // implement function call interface so that types other than // the result type R can be deduced from the function parameters. template constexpr checked_result cast(const T & t) /* noexcept */ { return heterogeneous_checked_operation< R, std::numeric_limits::min(), std::numeric_limits::max(), T >::cast(t); } template constexpr checked_result minus(const R & t) noexcept { return checked_operation::minus(t); } template constexpr checked_result add(const R & t, const R & u) noexcept { return checked_operation::add(t, u); } template constexpr checked_result subtract(const R & t, const R & u) noexcept { return checked_operation::subtract(t, u); } template constexpr checked_result multiply(const R & t, const R & u) noexcept { return checked_operation::multiply(t, u); } template constexpr checked_result divide(const R & t, const R & u) noexcept { return checked_operation::divide(t, u); } template constexpr checked_result modulus(const R & t, const R & u) noexcept { return checked_operation::modulus(t, u); } template constexpr checked_result less_than(const R & t, const R & u) noexcept { return checked_operation::less_than(t, u); } template constexpr checked_result greater_than_equal(const R & t, const R & u) noexcept { return ! checked_operation::less_than(t, u); } template constexpr checked_result greater_than(const R & t, const R & u) noexcept { return checked_operation::greater_than(t, u); } template constexpr checked_result less_than_equal(const R & t, const R & u) noexcept { return ! checked_operation::greater_than(t, u); } template constexpr checked_result equal(const R & t, const R & u) noexcept { return checked_operation::equal(t, u); } template constexpr checked_result left_shift(const R & t, const R & u) noexcept { return checked_operation::left_shift(t, u); } template constexpr checked_result right_shift(const R & t, const R & u) noexcept { return checked_operation::right_shift(t, u); } template constexpr checked_result bitwise_or(const R & t, const R & u) noexcept { return checked_operation::bitwise_or(t, u); } template constexpr checked_result bitwise_xor(const R & t, const R & u) noexcept { return checked_operation::bitwise_xor(t, u); } template constexpr checked_result bitwise_and(const R & t, const R & u) noexcept { return checked_operation::bitwise_and(t, u); } template constexpr checked_result bitwise_not(const R & t) noexcept { return checked_operation::bitwise_not(t); } } // checked } // safe_numerics } // boost #endif // BOOST_NUMERIC_CHECKED_DEFAULT_HPP