exception_policies.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #ifndef BOOST_NUMERIC_EXCEPTION_POLICIES_HPP
  2. #define BOOST_NUMERIC_EXCEPTION_POLICIES_HPP
  3. // Copyright (c) 2015 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. #include <boost/mp11.hpp>
  9. #include <boost/config.hpp> // BOOST_NO_EXCEPTIONS
  10. #include "exception.hpp"
  11. namespace boost {
  12. namespace safe_numerics {
  13. template<
  14. typename AE,
  15. typename IDB,
  16. typename UB,
  17. typename UV
  18. >
  19. struct exception_policy {
  20. constexpr static void on_arithmetic_error(
  21. const safe_numerics_error & e,
  22. const char * msg
  23. ){
  24. AE()(e, msg);
  25. }
  26. constexpr static void on_implementation_defined_behavior(
  27. const safe_numerics_error & e,
  28. const char * msg
  29. ){
  30. IDB()(e, msg);
  31. }
  32. constexpr static void on_undefined_behavior(
  33. const safe_numerics_error & e,
  34. const char * msg
  35. ){
  36. UB()(e, msg);
  37. }
  38. constexpr static void on_uninitialized_value(
  39. const safe_numerics_error & e,
  40. const char * msg
  41. ){
  42. UV()(e, msg);
  43. }
  44. };
  45. ////////////////////////////////////////////////////////////////////////////////
  46. // pre-made error action handers
  47. // ignore any error and just return.
  48. struct ignore_exception {
  49. constexpr ignore_exception() = default;
  50. constexpr void operator () (
  51. const boost::safe_numerics::safe_numerics_error &,
  52. const char *
  53. ){}
  54. };
  55. // emit compile time error if this is invoked.
  56. struct trap_exception {
  57. constexpr trap_exception() = default;
  58. // error will occur on operator call.
  59. // hopefully this will display arguments
  60. };
  61. // If an exceptional condition is detected at runtime throw the exception.
  62. struct throw_exception {
  63. constexpr throw_exception() = default;
  64. #ifndef BOOST_NO_EXCEPTIONS
  65. void operator()(
  66. const safe_numerics_error & e,
  67. const char * message
  68. ){
  69. throw std::system_error(std::error_code(e), message);
  70. }
  71. #else
  72. constexpr trap_exception()(const safe_numerics_error & e, const char * message);
  73. #endif
  74. };
  75. // given an error code - return the action code which it corresponds to.
  76. constexpr inline safe_numerics_actions
  77. make_safe_numerics_action(const safe_numerics_error & e){
  78. // we can't use standard algorithms since we want this to be constexpr
  79. // this brute force solution is simple and pretty fast anyway
  80. switch(e){
  81. case safe_numerics_error::negative_overflow_error:
  82. case safe_numerics_error::underflow_error:
  83. case safe_numerics_error::range_error:
  84. case safe_numerics_error::domain_error:
  85. case safe_numerics_error::positive_overflow_error:
  86. case safe_numerics_error::precision_overflow_error:
  87. return safe_numerics_actions::arithmetic_error;
  88. case safe_numerics_error::negative_value_shift:
  89. case safe_numerics_error::negative_shift:
  90. case safe_numerics_error::shift_too_large:
  91. return safe_numerics_actions::implementation_defined_behavior;
  92. case safe_numerics_error::uninitialized_value:
  93. return safe_numerics_actions::uninitialized_value;
  94. case safe_numerics_error::success:
  95. return safe_numerics_actions::no_action;
  96. default:
  97. assert(false);
  98. }
  99. // should never arrive here
  100. //include to suppress bogus warning
  101. return safe_numerics_actions::no_action;
  102. }
  103. ////////////////////////////////////////////////////////////////////////////////
  104. // pre-made error policy classes
  105. // loose exception
  106. // - throw on arithmetic errors
  107. // - ignore other errors.
  108. // Some applications ignore these issues and still work and we don't
  109. // want to update them.
  110. using loose_exception_policy = exception_policy<
  111. throw_exception, // arithmetic error
  112. ignore_exception, // implementation defined behavior
  113. ignore_exception, // undefined behavior
  114. ignore_exception // uninitialized value
  115. >;
  116. // loose trap
  117. // same as above in that it doesn't check for various undefined behaviors
  118. // but traps at compile time for hard arithmetic errors. This policy
  119. // would be suitable for older embedded systems which depend on
  120. // bit manipulation operations to work.
  121. using loose_trap_policy = exception_policy<
  122. trap_exception, // arithmetic error
  123. ignore_exception, // implementation defined behavior
  124. ignore_exception, // undefined behavior
  125. ignore_exception // uninitialized value
  126. >;
  127. // strict exception
  128. // - throw at runtime on any kind of error
  129. // recommended for new code. Check everything at compile time
  130. // if possible and runtime if necessary. Trap or Throw as
  131. // appropriate. Should guarantee code to be portable across
  132. // architectures.
  133. using strict_exception_policy = exception_policy<
  134. throw_exception,
  135. throw_exception,
  136. throw_exception,
  137. ignore_exception
  138. >;
  139. // strict trap
  140. // Same as above but requires code to be written in such a way as to
  141. // make it impossible for errors to occur. This naturally will require
  142. // extra coding effort but might be justified for embedded and/or
  143. // safety critical systems.
  144. using strict_trap_policy = exception_policy<
  145. trap_exception,
  146. trap_exception,
  147. trap_exception,
  148. trap_exception
  149. >;
  150. // default policy
  151. // One would use this first. After experimentation, one might
  152. // replace some actions with ignore_exception
  153. using default_exception_policy = strict_exception_policy;
  154. } // namespace safe_numerics
  155. } // namespace boost
  156. #endif // BOOST_NUMERIC_EXCEPTION_POLICIES_HPP