File indexing completed on 2025-01-18 09:51:36
0001 #ifndef BOOST_NUMERIC_CHECKED_RESULT
0002 #define BOOST_NUMERIC_CHECKED_RESULT
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <cassert>
0013 #include <type_traits> // is_convertible
0014 #include "exception.hpp"
0015
0016 namespace boost {
0017 namespace safe_numerics {
0018
0019 template<typename R>
0020 struct checked_result {
0021 const safe_numerics_error m_e;
0022 union contents {
0023 R m_r;
0024 char const * const m_msg;
0025
0026 constexpr contents(const R & r) noexcept : m_r(r){}
0027 constexpr contents(char const * msg) noexcept : m_msg(msg) {}
0028 constexpr operator R () noexcept {
0029 return m_r;
0030 }
0031 constexpr operator char const * () noexcept {
0032 return m_msg;
0033 }
0034 };
0035 contents m_contents;
0036
0037
0038 checked_result() = delete;
0039 checked_result(const checked_result & r) = default;
0040 checked_result(checked_result && r) = default;
0041
0042 constexpr checked_result(const R & r) noexcept :
0043 m_e(safe_numerics_error::success),
0044 m_contents{r}
0045 {}
0046
0047 constexpr checked_result(
0048 const safe_numerics_error & e,
0049 const char * msg = ""
0050 ) noexcept :
0051 m_e(e),
0052 m_contents{msg}
0053 {
0054 assert(m_e != safe_numerics_error::success);
0055 }
0056
0057
0058 template<typename T>
0059 constexpr checked_result(const checked_result<T> & t) noexcept :
0060 m_e(t.m_e)
0061 {
0062 static_assert(
0063 std::is_convertible<T, R>::value,
0064 "T must be convertible to R"
0065 );
0066 if(safe_numerics_error::success == t.m_e)
0067 m_contents.m_r = t.m_r;
0068 else
0069 m_contents.m_msg = t.m_msg;
0070 }
0071
0072 constexpr bool exception() const {
0073 return m_e != safe_numerics_error::success;
0074 }
0075
0076
0077 constexpr operator R() const noexcept{
0078
0079
0080 return m_contents.m_r;
0081 }
0082
0083 constexpr operator safe_numerics_error () const noexcept{
0084
0085
0086 return m_e;
0087 }
0088 constexpr operator const char *() const noexcept{
0089 assert(exception());
0090 return m_contents.m_msg;
0091 }
0092
0093
0094 checked_result & operator=(const checked_result &) = delete;
0095 };
0096
0097 template <class R>
0098 class make_checked_result {
0099 public:
0100 template<safe_numerics_error E>
0101 constexpr static checked_result<R> invoke(
0102 char const * const & m
0103 ) noexcept {
0104 return checked_result<R>(E, m);
0105 }
0106 };
0107
0108 }
0109 }
0110
0111 #endif