Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:51:36

0001 #ifndef BOOST_NUMERIC_CHECKED_RESULT
0002 #define BOOST_NUMERIC_CHECKED_RESULT
0003 
0004 //  Copyright (c) 2012 Robert Ramey
0005 //
0006 // Distributed under the Boost Software License, Version 1.0. (See
0007 // accompanying file LICENSE_1_0.txt or copy at
0008 // http://www.boost.org/LICENSE_1_0.txt)
0009 
0010 // contains operations for doing checked aritmetic on NATIVE
0011 // C++ types.
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         // contstructors for different types
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     // don't permit construction without initial value;
0038     checked_result() = delete;
0039     checked_result(const checked_result & r) = default;
0040     checked_result(checked_result && r) = default;
0041     
0042     constexpr /*explicit*/ checked_result(const R & r) noexcept :
0043         m_e(safe_numerics_error::success),
0044         m_contents{r}
0045     {}
0046 
0047     constexpr /*explicit*/ 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     // permit construct from another checked result type
0058     template<typename T>
0059     constexpr /*explicit*/ 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     // accesors
0077     constexpr operator R() const noexcept{
0078         // don't assert here.  Let the library catch these errors
0079         // assert(! exception());
0080         return m_contents.m_r;
0081     }
0082     
0083     constexpr operator safe_numerics_error () const noexcept{
0084         // note that this is a legitimate operation even when
0085         // the operation was successful - it will return success
0086         return m_e;
0087     }
0088     constexpr operator const char *() const noexcept{
0089         assert(exception());
0090         return m_contents.m_msg;
0091     }
0092 
0093     // disallow assignment
0094     checked_result & operator=(const checked_result &) = delete;
0095 }; // checked_result
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 } // safe_numerics
0109 } // boost
0110 
0111 #endif  // BOOST_NUMERIC_CHECKED_RESULT