#ifndef BOOST_NUMERIC_SAFE_COMPARE_HPP #define BOOST_NUMERIC_SAFE_COMPARE_HPP // Copyright (c) 2012 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 #include namespace boost { namespace safe_numerics { namespace safe_compare { //////////////////////////////////////////////////// // safe comparison on primitive integral types namespace safe_compare_detail { template using make_unsigned = typename std::conditional< std::is_signed::value, std::make_unsigned, T >::type; // both arguments unsigned or signed template struct less_than { template constexpr static bool invoke(const T & t, const U & u){ return t < u; } }; // T unsigned, U signed template<> struct less_than { template constexpr static bool invoke(const T & t, const U & u){ return (u < 0) ? false : less_than::invoke( t, static_cast::type &>(u) ) ; } }; // T signed, U unsigned template<> struct less_than { template constexpr static bool invoke(const T & t, const U & u){ return (t < 0) ? true : less_than::invoke( static_cast::type &>(t), u ) ; } }; } // safe_compare_detail template typename std::enable_if< std::is_integral::value && std::is_integral::value, bool >::type constexpr inline less_than(const T & lhs, const U & rhs) { return safe_compare_detail::less_than< std::is_signed::value, std::is_signed::value >::template invoke(lhs, rhs); } template typename std::enable_if< std::is_floating_point::value && std::is_floating_point::value, bool >::type constexpr inline less_than(const T & lhs, const U & rhs) { return lhs < rhs; } template constexpr inline bool greater_than(const T & lhs, const U & rhs) { return less_than(rhs, lhs); } template constexpr inline bool less_than_equal(const T & lhs, const U & rhs) { return ! greater_than(lhs, rhs); } template constexpr inline bool greater_than_equal(const T & lhs, const U & rhs) { return ! less_than(lhs, rhs); } namespace safe_compare_detail { // both arguments unsigned or signed template struct equal { template constexpr static bool invoke(const T & t, const U & u){ return t == u; } }; // T unsigned, U signed template<> struct equal { template constexpr static bool invoke(const T & t, const U & u){ return (u < 0) ? false : equal::invoke( t, static_cast::type &>(u) ) ; } }; // T signed, U unsigned template<> struct equal { template constexpr static bool invoke(const T & t, const U & u){ return (t < 0) ? false : equal::invoke( static_cast::type &>(t), u ) ; } }; } // safe_compare_detail template typename std::enable_if< std::is_integral::value && std::is_integral::value, bool >::type constexpr inline equal(const T & lhs, const U & rhs) { return safe_compare_detail::equal< std::numeric_limits::is_signed, std::numeric_limits::is_signed >::template invoke(lhs, rhs); } template typename std::enable_if< std::is_floating_point::value && std::is_floating_point::value, bool >::type constexpr inline equal(const T & lhs, const U & rhs) { return lhs == rhs; } template constexpr inline bool not_equal(const T & lhs, const U & rhs) { return ! equal(lhs, rhs); } } // safe_compare } // safe_numerics } // boost #endif // BOOST_NUMERIC_SAFE_COMPARE_HPP