checked_result.hpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. #ifndef BOOST_NUMERIC_CHECKED_RESULT
  2. #define BOOST_NUMERIC_CHECKED_RESULT
  3. // Copyright (c) 2012 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 operations for doing checked aritmetic on NATIVE
  9. // C++ types.
  10. #include <cassert>
  11. #include <type_traits> // is_convertible
  12. #include "exception.hpp"
  13. namespace boost {
  14. namespace safe_numerics {
  15. template<typename R>
  16. struct checked_result {
  17. const safe_numerics_error m_e;
  18. union contents {
  19. R m_r;
  20. char const * const m_msg;
  21. // contstructors for different types
  22. constexpr contents(const R & r) noexcept : m_r(r){}
  23. constexpr contents(char const * msg) noexcept : m_msg(msg) {}
  24. constexpr operator R () noexcept {
  25. return m_r;
  26. }
  27. constexpr operator char const * () noexcept {
  28. return m_msg;
  29. }
  30. };
  31. contents m_contents;
  32. // don't permit construction without initial value;
  33. checked_result() = delete;
  34. checked_result(const checked_result & r) = default;
  35. checked_result(checked_result && r) = default;
  36. constexpr /*explicit*/ checked_result(const R & r) noexcept :
  37. m_e(safe_numerics_error::success),
  38. m_contents{r}
  39. {}
  40. constexpr /*explicit*/ checked_result(
  41. const safe_numerics_error & e,
  42. const char * msg = ""
  43. ) noexcept :
  44. m_e(e),
  45. m_contents{msg}
  46. {
  47. assert(m_e != safe_numerics_error::success);
  48. }
  49. // permit construct from another checked result type
  50. template<typename T>
  51. constexpr /*explicit*/ checked_result(const checked_result<T> & t) noexcept :
  52. m_e(t.m_e)
  53. {
  54. static_assert(
  55. std::is_convertible<T, R>::value,
  56. "T must be convertible to R"
  57. );
  58. if(safe_numerics_error::success == t.m_e)
  59. m_contents.m_r = t.m_r;
  60. else
  61. m_contents.m_msg = t.m_msg;
  62. }
  63. constexpr bool exception() const {
  64. return m_e != safe_numerics_error::success;
  65. }
  66. // accesors
  67. constexpr operator R() const noexcept{
  68. // don't assert here. Let the library catch these errors
  69. // assert(! exception());
  70. return m_contents.m_r;
  71. }
  72. constexpr operator safe_numerics_error () const noexcept{
  73. // note that this is a legitimate operation even when
  74. // the operation was successful - it will return success
  75. return m_e;
  76. }
  77. constexpr operator const char *() const noexcept{
  78. assert(exception());
  79. return m_contents.m_msg;
  80. }
  81. // disallow assignment
  82. checked_result & operator=(const checked_result &) = delete;
  83. }; // checked_result
  84. template <class R>
  85. class make_checked_result {
  86. public:
  87. template<safe_numerics_error E>
  88. constexpr static checked_result<R> invoke(
  89. char const * const & m
  90. ) noexcept {
  91. return checked_result<R>(E, m);
  92. }
  93. };
  94. } // safe_numerics
  95. } // boost
  96. #endif // BOOST_NUMERIC_CHECKED_RESULT