diff --git a/examples/example82.cpp b/examples/example82.cpp index 8d3a71a..2fb1156 100644 --- a/examples/example82.cpp +++ b/examples/example82.cpp @@ -8,7 +8,7 @@ using safe_t = boost::numeric::safe< int, boost::numeric::automatic, // note use of "automatic" policy!!! - boost::numeric::trap_exception + boost::numeric::no_exceptions_policy >; int main(int argc, const char * argv[]){ diff --git a/examples/example83.cpp b/examples/example83.cpp index dd36933..55339fc 100644 --- a/examples/example83.cpp +++ b/examples/example83.cpp @@ -11,12 +11,12 @@ using namespace boost::numeric; // for safe_literal // create a type for holding small integers. We "know" that C++ // type promotion rules will work such that addition will never // overflow. If we change the program to break this, the usage -// of the trap_exception promotion policy will prevent compilation. +// of the no_exceptions_policy will prevent compilation. using safe_t = safe_signed_range< -24, 82, native, // C++ type promotion rules work OK for this example - trap_exception // catch problems at compile time + no_exceptions_policy // catch problems at compile time >; int main(int argc, const char * argv[]){ @@ -25,8 +25,8 @@ int main(int argc, const char * argv[]){ // since the sum of x and y wouldn't be in the legal // range for z. // const safe_signed_literal<20> x; - const safe_signed_literal<10, native, trap_exception> x; // no problem - const safe_signed_literal<67, native, trap_exception> y; + const safe_signed_literal<10, native, no_exceptions_policy> x; // no problem + const safe_signed_literal<67, native, no_exceptions_policy> y; const safe_t z = x + y; std::cout << "x = " << safe_format(x) << std::endl; diff --git a/examples/example84.cpp b/examples/example84.cpp index 2467d2d..d7ef6b1 100644 --- a/examples/example84.cpp +++ b/examples/example84.cpp @@ -13,7 +13,7 @@ using safe_t = safe_signed_range< -24, 82, automatic, - trap_exception + no_exceptions_policy >; // define variables used for input diff --git a/examples/example91.cpp b/examples/example91.cpp index 37920f4..88b0c9a 100644 --- a/examples/example91.cpp +++ b/examples/example91.cpp @@ -34,13 +34,13 @@ template // T is char, int, etc data type using safe_t = boost::numeric::safe< T, pic16_promotion, - boost::numeric::throw_exception // use for compiling and running tests + boost::numeric::default_exception_policy // use for compiling and running tests >; using safe_bool_t = boost::numeric::safe_unsigned_range< 0, 1, pic16_promotion, - boost::numeric::throw_exception // use for compiling and running tests + boost::numeric::default_exception_policy // use for compiling and running tests >; #define DESKTOP diff --git a/examples/example92.cpp b/examples/example92.cpp index a14c7fe..fe2a580 100644 --- a/examples/example92.cpp +++ b/examples/example92.cpp @@ -36,13 +36,13 @@ template // T is char, int, etc data type using safe_t = boost::numeric::safe< T, pic16_promotion, - boost::numeric::throw_exception // use for compiling and running tests + boost::numeric::default_exception_policy // use for compiling and running tests >; using safe_bool_t = boost::numeric::safe_unsigned_range< 0, 1, pic16_promotion, - boost::numeric::throw_exception // use for compiling and running tests + boost::numeric::default_exception_policy // use for compiling and running tests >; #define DESKTOP diff --git a/include/automatic.hpp b/include/automatic.hpp index e3cf6a2..8a07c54 100644 --- a/include/automatic.hpp +++ b/include/automatic.hpp @@ -251,16 +251,6 @@ struct automatic { >::type; }; - // forward to correct modulus implementation - template - checked_result - static constexpr modulus( - const T & t, - const U & u - ){ - return checked::modulus(t, u); - } - /////////////////////////////////////////////////////////////////////// // shift operations template diff --git a/include/checked.hpp b/include/checked.hpp index 2569f16..2af06ed 100644 --- a/include/checked.hpp +++ b/include/checked.hpp @@ -185,7 +185,7 @@ namespace detail { std::numeric_limits::max() - u < t ? checked_result( exception_type::positive_overflow_error, - "addition overflow" + "addition result too large" ) : checked_result(t + u) @@ -518,7 +518,7 @@ namespace detail { return (u == -1 && t == std::numeric_limits::min()) ? checked_result( - exception_type::domain_error, + exception_type::range_error, "result cannot be represented" ) : @@ -634,18 +634,13 @@ constexpr checked_left_shift( // the value of the result is E1 x 2^E2, reduced modulo one more than // the maximum value representable in the result type. - // note: we are intentionally varying from the standards language here. - // a safe is meant to be value preserving. That is t << u should - // equal an arithmetically correct value or fail in some visible manner. - // So we're going to fail if are shift loses higher order bits. - - // note: there is a good argument for following exactly the standards - // language above. Reasonable people can disagree. - + // see 5.8 & 1 + // if right operand is + // greater than or equal to the length in bits of the promoted left operand. if(u > std::numeric_limits::digits - utility::significant_bits(t)){ // behavior is undefined return checked_result( - exception_type::domain_error, + exception_type::undefined_behavior, "shifting more bits than available is undefined behavior" ); } @@ -654,7 +649,7 @@ constexpr checked_left_shift( template typename std::enable_if< - // if E1 has a signed type + // otherwise if E1 has a signed type std::numeric_limits::is_signed, checked_result >::type @@ -662,19 +657,22 @@ constexpr checked_left_shift( const T & t, const U & u ) noexcept { - if(t < 0){ - return checked_result( - exception_type::domain_error, - "shifting a negative value is undefined behavior" + // and [E1] has a non-negative value + if(t >= 0){ + // and E1 x 2^E2 is representable in the corresponding + // unsigned type of the result type, + + // then that value, converted to the result type, + // is the resulting value + return checked_left_shift( + static_cast::type>(t), + u ); } - - // and E1 x 2^E2 is representable in the corresponding - // unsigned type of the result type, - - return checked_left_shift( - static_cast::type>(t), - u + // otherwise, the behavior is undefined. + return checked_result( + exception_type::undefined_behavior, + "shifting a negative value is undefined behavior" ); } @@ -686,17 +684,22 @@ constexpr checked_result left_shift( const U & u ) noexcept { // INT34-C - Do not shift an expression by a negative number of bits - // C++ Standard standard paragraph 5.8.3 Doesn't excactly say this. - // It says the operation is defined as E1 / 2^E2 which IS defined when - // E2 is negative. - // I'm going to err on the side of concervativism dis-allowing negative - // shift counts. + + // standard paragraph 5.8 & 1 + // if the right operand is negative if(u < 0){ return checked_result( - exception_type::domain_error, + exception_type::implementation_defined_behavior, "shifting negative amount is undefined behavior" ); } + if(u > std::numeric_limits::digits){ + // behavior is undefined + return checked_result( + exception_type::implementation_defined_behavior, + "shifting more bits than available is undefined behavior" + ); + } if(t == 0) return cast(t); return detail::checked_left_shift(t, u); @@ -705,6 +708,11 @@ constexpr checked_result left_shift( // right shift namespace detail { +// INT34-C C++ + +// standard paragraph 5.8 / 3 +// The value of E1 << E2 is E1 left-shifted E2 bit positions; +// vacated bits are zero-filled. template typename std::enable_if< // If E1 has an unsigned type @@ -715,6 +723,8 @@ constexpr checked_right_shift( const T & t, const U & u ) noexcept { + // the value of the result is the integral part of the + // quotient of E1/2E2 return cast(t >> u); } @@ -728,13 +738,11 @@ constexpr checked_right_shift( const T & t, const U & u ) noexcept { - // INT13C - Use bitwise operators only on unsigned integers if(t < 0){ // note that the C++ standard considers this case is "implemenation - // defined" rather than "undefined". We'll err on the side of - // caution and disallow this. + // defined" rather than "undefined". return checked_result( - exception_type::domain_error, + exception_type::implementation_defined_behavior, "shifting a negative value is undefined behavior" ); } @@ -752,34 +760,19 @@ constexpr checked_result right_shift( const U & u ) noexcept { // INT34-C - Do not shift an expression by a negative number of bits - // C++ Standard standard paragraph 5.8.3 Doesn't excactly say this. - // It says the operation is defined as E1 / 2^E2 which IS defined when - // E2 is negative. - // I'm going to err on the side of concervativism dis-allowing negative - // shift counts. + + // standard paragraph 5.8 & 1 + // if the right operand is negative if(u < 0){ - // note that the C++ standard considers this case is "implemenation - // defined" rather than "undefined". We'll err on the side of - // caution and dis-allow this. return checked_result( - exception_type::domain_error, - "shifting a negative value is undefined behavior" + exception_type::implementation_defined_behavior, + "shifting negative amount is undefined behavior" ); } - // standard paragraph 5.8 / 3 - // Again, C++ Standard standard paragraph 5.8.3 doesn't seem to disallow - // shifts count > argument width. - - // Also, my Clang compiler traps this an an error when used in a constexpr - // at compile time. - - // Given all of the above, we're going to disallow shifting which exceeds - // the width of the argument. - else if(u > std::numeric_limits::digits){ // behavior is undefined return checked_result( - exception_type::domain_error, + exception_type::implementation_defined_behavior, "shifting more bits than available is undefined behavior" ); } @@ -801,13 +794,6 @@ constexpr checked_result bitwise_or( const U & u ) noexcept { using namespace boost::numeric::utility; - /* - if(! detail::check_bitwise_operand(t)) - return checked_result( - exception_type::domain_error, - "bitwise operands cannot be negative" - ); - */ const unsigned int result_size = std::max(significant_bits(t), significant_bits(u)); @@ -817,17 +803,6 @@ constexpr checked_result bitwise_or( "result type too small to hold bitwise or" }; } - /* - const checked_result rt = cast(t); - if(! rt.no_exception()) - return rt; - - const checked_result ru = cast(u); - if(! ru.no_exception()) - return ru; - - return static_cast(ru) | static_cast(rt); - */ return t | u; } @@ -837,13 +812,6 @@ constexpr checked_result bitwise_xor( const U & u ) noexcept { using namespace boost::numeric::utility; - /* - if(! detail::check_bitwise_operand(t)) - return checked_result( - exception_type::domain_error, - "bitwise operands cannot be negative" - ); - */ const unsigned int result_size = std::max(significant_bits(t), significant_bits(u)); @@ -871,13 +839,6 @@ constexpr checked_result bitwise_and( const U & u ) noexcept { using namespace boost::numeric::utility; - /* - if(! detail::check_bitwise_operand(t)) - return checked_result( - exception_type::domain_error, - "bitwise operands cannot be negative" - ); - */ const unsigned int result_size = std::min(significant_bits(t), significant_bits(u)); @@ -887,17 +848,6 @@ constexpr checked_result bitwise_and( "result type too small to hold bitwise or" }; } - /* - const checked_result rt = cast(t); - if(! rt.no_exception()) - return rt; - - const checked_result ru = cast(u); - if(! ru.no_exception()) - return ru; - - return static_cast(ru) & static_cast(rt); - */ return t & u; } diff --git a/include/checked_result.hpp b/include/checked_result.hpp index 10c43ea..037ecb4 100644 --- a/include/checked_result.hpp +++ b/include/checked_result.hpp @@ -120,11 +120,9 @@ constexpr bool operator!=(const exception_type & lhs, const checked_result &r } template -void +constexpr void dispatch(const checked_result & cr){ - if(cr.no_exception()) - dispatch(exception_type::no_exception, ""); - else + if(cr.exception()) dispatch(cr.m_e, cr.m_msg); } diff --git a/include/exception.hpp b/include/exception.hpp index 0c83d40..e401f75 100644 --- a/include/exception.hpp +++ b/include/exception.hpp @@ -15,6 +15,9 @@ // contains error indicators for results of doing checked // arithmetic on native C++ types +#include +#include + #include "exception_policies.hpp" #include "concept/exception_policy.hpp" @@ -30,35 +33,100 @@ enum class exception_type { underflow_error, range_error, domain_error, + implementation_defined_behavior, + undefined_behavior, uninitialized }; +enum class exception_group { + no_exception, + uninitialized_value, + arithmetic_error, + implementation_defined_behavior, + undefined_behavior +}; + +// translate exception type to exception handler type +constexpr exception_group +group(const exception_type & et){ + // we can't use standard algorithms since we want this to be constexpr + // this brute force solution is simple and pretty fast anyway + switch(et){ + case exception_type::negative_overflow_error: + case exception_type::underflow_error: + case exception_type::range_error: + case exception_type::domain_error: + case exception_type::positive_overflow_error: + return exception_group::arithmetic_error; + case exception_type::undefined_behavior: + return exception_group::undefined_behavior; + case exception_type::implementation_defined_behavior: + return exception_group::implementation_defined_behavior; + case exception_type::uninitialized: + return exception_group::uninitialized_value; + case exception_type::no_exception: + return exception_group::no_exception; + } +} + template -void -dispatch(const exception_type & e, char const * msg){ +constexpr exception_handler +handler(const exception_group & eg){ + // we can't use standard algorithms since we want this to be constexpr + // this brute force solution is simple and pretty fast anyway + switch(eg){ + case exception_group::no_exception: + return exception_handler::ignore_exception; + case exception_group::uninitialized_value: + return EP::on_uninitialized_value(); + case exception_group::arithmetic_error: + return EP::on_arithmetic_error(); + case exception_group::implementation_defined_behavior: + return EP::on_implementation_defined_behavior(); + case exception_group::undefined_behavior: + return EP::on_undefined_behavior(); + default: + assert(false); + } +} + +constexpr void +throw_exception(const exception_type & e, char const * const & msg){ switch(e){ case exception_type::positive_overflow_error: case exception_type::negative_overflow_error: - EP::overflow_error(msg); - break; + throw std::overflow_error(msg); case exception_type::underflow_error: - EP::underflow_error(msg); - break; + throw std::underflow_error(msg); case exception_type::range_error: - EP::range_error(msg); - break; + throw std::range_error(msg); case exception_type::domain_error: - EP::domain_error(msg); - break; + throw std::domain_error(msg); + case exception_type::implementation_defined_behavior: + case exception_type::undefined_behavior: case exception_type::uninitialized: - EP::domain_error(msg); - break; case exception_type::no_exception: - break; default: assert(false); - break; } +}; + +template +constexpr void +dispatch(const exception_type & e, char const * const & msg){ + const exception_group eg = group(e); + const exception_handler eh = handler(eg); + switch(eh){ + case exception_handler::ignore_exception: + return; + case exception_handler::throw_exception: + throw_exception(e, msg); + case exception_handler::trap_exception: + assert(false); + default: + assert(false); + } + } } // numeric diff --git a/include/exception_policies.hpp b/include/exception_policies.hpp index 0cc5df3..72987bd 100644 --- a/include/exception_policies.hpp +++ b/include/exception_policies.hpp @@ -12,91 +12,76 @@ // accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) -#include -#include -#include // is_base_of, is_same #include +#include // is_convertible + +//#include "exception.hpp" namespace boost { namespace numeric { -// run time trap handlers - -// this would emulate the normal C/C++ behavior of permitting overflows -// and the like. -struct ignore_exception { - static void no_error(const char *) {} - static void uninitialized_error(const char *) {} - static void overflow_error(const char *) {} - static void underflow_error(const char *) {} - static void range_error(const char *) {} - static void domain_error(const char *) {} +enum class exception_handler { + ignore_exception, + throw_exception, + trap_exception }; - -// example - if you want to specify specific behavior for particular exception -// types, use this policy. The most likely situation is where you don't have -// exception support and you want to trap "exceptions" by calling your own -// special functions. template< - void (*FUNCTION_NO_EXCEPTION)(const char *), - void (*FUNCTION_UNINITIALIZED)(const char *), - void (*FUNCTION_OVERFLOW)(const char *), - void (*FUNCTION_UNDERFLOW)(const char *), - void (*FUNCTION_RANGE)(const char *), - void (*FUNCTION_DOMAIN)(const char *) + exception_handler UV, + exception_handler AE, + exception_handler IDB, + exception_handler UB > -struct no_exception_support { - static void no_error(const char * message) { - (*FUNCTION_NO_EXCEPTION)(message); +struct exception_policy { + static exception_handler on_uninitialized_value(){ + return UV; } - static void uninitialized_error(const char * message) { - (*FUNCTION_UNINITIALIZED)(message); + static exception_handler on_arithmetic_error(){ + return AE; } - static void overflow_error(const char * message) { - (*FUNCTION_OVERFLOW)(message); + static exception_handler on_implementation_defined_behavior(){ + return IDB; } - static void underflow_error(const char * message) { - (FUNCTION_UNDERFLOW)(message); - } - static void range_error(const char * message) { - FUNCTION_RANGE(message); - } - static void domain_error(const char * message) { - FUNCTION_DOMAIN(message); + static exception_handler on_undefined_behavior(){ + return UB; } }; +// normal policy - permit runtime exceptions +using default_exception_policy = exception_policy< + exception_handler::ignore_exception, + exception_handler::throw_exception, + exception_handler::ignore_exception, + exception_handler::trap_exception +>; -// If an exceptional condition is detected at runtime throw the exception. -// map our exception list to the ones in stdexcept -struct throw_exception { - static void no_error(const char *) { - } - static void unintialized_error(const char * message) { - throw std::invalid_argument(message); - } - static void overflow_error(const char * message) { - throw std::overflow_error(message); - } - static void underflow_error(const char * message) { - throw std::underflow_error(message); - } - static void range_error(const char * message) { - throw std::range_error(message); - } - static void domain_error(const char * message) { - throw std::domain_error(message); - } -}; +// trap non portable C++ code at compile time but permit +// exceptions to be thrown for runtime errors +using strict_exception_policy = exception_policy< + exception_handler::ignore_exception, + exception_handler::throw_exception, + exception_handler::trap_exception, + exception_handler::trap_exception +>; -// use this policy to trap at compile time any operation which -// would otherwise trap at runtime. Hence expressions such as i/j -// will trap at compile time unless j can be guaranteed to not be zero. - -// meant to be trap the case where a program MIGHT throw an exception -struct trap_exception { -}; +// use when any possible exceptions should be trapped at compile time +// but we're a little loose on things like bit shifts etc. +// this might be attractive choice for small embedded systems +using no_exceptions_policy = exception_policy< + exception_handler::ignore_exception, + exception_handler::trap_exception, + exception_handler::ignore_exception, + exception_handler::trap_exception +>; +// use when any possible exceptions should be trapped at compile time +// but we're a little loose on things like bit shifts etc. +// this might be attractive choice for small embedded systems +using strict_no_exceptions_policy = exception_policy< + exception_handler::ignore_exception, + exception_handler::trap_exception, + exception_handler::trap_exception, + exception_handler::trap_exception +>; } // namespace numeric } // namespace boost diff --git a/include/native.hpp b/include/native.hpp index 73af391..619ef87 100644 --- a/include/native.hpp +++ b/include/native.hpp @@ -66,32 +66,10 @@ struct native { struct division_result { using type = multiplicative_operator_type; }; - - // forward to correct divide implementation - template - checked_result - static constexpr divide( - const T & t, - const U & u - ){ - return checked::divide(t, u); - } - template struct modulus_result { using type = multiplicative_operator_type; }; - - // forward to correct modulus implementation - template - checked_result - static constexpr modulus( - const T & t, - const U & u - ){ - return checked::modulus(t, u); - } - template struct left_shift_result { using type = bitwise_shift_operator_type; diff --git a/include/safe_base.hpp b/include/safe_base.hpp index ca8f72f..4d248ec 100644 --- a/include/safe_base.hpp +++ b/include/safe_base.hpp @@ -122,46 +122,12 @@ template< class E // exception policy > class safe_base { -//public: +private: BOOST_CONCEPT_ASSERT((Integer)); BOOST_CONCEPT_ASSERT((PromotionPolicy

)); BOOST_CONCEPT_ASSERT((ExceptionPolicy)); Stored m_t; - template< - class CharT, - class Traits - > - friend std::basic_ostream & operator<<( - std::basic_ostream & os, - const safe_base & t - ){ - return os << ( - (::std::is_same::value - || ::std::is_same::value - || ::std::is_same::value - ) ? - static_cast(t.m_t) - : - t.m_t - ); - }; - - template< - class CharT, - class Traits - > - friend std::basic_istream & operator>>( - std::basic_istream & is, - safe_base & t - ){ - is >> t.m_t; - t.validated_cast(t.m_t); // no need to store result - if(is.fail()) - E::domain_error("error in file input"); - return is; - } - template< class StoredX, StoredX MinX, @@ -180,9 +146,45 @@ class safe_base { constexpr Stored validated_cast( const safe_literal_impl & t ) const; -protected: + + // stream support + + template + void output(std::basic_ostream & os) const; + + // note usage of friend declaration to mark function as + // a global function rather than a member function. If + // this is not done, the compiler will confuse this with + // a member operator overload on the << operator. Weird + // I know. But it's documented here + // http://en.cppreference.com/w/cpp/language/friend + // under the heading "Template friend operators" + template + friend std::basic_ostream & + operator<<( + std::basic_ostream & os, + const safe_base & t + ){ + t.output(os); + return os; + } + + template + void input(std::basic_istream & is); + + // see above + template + friend inline std::basic_istream & + operator>>( + std::basic_istream & is, + safe_base & t + ){ + t.input(is); + return is; + } public: + //////////////////////////////////////////////////////////// // constructors diff --git a/include/safe_base_operations.hpp b/include/safe_base_operations.hpp index 5566b1d..9e237cd 100644 --- a/include/safe_base_operations.hpp +++ b/include/safe_base_operations.hpp @@ -1523,6 +1523,58 @@ constexpr operator^=(T & t, const U & u){ t = static_cast(t ^ u); return t; } + +///////////////////////////////////////////////////////////////// +// stream helpers + +template< + class T, + T Min, + T Max, + class P, // promotion polic + class E // exception policy +> +template< + class CharT, + class Traits +> +void safe_base::output( + std::basic_ostream & os +) const { + os << ( + (std::is_same::value + || std::is_same::value + || std::is_same::value + ) ? + static_cast(m_t) + : + m_t + ); +} +template< + class T, + T Min, + T Max, + class P, // promotion polic + class E // exception policy +> +template< + class CharT, + class Traits +> +void safe_base::input( + std::basic_istream & is +){ + is >> m_t; + validated_cast(m_t); // no need to store result + if(is.fail()){ + boost::numeric::dispatch( + boost::numeric::exception_type::domain_error, + "error in file input" + ); + } +} + } // numeric } // boost diff --git a/include/safe_integer.hpp b/include/safe_integer.hpp index 194de58..3ff7191 100644 --- a/include/safe_integer.hpp +++ b/include/safe_integer.hpp @@ -24,7 +24,7 @@ namespace numeric { template < class T, class P = native, - class E = throw_exception + class E = default_exception_policy > using safe = safe_base< T, diff --git a/include/safe_range.hpp b/include/safe_range.hpp index fbed366..316c92a 100644 --- a/include/safe_range.hpp +++ b/include/safe_range.hpp @@ -33,7 +33,7 @@ template < std::intmax_t Min, std::intmax_t Max, class P = native, - class E = throw_exception + class E = default_exception_policy > using safe_signed_range = safe_base< typename utility::signed_stored_type, @@ -50,7 +50,7 @@ template < std::uintmax_t Min, std::uintmax_t Max, class P = native, - class E = throw_exception + class E = default_exception_policy > using safe_unsigned_range = safe_base< typename utility::unsigned_stored_type, diff --git a/test/test_auto.cpp b/test/test_auto.cpp index e9e4665..fdd29f5 100644 --- a/test/test_auto.cpp +++ b/test/test_auto.cpp @@ -80,7 +80,7 @@ int main(){ safe_signed_range<-3, 8>, safe_signed_range<-4, 9>, automatic, - throw_exception + default_exception_policy >::type x1; test_log(); diff --git a/test/test_range.cpp b/test/test_range.cpp index 5c6fe12..7bb8e32 100644 --- a/test/test_range.cpp +++ b/test/test_range.cpp @@ -48,7 +48,7 @@ using safe_t = boost::numeric::safe_signed_range< Min, Max, boost::numeric::automatic, - boost::numeric::throw_exception + boost::numeric::default_exception_policy >; bool test2(){ diff --git a/test/test_z.cpp b/test/test_z.cpp index fd06aaf..2dba5cf 100644 --- a/test/test_z.cpp +++ b/test/test_z.cpp @@ -191,7 +191,7 @@ template // T is char, int, etc data type using safe_t = safe< T, native, - trap_exception // use for compiling and running tests + no_exceptions_policy // use for compiling and running tests >; template @@ -299,12 +299,12 @@ using namespace boost::numeric; // for safe_literal // create a type for holding small integers. We "know" that C++ type // promotion rules will work such that operations on this type // will never overflow. If change the program to break this, the -// usage of the trap_exception promotion policy will prevent compilation. +// usage of the no_exceptions_policy will prevent compilation. using safe_t = safe_signed_range< -24, 82, native, // C++ type promotion rules work OK for this example - trap_exception // catch problems at compile time + no_exceptions_policy // catch problems at compile time >; int main(int argc, const char * argv[]){ @@ -433,13 +433,13 @@ int main(){ int main(){ using namespace boost::numeric; unsigned char t1 = 1; - constexpr const safe_unsigned_literal<42, automatic, throw_exception> v2; + constexpr const safe_unsigned_literal<42, automatic, default_exception_policy> v2; using result_type = decltype(t1 + v2); static_assert( std::is_same< result_type, - safe_unsigned_range<42, 297, automatic, throw_exception> + safe_unsigned_range<42, 297, automatic, default_exception_policy> >::value, "result type should have a range 42-297" ); @@ -461,14 +461,14 @@ void f2(){ void f3(){ using namespace boost::numeric; - constexpr auto j = safe_signed_literal<0, native, trap_exception>(); + constexpr auto j = safe_signed_literal<0, native, no_exceptions_policy>(); constexpr auto k = safe_signed_literal<3>(); constexpr const safe l = j + k; } void f4(){ using namespace boost::numeric; - safe_signed_literal<0, native, trap_exception> j; + safe_signed_literal<0, native, no_exceptions_policy> j; safe_signed_literal<3> k; constexpr auto l = safe_signed_literal<3>(); constexpr const safe l2 = j + k;