]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/safe_numerics/test/test_z.cpp
10 #include <boost/safe_numerics/safe_integer.hpp>
11 #include <boost/safe_numerics/safe_integer_literal.hpp>
14 const boost::safe_numerics::safe
<unsigned int> x
{0};
15 std::cout
<< x
<< std::endl
;
16 std::cout
<< -x
<< std::endl
;
18 std::cout
<< y
<< std::endl
;
21 constexpr boost::safe_numerics::safe
<unsigned int> val1()
23 constexpr boost::safe_numerics::safe
<unsigned int> x
= 0xFFFFFFFF;
26 constexpr boost::safe_numerics::safe
<unsigned int> val2()
28 boost::safe_numerics::safe
<unsigned int> x
= - boost::safe_numerics::safe_unsigned_literal
<0xFFFFFFFF>();
32 constexpr boost::safe_numerics::safe
<unsigned int> val3()
34 return - boost::safe_numerics::safe_unsigned_literal
<0xFFFFFFFF>();
39 std::cout
<< val1() << std::endl
;
40 std::cout
<< val2() << std::endl
;
41 std::cout
<< val3() << std::endl
;
46 #include <boost/safe_numerics/utility.hpp>
49 using namespace boost::safe_numerics
;
50 using x
= unsigned_stored_type
<0, 42>;
56 // test automatic type promotion
57 #include <boost/safe_numerics/automatic.hpp>
58 #include <boost/safe_numerics/safe_integer.hpp>
59 #include <type_traits>
64 using namespace boost::safe_numerics
;
65 using ar
= automatic::addition_result
<std::uint8_t, std::uint8_t>;
67 std::is_same
<ar::type
, std::uint16_t>::value
,
68 "sum of two 8 bit unsigned integers should fit in on 16 bit unsigned integer"
74 // test automatic type promotion
75 #include <boost/safe_numerics/safe_integer.hpp>
76 #include <boost/safe_numerics/safe_integer_range.hpp>
77 #include <boost/safe_numerics/safe_integer_literal.hpp>
78 #include <boost/safe_numerics/automatic.hpp>
79 #include <type_traits>
84 using namespace boost::safe_numerics
;
86 constexpr const safe_unsigned_literal
<42, automatic
, default_exception_policy
> v2
;
87 using result_type
= decltype(t1
+ v2
);
92 safe_unsigned_range
<42, 297, automatic
, default_exception_policy
>
94 "result type should have a range 42-297"
99 using namespace boost::safe_numerics
;
100 constexpr safe
<int> j
= 0;
101 constexpr safe
<int> k
= 3;
102 constexpr safe
<int> l
= j
+ k
; // compile error
106 using namespace boost::safe_numerics
;
107 constexpr safe
<int> j
= boost::safe_numerics::safe_signed_literal
<0>();
108 constexpr safe
<int> k
= boost::safe_numerics::safe_signed_literal
<3>();
109 constexpr safe
<int> l
= j
+ k
; // compile error
113 using namespace boost::safe_numerics
;
114 constexpr auto j
= safe_signed_literal
<0, native
, loose_trap_policy
>();
115 constexpr auto k
= safe_signed_literal
<3>();
116 constexpr const safe
<int> l
= j
+ k
;
120 using namespace boost::safe_numerics
;
121 safe_signed_literal
<0, native
, loose_trap_policy
> j
;
122 safe_signed_literal
<3> k
;
123 constexpr auto l
= safe_signed_literal
<3>();
124 constexpr const safe
<int> l2
= j
+ k
;
127 #include <boost/safe_numerics/interval.hpp>
133 #include <boost/safe_numerics/utility.hpp>
134 #include <boost/safe_numerics/cpp.hpp>
135 #include <boost/safe_numerics/safe_common.hpp>
137 using pic16_promotion
= boost::safe_numerics::cpp
<
145 #include <type_traits>
146 #include <boost/safe_numerics/safe_integer.hpp>
147 #include <boost/safe_numerics/range_value.hpp>
151 using namespace boost::safe_numerics
;
153 std::is_literal_type
<safe
<int>>::value
,
154 "safe type is a literal type"
157 std::is_literal_type
<interval
<int>>::value
,
158 "interval type is a literal type"
161 std::is_literal_type
<interval
<
164 "interval of safe types is a literal type"
167 std::is_literal_type
<range_value
<
170 "range_value of safe types is a literal type"
173 std::cout
<< make_range_value(x
);
184 #include <boost/safe_numerics/safe_integer.hpp>
185 #include <boost/safe_numerics/safe_integer_literal.hpp>
188 const boost::safe_numerics::safe
<unsigned int> x
{0};
189 std::cout
<< x
<< std::endl
;
190 std::cout
<< -x
<< std::endl
;
192 std::cout
<< y
<< std::endl
;
195 constexpr boost::safe_numerics::safe
<unsigned int> val1(){
196 constexpr boost::safe_numerics::safe
<unsigned int> x
= 0xFFFFFFFF;
199 constexpr boost::safe_numerics::safe
<unsigned int> val2(){
200 const boost::safe_numerics::safe
<unsigned int> x
201 = -boost::safe_numerics::safe_unsigned_literal
<0xFFFFFFFF>();
204 constexpr boost::safe_numerics::safe
<unsigned int> val3(){
205 return - boost::safe_numerics::safe_unsigned_literal
<0xFFFFFFFF>();
210 std::cout
<< val1() << std::endl
;
211 std::cout
<< val2() << std::endl
;
212 std::cout
<< val3() << std::endl
;
216 #include <boost/logic/tribool.hpp>
217 #include <boost/safe_integer/checked_integer.hpp>
218 #include <boost/safe_integer/checked_result.hpp>
219 #include <boost/safe_integer/checked_result_operations.hpp>
220 #include <boost/safe_integer/interval.hpp>
223 namespace safe_numerics
{
225 template<class EP
, typename R
>
227 dispatch(const checked_result
<R
> & cr
){
231 constexpr T
base_value(const T
& t
){
235 template<typename R
, R Min
, R Max
, typename E
>
236 struct validate_detail
{
238 constexpr static const interval
<checked_result
<R
>> t_interval
{
239 checked::cast
<R
>(base_value(std::numeric_limits
<T
>::min())),
240 checked::cast
<R
>(base_value(std::numeric_limits
<T
>::max()))
242 constexpr static const interval
<checked_result
<R
>> r_interval
{Min
, Max
};
246 ! static_cast<bool>(r_interval.excludes(t_interval)),
247 "ranges don't overlap: can't cast"
251 struct exception_possible
{
252 constexpr static R
return_value(
256 ! static_cast<bool>(r_interval
.includes(t_interval
)),
257 "exeption not possible"
260 const checked_result
<R
> r
= checked::cast
<R
>(t
);
262 return base_value(r
);
265 struct exception_not_possible
{
266 constexpr static R
return_value(
270 static_cast<bool>(r_interval
.includes(t_interval
)),
271 "exeption not possible"
273 return static_cast<R
>(t
);
277 static R
return_value(const T
& t
){
278 return std::conditional
<
279 static_cast<bool>(r_interval
.includes(t_interval
)),
280 exception_not_possible
,
282 >::type::return_value(t
);
286 template<typename R
, R Min
, R Max
, typename T
>
287 bool test1(const T
& t
){
288 const interval
<checked_result
<R
>> t_interval
{
289 checked::cast
<R
>(base_value(std::numeric_limits
<T
>::min())),
290 checked::cast
<R
>(base_value(std::numeric_limits
<T
>::max()))
292 const interval
<checked_result
<R
>> r_interval
{Min
, Max
};
296 ! static_cast<bool>(r_interval.excludes(t_interval)),
297 "ranges don't overlap: can't cast"
300 const boost::logic::tribool tb1
= r_interval
.includes(t_interval
);
303 const boost::logic::tribool tb2
= r_interval
.excludes(t_interval
);
313 unsigned int x1
= boost::safe_numerics::test1
<
314 unsigned int, 0, 100, signed char
316 bool x2
= boost::safe_numerics::validate_detail
<
317 unsigned int, 0, 100, signed char, void
322 using uint8_t = unsigned char;
324 enum class safe_numerics_error
: uint8_t {
326 failure
, // result is above representational maximum
331 struct checked_result
{
332 const safe_numerics_error m_e
;
335 char const * const m_msg
;
337 constexpr /*explicit*/ checked_result(const R
& r
) :
338 m_e(safe_numerics_error::success
),
341 constexpr /*explicit*/ checked_result(const safe_numerics_error
& e
) :
349 constexpr inline checked_result
<T
> operator+(
350 const checked_result
<T
> & t
,
351 const checked_result
<T
> & u
353 #if 1 // compile fails
354 constexpr const safe_numerics_error x
[2][2]{
358 safe_numerics_error::success
,
359 safe_numerics_error::failure
361 // t == positive_overflow_error,
364 safe_numerics_error::success
,
365 safe_numerics_error::failure
369 // "Constexpr variable 'e' must be initialized by a constant expression"
370 constexpr const safe_numerics_error e
= x
371 [static_cast<uint8_t>(t
.m_e
)]
372 [static_cast<uint8_t>(u
.m_e
)]
376 safe_numerics_error::success
== e
378 : checked_result
<T
>(e
)
380 #else // works as expected
381 constexpr const safe_numerics_error x
[2][2]{
385 safe_numerics_error::success
,
386 safe_numerics_error::failure
391 safe_numerics_error::failure
,
392 safe_numerics_error::failure
397 safe_numerics_error::success
== x
398 [static_cast<uint8_t>(t
.m_e
)]
399 [static_cast<uint8_t>(u
.m_e
)]
401 : checked_result
<T
>(x
402 [static_cast<uint8_t>(t
.m_e
)]
403 [static_cast<uint8_t>(u
.m_e
)]
410 constexpr const checked_result
<unsigned> i
= 0;
411 constexpr const checked_result
<unsigned> j
= 0;
413 constexpr const checked_result
<unsigned> k
= i
+ j
;
417 constexpr const checked_result
<unsigned> i2
= safe_numerics_error::failure
;
418 constexpr const checked_result
<unsigned> j2
= 0;
420 constexpr const checked_result
<unsigned> k2
= i2
+ j2
;
426 using uint8_t = unsigned char;
430 enum class safe_numerics_error
: uint8_t {
432 failure
, // result is above representational maximum
436 // avoiding enum class fails to solve problem
437 struct safe_numerics_error
{
439 constexpr const static uint8_t success
= 0;
440 constexpr const static uint8_t failure
= 1;
441 constexpr safe_numerics_error(uint8_t t
) :
444 constexpr operator uint8_t () const {
451 struct checked_result
{
452 const safe_numerics_error m_e
;
455 char const * const m_msg
;
457 constexpr /*explicit*/ checked_result(const R
& r
) :
458 m_e(safe_numerics_error::success
),
461 constexpr /*explicit*/ checked_result(const safe_numerics_error
& e
) :
469 constexpr inline checked_result
<T
> operator+(
470 const checked_result
<T
> & t
,
471 const checked_result
<T
> & u
473 // "Constexpr variable 'e' must be initialized by a constant expression"
474 constexpr const safe_numerics_error x
[2][2]{
478 safe_numerics_error::success
,
479 safe_numerics_error::failure
481 // t == positive_overflow_error,
484 safe_numerics_error::failure
,
485 safe_numerics_error::failure
489 #if 1 // compile fails
490 const safe_numerics_error e
= x
491 [static_cast<uint8_t>(t
.m_e
)]
492 [static_cast<uint8_t>(u
.m_e
)]
496 (safe_numerics_error::success
== e
)
498 : checked_result
<T
>(e
)
500 #else // works as expected
502 safe_numerics_error::success
== x
503 [static_cast<uint8_t>(t
.m_e
)]
504 [static_cast<uint8_t>(u
.m_e
)]
506 : checked_result
<T
>(x
507 [static_cast<uint8_t>(t
.m_e
)]
508 [static_cast<uint8_t>(u
.m_e
)]
515 constexpr const checked_result
<unsigned> i
= 0;
516 constexpr const checked_result
<unsigned> j
= 0;
518 //constexpr const checked_result<unsigned> k = i + j;
521 constexpr const checked_result
<unsigned> i2
= safe_numerics_error::failure
;
522 constexpr const checked_result
<unsigned> j2
= 0;
524 constexpr const checked_result
<unsigned> k2
= i2
+ j2
;
531 //#include "safe_common.hpp>
532 //#include "checked_result.hpp>
533 //#include "checked_default.hpp>
535 #include <boost/logic/tribool.hpp>
539 // note: Don't reorder these. Code in the file checked_result_operations.hpp
540 // depends upon this order !!!
541 enum class safe_numerics_error
: std::uint8_t {
543 positive_overflow_error
, // result is above representational maximum
544 negative_overflow_error
, // result is below representational minimum
545 domain_error
, // one operand is out of valid range
546 range_error
, // result cannot be produced for this operation
547 precision_overflow_error
, // result lost precision
548 underflow_error
, // result is too small to be represented
549 negative_value_shift
, // negative value in shift operator
550 negative_shift
, // shift a negative value
551 shift_too_large
, // l/r shift exceeds variable size
552 uninitialized_value
// l/r shift exceeds variable size
555 // checked result is an "extended version" of the type R. That is it's domain is
556 // the domain of R U possible other values which might result from arithmetic
557 // operations. An example of such a value would be safe_error::positive_overflow_error.
559 struct checked_result
{
560 const safe_numerics_error m_e
;
566 constexpr /*explicit*/ checked_result(const R
& r
) :
567 m_e(safe_numerics_error::success
),
570 constexpr /*explicit*/ checked_result(
571 safe_numerics_error e
,
572 const char * msg
= ""
577 assert(m_e
!= safe_numerics_error::success
);
579 constexpr bool exception() const {
580 return m_e
!= safe_numerics_error::success
;
583 // don't permit construction without initial value;
584 checked_result() = delete;
586 // disallow assignment
587 checked_result
& operator=(const checked_result
&) = delete;
590 // all arithmetic operations of type T are supported on checked_result<T>.
591 // but the results might surprising. For example
594 constexpr signed int test_constexpr(
595 const checked_result
<signed int> & t
,
596 const checked_result
<signed int> & u
598 const boost::logic::tribool tb2
= t
< u
;
599 const signed int x
= (tb2
) ? 2 : 3;
603 using namespace boost::safe_numerics
;
607 constexpr const checked_result
<signed int> po
= safe_numerics_error::positive_overflow_error
;
608 constexpr const checked_result
<signed int> no
= safe_numerics_error::negative_overflow_error
;
609 constexpr const boost::logic::tribool tb
= no
< po
;
610 const boost::logic::tribool tb1
= no
> po
;
611 constexpr const checked_result
<signed int> re
= safe_numerics_error::range_error
;
612 const boost::logic::tribool tb2
= no
< re
;
613 const checked_result
<signed int> x
= no
< re
? no
: re
;
615 static_assert(test_constexpr(no
, re
) == 3, "test_constexpr(no, re)");
618 static_assert(tb
, "no < po");
633 #include <boost/logic/tribool.hpp>
636 constexpr const boost::tribool tb_t
{true};
637 static_assert(tb_t
, "tb_t");
638 assert(static_cast<bool>(tb_t
));
639 constexpr boost::tribool tb_f
{false};
640 static_assert(! tb_f
, "tb_f");
641 assert(! static_cast<bool>(tb_f
));
647 #include <boost/integer.hpp>
648 #include <boost/safe_numerics/utility.hpp>
650 // include headers to support safe integers
651 #include <boost/safe_numerics/cpp.hpp>
652 //#include <boost/safe_numerics/exception.hpp>
654 using promotion_policy
= boost::safe_numerics::cpp
<
659 32 // long long 32 bits
662 template<typename R
, typename T
, typename U
>
664 using ResultType
= promotion_policy::result_type
<T
,U
>;
665 //boost::safe_numerics::utility::print_type<ResultType> pt;
667 std::is_same
<R
, ResultType
>::value
,
668 "is_same<R, ResultType>"
672 test
<std::uint16_t, std::uint8_t, std::uint8_t> t1
;
682 #include <unordered_map>
683 #include <boost/safe_numerics/safe_integer.hpp>
685 #include <functional> // hash
689 size_t operator()(boost::safe_numerics::safe
<T
> const& t
) const {
690 return std::hash
<T
>()(t
);
695 auto foo
= std::unordered_map
<
696 boost::safe_numerics::safe
<int>,
700 foo
[boost::safe_numerics::safe
<int>(42)] = "hello, world!";
701 foo
[42] = "hello, world!";
709 #include <unordered_map>
710 #include <boost/safe_numerics/safe_integer.hpp>
712 #include <functional> // hash
716 size_t operator()(boost::safe_numerics::safe
<T
> const& t
) const {
717 return std::hash
<T
>()(t
);
722 auto foo
= std::unordered_map
<int, std::string
>{};
723 foo
[boost::safe_numerics::safe
<int>(42)] = "hello, world!";
731 #include <boost/safe_numerics/safe_integer.hpp>
732 //#include <boost/safe_numerics/automatic.hpp>
734 using namespace boost::safe_numerics
;
737 using safe_int
= safe
<
743 std::cin
>> i
; // might throw exception
746 // result type can hold the maximum value of i * i
747 static_assert(is_safe
<decltype(j
)>::value
, "result is a safe type");
749 std::numeric_limits
<decltype(i
* i
)>::max() >=
750 std::numeric_limits
<safe_int
>::max() * std::numeric_limits
<safe_int
>::max(),
751 "result can never overflow"
758 #include <boost/safe_numerics/safe_integer_range.hpp>
759 #include <boost/safe_numerics/safe_integer_literal.hpp>
761 template <uintmax_t Min
, uintmax_t Max
>
762 using urange
= boost::safe_numerics::safe_unsigned_range
<
765 boost::safe_numerics::native
,
766 boost::safe_numerics::strict_trap_policy
769 template <uintmax_t N
>
770 using ulit
= boost::safe_numerics::safe_unsigned_literal
<
772 boost::safe_numerics::native
,
773 boost::safe_numerics::strict_trap_policy
777 urange
<0,4095> x
= ulit
<0>(); // 12 bits
778 urange
<0, 69615> y
= x
* ulit
<17>(); // no error - resulting value
779 // cannot exceed 69615
780 auto z
= y
/ ulit
<17>() ; //Boom, compile-time error
787 #include <boost/safe_numerics/safe_integer_range.hpp>
790 using namespace boost::safe_numerics
;
791 safe_unsigned_range
<0, 36> a
= 30;
799 #include <functional>
800 #include <boost/safe_numerics/safe_integer_range.hpp>
801 #include <boost/safe_numerics/interval.hpp> // print variable range
802 #include <boost/safe_numerics/native.hpp> // native promotion policy
803 #include <boost/safe_numerics/exception.hpp> // safe_numerics_error
804 #include <boost/safe_numerics/exception_policies.hpp>
806 // log an exception condition but continue processing as though nothing has happened
807 // this would emulate the behavior of an unsafe type.
808 struct log_runtime_exception
{
809 log_runtime_exception() = default;
811 const boost::safe_numerics::safe_numerics_error
& e
,
815 << "Caught system_error with code "
816 << boost::safe_numerics::literal_string(e
)
817 << " and message " << message
<< '\n';
822 // log arithmetic errors but ignore them and continue to execute
823 // implementation defined and undefined behavior is just executed
826 using logging_exception_policy
= boost::safe_numerics::exception_policy
<
827 log_runtime_exception
, // arithmetic error
828 log_runtime_exception
, // implementation defined behavior
829 log_runtime_exception
, // undefined behavior
830 log_runtime_exception
// uninitialized value
833 template<unsigned int Min
, unsigned int Max
>
834 using sur
= boost::safe_numerics::safe_unsigned_range
<
835 Min
, // min value in range
836 Max
, // max value in range
837 boost::safe_numerics::native
, // promotion policy
838 logging_exception_policy
// exception policy
841 template<int Min
, int Max
>
842 using ssr
= boost::safe_numerics::safe_signed_range
<
843 Min
, // min value in range
844 Max
, // max value in range
845 boost::safe_numerics::native
, // promotion policy
846 logging_exception_policy
// exception policy
850 const sur
<1910, 2099> test0
= 7; // note logged exception - value undefined
851 std::cout
<< "test0 = " << test0
<< '\n';
852 const ssr
<1910, 2099> test1
= 7; // note logged exception - value undefined
853 std::cout
<< "test1 = " << test1
<< '\n';
854 const sur
<0, 2> test2
= 7; // note logged exception - value undefined
855 std::cout
<< "test2 = " << test2
<< '\n';
856 const sur
<1910, 2099> test3
; // unitialized value
857 std::cout
<< "test3 = " << test3
<< '\n';
858 sur
<1910, 2099> test4
= 2000; // OK value
859 std::cout
<< "test4 = " << test4
<< boost::safe_numerics::make_interval(test4
) << '\n';
867 #include <boost/safe_numerics/safe_integer.hpp>
869 using boost::safe_numerics::safe
;
872 safe
<safe
<int>> r
{};
874 std::cout
<< r
<< std::endl
;
882 #include <boost/safe_numerics/safe_integer.hpp>
886 boost::safe_numerics::safe
<unsigned> u
;
887 std::istringstream is
{"-1"};
889 std::cout
<< u
<< std::endl
;
891 catch (std::exception
const& e
)
893 std::cerr
<< "ERR: " << e
.what() << std::endl
;