123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758 |
- #if 0
- auto val()
- {
- return -0xFFFFFFFF;
- }
- #include <stdexcept>
- #include <iostream>
- #include <boost/safe_numerics/safe_integer.hpp>
- #include <boost/safe_numerics/safe_integer_literal.hpp>
- void val0(){
- const boost::safe_numerics::safe<unsigned int> x{0};
- std::cout << x << std::endl;
- std::cout << -x << std::endl;
- auto y = -x;
- std::cout << y << std::endl;
- }
- constexpr boost::safe_numerics::safe<unsigned int> val1()
- {
- constexpr boost::safe_numerics::safe<unsigned int> x = 0xFFFFFFFF;
- return -x;
- }
- constexpr boost::safe_numerics::safe<unsigned int> val2()
- {
- boost::safe_numerics::safe<unsigned int> x = - boost::safe_numerics::safe_unsigned_literal<0xFFFFFFFF>();
- return x;
- }
- constexpr boost::safe_numerics::safe<unsigned int> val3()
- {
- return - boost::safe_numerics::safe_unsigned_literal<0xFFFFFFFF>();
- }
- int main(){
- val0();
- std::cout << val1() << std::endl;
- std::cout << val2() << std::endl;
- std::cout << val3() << std::endl;
- return 0;
- }
- // test utility
- #include <boost/safe_numerics/utility.hpp>
- int main(){
- using namespace boost::safe_numerics;
- using x = unsigned_stored_type<0, 42>;
- print_type<x> p1;
- return 0;
- }
- // test automatic type promotion
- #include <boost/safe_numerics/automatic.hpp>
- #include <boost/safe_numerics/safe_integer.hpp>
- #include <type_traits>
- #include <cstdint>
- #include <iostream>
- int main(){
- using namespace boost::safe_numerics;
- using ar = automatic::addition_result<std::uint8_t, std::uint8_t>;
- static_assert(
- std::is_same<ar::type, std::uint16_t>::value,
- "sum of two 8 bit unsigned integers should fit in on 16 bit unsigned integer"
- );
- return 0;
- }
- // test automatic type promotion
- #include <boost/safe_numerics/safe_integer.hpp>
- #include <boost/safe_numerics/safe_integer_range.hpp>
- #include <boost/safe_numerics/safe_integer_literal.hpp>
- #include <boost/safe_numerics/automatic.hpp>
- #include <type_traits>
- #include <cstdint>
- #include <iostream>
- int main(){
- using namespace boost::safe_numerics;
- unsigned char t1 = 1;
- 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, default_exception_policy>
- >::value,
- "result type should have a range 42-297"
- );
- return 0;
- }
- void f1(){
- using namespace boost::safe_numerics;
- constexpr safe<int> j = 0;
- constexpr safe<int> k = 3;
- constexpr safe<int> l = j + k; // compile error
- }
- void f2(){
- using namespace boost::safe_numerics;
- constexpr safe<int> j = boost::safe_numerics::safe_signed_literal<0>();
- constexpr safe<int> k = boost::safe_numerics::safe_signed_literal<3>();
- constexpr safe<int> l = j + k; // compile error
- }
- void f3(){
- using namespace boost::safe_numerics;
- constexpr auto j = safe_signed_literal<0, native, loose_trap_policy>();
- constexpr auto k = safe_signed_literal<3>();
- constexpr const safe<int> l = j + k;
- }
- void f4(){
- using namespace boost::safe_numerics;
- safe_signed_literal<0, native, loose_trap_policy> j;
- safe_signed_literal<3> k;
- constexpr auto l = safe_signed_literal<3>();
- constexpr const safe<int> l2 = j + k;
- }
- #include <boost/safe_numerics/interval.hpp>
- int main(){
- return 0;
- }
- #include <boost/safe_numerics/utility.hpp>
- #include <boost/safe_numerics/cpp.hpp>
- #include <boost/safe_numerics/safe_common.hpp>
- using pic16_promotion = boost::safe_numerics::cpp<
- 8, // char
- 8, // short
- 8, // int
- 16, // long
- 32 // long long
- >;
- #include <type_traits>
- #include <boost/safe_numerics/safe_integer.hpp>
- #include <boost/safe_numerics/range_value.hpp>
- #include <iostream>
- int main(){
- using namespace boost::safe_numerics;
- static_assert(
- std::is_literal_type<safe<int>>::value,
- "safe type is a literal type"
- );
- static_assert(
- std::is_literal_type<interval<int>>::value,
- "interval type is a literal type"
- );
- static_assert(
- std::is_literal_type<interval<
- safe<int>
- >>::value,
- "interval of safe types is a literal type"
- );
- static_assert(
- std::is_literal_type<range_value<
- safe<int>
- >>::value,
- "range_value of safe types is a literal type"
- );
- safe<int> x = 42;
- std::cout << make_range_value(x);
- return 0;
- }
- auto val()
- {
- return -0xFFFFFFFF;
- }
- #include <stdexcept>
- #include <iostream>
- #include <boost/safe_numerics/safe_integer.hpp>
- #include <boost/safe_numerics/safe_integer_literal.hpp>
- void val0(){
- const boost::safe_numerics::safe<unsigned int> x{0};
- std::cout << x << std::endl;
- std::cout << -x << std::endl;
- auto y = -x;
- std::cout << y << std::endl;
- }
- constexpr boost::safe_numerics::safe<unsigned int> val1(){
- constexpr boost::safe_numerics::safe<unsigned int> x = 0xFFFFFFFF;
- return -x;
- }
- constexpr boost::safe_numerics::safe<unsigned int> val2(){
- const boost::safe_numerics::safe<unsigned int> x
- = -boost::safe_numerics::safe_unsigned_literal<0xFFFFFFFF>();
- return x;
- }
- constexpr boost::safe_numerics::safe<unsigned int> val3(){
- return - boost::safe_numerics::safe_unsigned_literal<0xFFFFFFFF>();
- }
- int main(){
- val0();
- std::cout << val1() << std::endl;
- std::cout << val2() << std::endl;
- std::cout << val3() << std::endl;
- return 0;
- }
- #include <boost/logic/tribool.hpp>
- #include <boost/safe_integer/checked_integer.hpp>
- #include <boost/safe_integer/checked_result.hpp>
- #include <boost/safe_integer/checked_result_operations.hpp>
- #include <boost/safe_integer/interval.hpp>
- namespace boost {
- namespace safe_numerics {
- template<class EP, typename R>
- constexpr void
- dispatch(const checked_result<R> & cr){
- }
- template<class T>
- constexpr T base_value(const T & t){
- return t;
- }
- template<typename R, R Min, R Max, typename T, typename E>
- struct validate_detail {
- constexpr static const interval<checked_result<R>> t_interval{
- checked::cast<R>(base_value(std::numeric_limits<T>::min())),
- checked::cast<R>(base_value(std::numeric_limits<T>::max()))
- };
- constexpr static const interval<checked_result<R>> r_interval{Min, Max};
- /*
- static_assert(
- ! static_cast<bool>(r_interval.excludes(t_interval)),
- "ranges don't overlap: can't cast"
- );
- */
- struct exception_possible {
- constexpr static R return_value(
- const T & t
- ){
- static_assert(
- ! static_cast<bool>(r_interval.includes(t_interval)),
- "exeption not possible"
- );
- // INT08-C
- const checked_result<R> r = checked::cast<R>(t);
- dispatch<E>(r);
- return base_value(r);
- }
- };
- struct exception_not_possible {
- constexpr static R return_value(
- const T & t
- ){
- static_assert(
- static_cast<bool>(r_interval.includes(t_interval)),
- "exeption not possible"
- );
- return static_cast<R>(t);
- }
- };
- static R return_value(const T & t){
- return std::conditional<
- static_cast<bool>(r_interval.includes(t_interval)),
- exception_not_possible,
- exception_possible
- >::type::return_value(t);
- }
- };
- template<typename R, R Min, R Max, typename T>
- bool test1(const T & t){
- const interval<checked_result<R>> t_interval{
- checked::cast<R>(base_value(std::numeric_limits<T>::min())),
- checked::cast<R>(base_value(std::numeric_limits<T>::max()))
- };
- const interval<checked_result<R>> r_interval{Min, Max};
- /*
- static_assert(
- ! static_cast<bool>(r_interval.excludes(t_interval)),
- "ranges don't overlap: can't cast"
- );
- */
- const boost::logic::tribool tb1 = r_interval.includes(t_interval);
- const bool x1 = tb1;
- const boost::logic::tribool tb2 = r_interval.excludes(t_interval);
- const bool x2 = tb2;
- return x2;
- }
- } // safe_numerics
- } // boost
- int main(){
- unsigned int x1 = boost::safe_numerics::test1<
- unsigned int, 0, 100, signed char
- >(-1);
- bool x2 = boost::safe_numerics::validate_detail<
- unsigned int, 0, 100, signed char, void
- >::return_value(-1);
- return 0;
- }
- using uint8_t = unsigned char;
- enum class safe_numerics_error : uint8_t {
- success = 0,
- failure, // result is above representational maximum
- error_count
- };
- template<typename R>
- struct checked_result {
- const safe_numerics_error m_e;
- const union {
- const R m_r;
- char const * const m_msg;
- };
- constexpr /*explicit*/ checked_result(const R & r) :
- m_e(safe_numerics_error::success),
- m_r(r)
- {}
- constexpr /*explicit*/ checked_result(const safe_numerics_error & e) :
- m_e(e),
- m_msg("")
- {}
- };
- // integers addition
- template<class T>
- constexpr inline checked_result<T> operator+(
- const checked_result<T> & t,
- const checked_result<T> & u
- ){
- #if 1 // compile fails
- constexpr const safe_numerics_error x[2][2]{
- // t == success
- {
- // u == ...
- safe_numerics_error::success,
- safe_numerics_error::failure
- },
- // t == positive_overflow_error,
- {
- // u == ...
- safe_numerics_error::success,
- safe_numerics_error::failure
- }
- };
- // "Constexpr variable 'e' must be initialized by a constant expression"
- constexpr const safe_numerics_error e = x
- [static_cast<uint8_t>(t.m_e)]
- [static_cast<uint8_t>(u.m_e)]
- ;
- return
- safe_numerics_error::success == e
- ? t.m_r + u.m_r
- : checked_result<T>(e)
- ;
- #else // works as expected
- constexpr const safe_numerics_error x[2][2]{
- // t == success
- {
- // u == ...
- safe_numerics_error::success,
- safe_numerics_error::failure
- },
- // t == failure,
- {
- // u == ...
- safe_numerics_error::failure,
- safe_numerics_error::failure
- }
- };
- return
- safe_numerics_error::success == x
- [static_cast<uint8_t>(t.m_e)]
- [static_cast<uint8_t>(u.m_e)]
- ? t.m_r + u.m_r
- : checked_result<T>(x
- [static_cast<uint8_t>(t.m_e)]
- [static_cast<uint8_t>(u.m_e)]
- )
- ;
- #endif
- }
- int main(){
- constexpr const checked_result<unsigned> i = 0;
- constexpr const checked_result<unsigned> j = 0;
- constexpr const checked_result<unsigned> k = i + j;
- // return k.m_r;
- constexpr const checked_result<unsigned> i2 = safe_numerics_error::failure;
- constexpr const checked_result<unsigned> j2 = 0;
- constexpr const checked_result<unsigned> k2 = i2 + j2;
- return k2.m_r;
- }
- #endif
- #if 0
- using uint8_t = unsigned char;
- #if 1
- enum class safe_numerics_error : uint8_t {
- success = 0,
- failure, // result is above representational maximum
- error_count
- };
- #else
- // avoiding enum class fails to solve problem
- struct safe_numerics_error {
- const uint8_t m_t;
- constexpr const static uint8_t success = 0;
- constexpr const static uint8_t failure = 1;
- constexpr safe_numerics_error(uint8_t t) :
- m_t(t)
- {}
- constexpr operator uint8_t () const {
- return m_t;
- }
- };
- #endif
- template<typename R>
- struct checked_result {
- const safe_numerics_error m_e;
- const union {
- const R m_r;
- char const * const m_msg;
- };
- constexpr /*explicit*/ checked_result(const R & r) :
- m_e(safe_numerics_error::success),
- m_r(r)
- {}
- constexpr /*explicit*/ checked_result(const safe_numerics_error & e) :
- m_e(e),
- m_msg("")
- {}
- };
- // integers addition
- template<class T>
- constexpr inline checked_result<T> operator+(
- const checked_result<T> & t,
- const checked_result<T> & u
- ){
- // "Constexpr variable 'e' must be initialized by a constant expression"
- constexpr const safe_numerics_error x[2][2]{
- // t == success
- {
- // u == ...
- safe_numerics_error::success,
- safe_numerics_error::failure
- },
- // t == positive_overflow_error,
- {
- // u == ...
- safe_numerics_error::failure,
- safe_numerics_error::failure
- }
- };
- #if 1 // compile fails
- const safe_numerics_error e = x
- [static_cast<uint8_t>(t.m_e)]
- [static_cast<uint8_t>(u.m_e)]
- ;
- return
- (safe_numerics_error::success == e)
- ? t.m_r + u.m_r
- : checked_result<T>(e)
- ;
- #else // works as expected
- return
- safe_numerics_error::success == x
- [static_cast<uint8_t>(t.m_e)]
- [static_cast<uint8_t>(u.m_e)]
- ? t.m_r + u.m_r
- : checked_result<T>(x
- [static_cast<uint8_t>(t.m_e)]
- [static_cast<uint8_t>(u.m_e)]
- )
- ;
- #endif
- }
- int main(){
- constexpr const checked_result<unsigned> i = 0;
- constexpr const checked_result<unsigned> j = 0;
- //constexpr const checked_result<unsigned> k = i + j;
- // return k.m_r;
- constexpr const checked_result<unsigned> i2 = safe_numerics_error::failure;
- constexpr const checked_result<unsigned> j2 = 0;
- constexpr const checked_result<unsigned> k2 = i2 + j2;
- return 0;
- }
- #endif
- #if 0
- //#include "safe_common.hpp>
- //#include "checked_result.hpp>
- //#include "checked_default.hpp>
- #include <cassert>
- #include <boost/logic/tribool.hpp>
- #include <iostream>
- // note: Don't reorder these. Code in the file checked_result_operations.hpp
- // depends upon this order !!!
- enum class safe_numerics_error : std::uint8_t {
- success = 0,
- positive_overflow_error, // result is above representational maximum
- negative_overflow_error, // result is below representational minimum
- domain_error, // one operand is out of valid range
- range_error, // result cannot be produced for this operation
- precision_overflow_error, // result lost precision
- underflow_error, // result is too small to be represented
- negative_value_shift, // negative value in shift operator
- negative_shift, // shift a negative value
- shift_too_large, // l/r shift exceeds variable size
- uninitialized_value // l/r shift exceeds variable size
- };
- // checked result is an "extended version" of the type R. That is it's domain is
- // the domain of R U possible other values which might result from arithmetic
- // operations. An example of such a value would be safe_error::positive_overflow_error.
- template<typename R>
- struct checked_result {
- const safe_numerics_error m_e;
- const union {
- R m_r;
- char const * m_msg;
- };
-
- constexpr /*explicit*/ checked_result(const R & r) :
- m_e(safe_numerics_error::success),
- m_r(r)
- {}
- constexpr /*explicit*/ checked_result(
- safe_numerics_error e,
- const char * msg = ""
- ) :
- m_e(e),
- m_msg(msg)
- {
- assert(m_e != safe_numerics_error::success);
- }
- constexpr bool exception() const {
- return m_e != safe_numerics_error::success;
- }
- // don't permit construction without initial value;
- checked_result() = delete;
- // disallow assignment
- checked_result & operator=(const checked_result &) = delete;
- };
- // all arithmetic operations of type T are supported on checked_result<T>.
- // but the results might surprising. For example
- constexpr signed int test_constexpr(
- const checked_result<signed int> & t,
- const checked_result<signed int> & u
- ){
- const boost::logic::tribool tb2 = t < u;
- const signed int x = (tb2) ? 2 : 3;
- return x;
- }
- using namespace boost::safe_numerics;
- int main()
- {
- constexpr const checked_result<signed int> po = safe_numerics_error::positive_overflow_error;
- constexpr const checked_result<signed int> no = safe_numerics_error::negative_overflow_error;
- constexpr const boost::logic::tribool tb = no < po;
- const boost::logic::tribool tb1 = no > po;
- constexpr const checked_result<signed int> re = safe_numerics_error::range_error;
- const boost::logic::tribool tb2 = no < re;
- const checked_result<signed int> x = no < re ? no : re;
- static_assert(test_constexpr(no, re) == 3, "test_constexpr(no, re)");
- static_assert(tb, "no < po");
- signed int result;
- if(tb)
- result = 0;
- else
- result = 1;
- std::cout << result;
- return result;
- }
- #endif
- #if 0
- #include <boost/logic/tribool.hpp>
- #include <cassert>
- int main(){
- constexpr const boost::tribool tb_t{true};
- static_assert(tb_t, "tb_t");
- assert(static_cast<bool>(tb_t));
- constexpr boost::tribool tb_f{false};
- static_assert(! tb_f, "tb_f");
- assert(! static_cast<bool>(tb_f));
- return 0;
- }
- #endif
- #if 0
- #include <boost/integer.hpp>
- #include <boost/safe_numerics/utility.hpp>
- // include headers to support safe integers
- #include <boost/safe_numerics/cpp.hpp>
- //#include <boost/safe_numerics/exception.hpp>
- using promotion_policy = boost::safe_numerics::cpp<
- 8, // char 8 bits
- 16, // short 16 bits
- 16, // int 16 bits
- 16, // long 32 bits
- 32 // long long 32 bits
- >;
- template<typename R, typename T, typename U>
- struct test {
- using ResultType = promotion_policy::result_type<T,U>;
- //boost::safe_numerics::utility::print_type<ResultType> pt;
- static_assert(
- std::is_same<R, ResultType>::value,
- "is_same<R, ResultType>"
- );
- };
- test<std::uint16_t, std::uint8_t, std::uint8_t> t1;
- int main(){
- return 0;
- }
- #endif
- #if 0
- #include <string>
- #include <unordered_map>
- #include <boost/safe_numerics/safe_integer.hpp>
- #include <functional> // hash
- template<typename T>
- struct safe_hash {
- size_t operator()(boost::safe_numerics::safe<T> const& t) const {
- return std::hash<T>()(t);
- }
- };
- int main(){
- auto foo = std::unordered_map<
- boost::safe_numerics::safe<int>,
- std::string,
- safe_hash<int>
- >{};
- foo[boost::safe_numerics::safe<int>(42)] = "hello, world!";
- foo[42] = "hello, world!";
- }
- #endif
- #if 0
- #include <string>
- #include <unordered_map>
- #include <boost/safe_numerics/safe_integer.hpp>
- #include <functional> // hash
- template<typename T>
- struct safe_hash {
- size_t operator()(boost::safe_numerics::safe<T> const& t) const {
- return std::hash<T>()(t);
- }
- };
- int main(){
- auto foo = std::unordered_map<int, std::string>{};
- foo[boost::safe_numerics::safe<int>(42)] = "hello, world!";
- }
- #endif
- #if 0
- #include <iostream>
- #include <boost/safe_numerics/safe_integer.hpp>
- #include <boost/safe_numerics/automatic.hpp>
- using namespace boost::safe_numerics;
- int main(){
- using safe_int = safe<
- int,
- automatic,
- loose_trap_policy
- >;
- safe_int i;
- std::cin >> i; // might throw exception
- auto j = i * i;
- // won't ever trap
- // result type can hold the maximum value of i * i
- static_assert(is_safe<decltype(j)>::value, "result is a safe type");
- static_assert(
- std::numeric_limits<decltype(i * i)>::max() >=
- std::numeric_limits<safe_int>::max() * std::numeric_limits<safe_int>::max(),
- "result can never overflow"
- ); // always true
- return 0;
- }
- #endif
- int main(){}
|