1 #ifndef BOOST_NUMERIC_SAFE_COMPARE_HPP
2 #define BOOST_NUMERIC_SAFE_COMPARE_HPP
4 // Copyright (c) 2012 Robert Ramey
6 // Distributed under the Boost Software License, Version 1.0. (See
7 // accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
10 #include <type_traits>
14 namespace safe_numerics {
15 namespace safe_compare {
17 ////////////////////////////////////////////////////
18 // safe comparison on primitive integral types
19 namespace safe_compare_detail {
21 using make_unsigned = typename std::conditional<
22 std::is_signed<T>::value,
23 std::make_unsigned<T>,
27 // both arguments unsigned or signed
28 template<bool TS, bool US>
30 template<class T, class U>
31 constexpr static bool invoke(const T & t, const U & u){
36 // T unsigned, U signed
38 struct less_than<false, true> {
39 template<class T, class U>
40 constexpr static bool invoke(const T & t, const U & u){
45 less_than<false, false>::invoke(
47 static_cast<const typename make_unsigned<U>::type &>(u)
52 // T signed, U unsigned
54 struct less_than<true, false> {
55 template<class T, class U>
56 constexpr static bool invoke(const T & t, const U & u){
61 less_than<false, false>::invoke(
62 static_cast<const typename make_unsigned<T>::type &>(t),
68 } // safe_compare_detail
70 template<class T, class U>
71 typename std::enable_if<
72 std::is_integral<T>::value && std::is_integral<U>::value,
75 constexpr inline less_than(const T & lhs, const U & rhs) {
76 return safe_compare_detail::less_than<
77 std::is_signed<T>::value,
78 std::is_signed<U>::value
82 template<class T, class U>
83 typename std::enable_if<
84 std::is_floating_point<T>::value && std::is_floating_point<U>::value,
87 constexpr inline less_than(const T & lhs, const U & rhs) {
91 template<class T, class U>
92 constexpr inline bool greater_than(const T & lhs, const U & rhs) {
93 return less_than(rhs, lhs);
96 template<class T, class U>
97 constexpr inline bool less_than_equal(const T & lhs, const U & rhs) {
98 return ! greater_than(lhs, rhs);
101 template<class T, class U>
102 constexpr inline bool greater_than_equal(const T & lhs, const U & rhs) {
103 return ! less_than(lhs, rhs);
106 namespace safe_compare_detail {
107 // both arguments unsigned or signed
108 template<bool TS, bool US>
110 template<class T, class U>
111 constexpr static bool invoke(const T & t, const U & u){
116 // T unsigned, U signed
118 struct equal<false, true> {
119 template<class T, class U>
120 constexpr static bool invoke(const T & t, const U & u){
125 equal<false, false>::invoke(
127 static_cast<const typename make_unsigned<U>::type &>(u)
132 // T signed, U unsigned
134 struct equal<true, false> {
135 template<class T, class U>
136 constexpr static bool invoke(const T & t, const U & u){
141 equal<false, false>::invoke(
142 static_cast<const typename make_unsigned<T>::type &>(t),
148 } // safe_compare_detail
150 template<class T, class U>
151 typename std::enable_if<
152 std::is_integral<T>::value && std::is_integral<U>::value,
155 constexpr inline equal(const T & lhs, const U & rhs) {
156 return safe_compare_detail::equal<
157 std::numeric_limits<T>::is_signed,
158 std::numeric_limits<U>::is_signed
159 >:: invoke(lhs, rhs);
162 template<class T, class U>
163 typename std::enable_if<
164 std::is_floating_point<T>::value && std::is_floating_point<U>::value,
167 constexpr inline equal(const T & lhs, const U & rhs) {
171 template<class T, class U>
172 constexpr inline bool not_equal(const T & lhs, const U & rhs) {
173 return ! equal(lhs, rhs);
180 #endif // BOOST_NUMERIC_SAFE_COMPARE_HPP