checked_default.hpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #ifndef BOOST_NUMERIC_CHECKED_DEFAULT_HPP
  2. #define BOOST_NUMERIC_CHECKED_DEFAULT_HPP
  3. // Copyright (c) 2017 Robert Ramey
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See
  6. // accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. // contains operation implementation of arithmetic operators
  9. // on built-in types. The default implementation is to just
  10. // invoke the operation with no checking. These are overloaded
  11. // for specific types such as integer, etc.
  12. // implement the equivant of template partial specialization for functions
  13. // what we need is
  14. // a) a default implementation of add, subtract, etc which just
  15. // implements the standard operations and returns the result
  16. // b) specific implementations to be called from safe implementation
  17. // such as safe<int> ... and someday maybe money<T, D> ...
  18. //
  19. // What we need is partial function specialization - but this doesn't
  20. // exist in C++ (yet?). But particial specialization of structures DOES
  21. // exist. So put our functions into a class which can then be
  22. // partially specialized. Finally. add a function interface to so that
  23. // data types can be deduced from the function call. We now have
  24. // the equivalent of partial function template specialization.
  25. // usage example: checked<int>::add(t, u) ...
  26. #include <boost/logic/tribool.hpp>
  27. #include "checked_result.hpp"
  28. namespace boost {
  29. namespace safe_numerics {
  30. // main function object which contains functions which handle
  31. // primitives which haven't been overriden. For now, these
  32. // implement the default operation. But I see this as an indicator
  33. // that there is more work to be done. For example float * int should
  34. // never be called because promotions on operands should occur before
  35. // the operation is invoked. So rather than returning the default operation
  36. // it should trap with a static_assert. This occurs at compile time while
  37. // calculating result interval. This needs more investigation.
  38. template<
  39. typename R,
  40. typename T,
  41. class F = make_checked_result<R>,
  42. class Default = void
  43. >
  44. struct heterogeneous_checked_operation {
  45. constexpr static checked_result<R>
  46. cast(const T & t) /* noexcept */ {
  47. return static_cast<R>(t);
  48. }
  49. };
  50. template<
  51. typename R,
  52. class F = make_checked_result<R>,
  53. class Default = void
  54. >
  55. struct checked_operation{
  56. constexpr static checked_result<R>
  57. minus(const R & t) noexcept {
  58. return - t;
  59. }
  60. constexpr static checked_result<R>
  61. add(const R & t, const R & u) noexcept {
  62. return t + u;
  63. }
  64. constexpr static checked_result<R>
  65. subtract(const R & t, const R & u) noexcept {
  66. return t - u;
  67. }
  68. constexpr static checked_result<R>
  69. multiply(const R & t, const R & u) noexcept {
  70. return t * u;
  71. }
  72. constexpr static checked_result<R>
  73. divide(const R & t, const R & u) noexcept {
  74. return t / u;
  75. }
  76. constexpr static checked_result<R>
  77. modulus(const R & t, const R & u) noexcept {
  78. return t % u;
  79. }
  80. constexpr static boost::logic::tribool
  81. less_than(const R & t, const R & u) noexcept {
  82. return t < u;
  83. }
  84. constexpr static boost::logic::tribool
  85. greater_than(const R & t, const R & u) noexcept {
  86. return t > u;
  87. }
  88. constexpr static boost::logic::tribool
  89. equal(const R & t, const R & u) noexcept {
  90. return t < u;
  91. }
  92. constexpr static checked_result<R>
  93. left_shift(const R & t, const R & u) noexcept {
  94. return t << u;
  95. }
  96. constexpr static checked_result<R>
  97. right_shift(const R & t, const R & u) noexcept {
  98. return t >> u;
  99. }
  100. constexpr static checked_result<R>
  101. bitwise_or(const R & t, const R & u) noexcept {
  102. return t | u;
  103. }
  104. constexpr static checked_result<R>
  105. bitwise_xor(const R & t, const R & u) noexcept {
  106. return t ^ u;
  107. }
  108. constexpr static checked_result<R>
  109. bitwise_and(const R & t, const R & u) noexcept {
  110. return t & u;
  111. }
  112. constexpr static checked_result<R>
  113. bitwise_not(const R & t) noexcept {
  114. return ~t;
  115. }
  116. };
  117. namespace checked {
  118. // implement function call interface so that types other than
  119. // the result type R can be deduced from the function parameters.
  120. template<typename R, typename T>
  121. constexpr checked_result<R> cast(const T & t) /* noexcept */ {
  122. return heterogeneous_checked_operation<R, T>::cast(t);
  123. }
  124. template<typename R>
  125. constexpr checked_result<R> minus(const R & t) noexcept {
  126. return checked_operation<R>::minus(t);
  127. }
  128. template<typename R>
  129. constexpr checked_result<R> add(const R & t, const R & u) noexcept {
  130. return checked_operation<R>::add(t, u);
  131. }
  132. template<typename R>
  133. constexpr checked_result<R> subtract(const R & t, const R & u) noexcept {
  134. return checked_operation<R>::subtract(t, u);
  135. }
  136. template<typename R>
  137. constexpr checked_result<R> multiply(const R & t, const R & u) noexcept {
  138. return checked_operation<R>::multiply(t, u);
  139. }
  140. template<typename R>
  141. constexpr checked_result<R> divide(const R & t, const R & u) noexcept {
  142. return checked_operation<R>::divide(t, u);
  143. }
  144. template<typename R>
  145. constexpr checked_result<R> modulus(const R & t, const R & u) noexcept {
  146. return checked_operation<R>::modulus(t, u);
  147. }
  148. template<typename R>
  149. constexpr checked_result<bool> less_than(const R & t, const R & u) noexcept {
  150. return checked_operation<R>::less_than(t, u);
  151. }
  152. template<typename R>
  153. constexpr checked_result<bool> greater_than_equal(const R & t, const R & u) noexcept {
  154. return ! checked_operation<R>::less_than(t, u);
  155. }
  156. template<typename R>
  157. constexpr checked_result<bool> greater_than(const R & t, const R & u) noexcept {
  158. return checked_operation<R>::greater_than(t, u);
  159. }
  160. template<typename R>
  161. constexpr checked_result<bool> less_than_equal(const R & t, const R & u) noexcept {
  162. return ! checked_operation<R>::greater_than(t, u);
  163. }
  164. template<typename R>
  165. constexpr checked_result<bool> equal(const R & t, const R & u) noexcept {
  166. return checked_operation<R>::equal(t, u);
  167. }
  168. template<typename R>
  169. constexpr checked_result<R> left_shift(const R & t, const R & u) noexcept {
  170. return checked_operation<R>::left_shift(t, u);
  171. }
  172. template<typename R>
  173. constexpr checked_result<R> right_shift(const R & t, const R & u) noexcept {
  174. return checked_operation<R>::right_shift(t, u);
  175. }
  176. template<typename R>
  177. constexpr checked_result<R> bitwise_or(const R & t, const R & u) noexcept {
  178. return checked_operation<R>::bitwise_or(t, u);
  179. }
  180. template<typename R>
  181. constexpr checked_result<R> bitwise_xor(const R & t, const R & u) noexcept {
  182. return checked_operation<R>::bitwise_xor(t, u);
  183. }
  184. template<typename R>
  185. constexpr checked_result<R> bitwise_and(const R & t, const R & u) noexcept {
  186. return checked_operation<R>::bitwise_and(t, u);
  187. }
  188. template<typename R>
  189. constexpr checked_result<R> bitwise_not(const R & t) noexcept {
  190. return checked_operation<R>::bitwise_not(t);
  191. }
  192. } // checked
  193. } // safe_numerics
  194. } // boost
  195. #endif // BOOST_NUMERIC_CHECKED_DEFAULT_HPP