| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 | #ifndef BOOST_NUMERIC_CHECKED_RESULT#define BOOST_NUMERIC_CHECKED_RESULT//  Copyright (c) 2012 Robert Ramey//// Distributed under the Boost Software License, Version 1.0. (See// accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt)// contains operations for doing checked aritmetic on NATIVE// C++ types.#include <cassert>#include <type_traits> // is_convertible#include "exception.hpp"namespace boost {namespace safe_numerics {template<typename R>struct checked_result {    const safe_numerics_error m_e;    const union {        R m_r;        char const * m_msg;    };        // don't permit construction without initial value;    checked_result() = delete;    // note: I implemented the following non-default copy and move    // constructors because I thought I needed to do this in order    // to make them constexpr.  Turns out though that doing this creates    // a syntax error because the assignment results in error due    // to assignment "outside of object lifetime".  I think this could    // be addressed by replacing the anonymous union above with a    // named union.  This would create some syntax changes which would    // ripple through some parts of th program.  So for now, we'll just    // rely on the default copy and move constructors.    #if 0    // copy constructor    constexpr /*explicit*/ checked_result(const checked_result & r) noexpect :        m_e(r.m_e)    {        if(safe_numerics_error::success == r.m_e)            m_r = r.m_r;        else            m_msg = r.m_msg;    }    // move constructor    constexpr /*explicit*/ checked_result(checked_result && r) noexcept :        m_e(r.m_e)    {        if(safe_numerics_error::success == r.m_e)            m_r = r.m_r;        else            m_msg = r.m_msg;    }    #endif    checked_result(const checked_result & r) = default;    checked_result(checked_result && r) = default;        constexpr /*explicit*/ checked_result(const R & r) :        m_e(safe_numerics_error::success),        m_r(r)    {}    #if 0    template<typename T>    constexpr /*explicit*/ checked_result(const T & t) noexcept :        m_e(safe_numerics_error::success),        m_r(t)    {}    #endif    constexpr /*explicit*/ checked_result(        const safe_numerics_error & e,        const char * msg = ""    )  noexcept :        m_e(e),        m_msg(msg)    {        assert(m_e != safe_numerics_error::success);    }    // permit construct from another checked result type    template<typename T>    constexpr /*explicit*/ checked_result(const checked_result<T> & t) noexcept :        m_e(t.m_e)    {        static_assert(            std::is_convertible<T, R>::value,            "T must be convertible to R"        );        if(safe_numerics_error::success == t.m_e)            m_r = t.m_r;        else            m_msg = t.m_msg;    }    constexpr bool exception() const {        return m_e != safe_numerics_error::success;    }    // accesors    constexpr operator R() const  noexcept{        // don't assert here.  Let the library catch these errors        assert(! exception());        return m_r;    }        constexpr operator safe_numerics_error () const  noexcept{        // note that this is a legitimate operation even when        // the operation was successful - it will return success        return m_e;    }    constexpr operator const char *() const  noexcept{        assert(exception());        return m_msg;    }    // disallow assignment    checked_result & operator=(const checked_result &) = delete;};#if 0template<typename R>constexpr checked_result<R> make_checked_result(    const safe_numerics_error & e,    char const * const & m)  noexcept {    return checked_result<R>(e, m);}#endiftemplate <class R>class make_checked_result {public:    template<safe_numerics_error E>    constexpr static checked_result<R> invoke(        char const * const & m    ) noexcept {        return checked_result<R>(E, m);    }};} // safe_numerics} // boost#endif  // BOOST_NUMERIC_CHECKED_RESULT
 |