1 // Copyright (c) 2019 Robert Ramey
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See
4 // accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6
7 // compile only test to test constexpr casting
8
9 #include <boost/safe_numerics/safe_integer.hpp>
10 #include <boost/safe_numerics/native.hpp>
11 #include <boost/safe_numerics/exception_policies.hpp>
12
13 template <class T>
14 using safe_t = boost::safe_numerics::safe<
15 T,
16 boost::safe_numerics::native,
17 boost::safe_numerics::trap_exception
18 >;
19
20 constexpr const char * test_casting_results[] = {
21 // 0 0 0 0
22 // 012345670123456701234567012345670
23 // 012345678901234567890123456789012
24 /* 0*/ ".....xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
25 /* 1*/ ".........xxx.xxx...x.xxx.xxx.xxx.",
26 /* 2*/ ".............xxx...x...x.xxx.xxx.",
27 /* 3*/ "...................x...x...x.xxx.",
28 /* 4*/ "..xx.xxx.xxx.xxx..xx.xxx.xxx.xxx.",
29 /* 5*/ "..xx..xx.xxx.xxx......xx.xxx.xxx.",
30 /* 6*/ "..xx..xx..xx.xxx..........xx.xxx.",
31 /* 7*/ "..xx..xx..xx..xx..............xx.",
32 };
33
34 #include <boost/safe_numerics/safe_integer_literal.hpp>
35 using namespace boost::safe_numerics;
36
37 #include <boost/mp11/algorithm.hpp>
38
39 using namespace boost::mp11;
40
41 template<class T>
42 struct p {
43 constexpr static bool value = '.' == test_casting_results[mp_first<T>::value][mp_second<T>::value];
44 };
45
46 template<class T2, class T1>
test_cast_constexpr(const T1 & v1)47 constexpr bool test_cast_constexpr(const T1 & v1){
48 // if we don't expect the operation to pass, we can't
49 // check the constexpr version of the calculation so
50 // just return success.
51 #pragma GCC diagnostic push
52 #pragma GCC diagnostic ignored "-Wunused-value"
53 static_cast<safe_t<T2>>(v1);
54 static_cast<T2>(v1);
55 #pragma GCC diagnostic pop
56 return true;
57 }
58
59 #include "test_values.hpp"
60
61 template<typename L2>
62 struct test {
63 static_assert(mp_is_list<L2>(), "must be a list of two indices");
64 const static std::size_t i = mp_first<L2>();
65 const static std::size_t j = mp_second<L2>();
66 using T = mp_at_c<test_types, i>; // first element is a type
67 using T1 = typename mp_at_c<test_values, j>::value_type;
68 const static T1 v = mp_at_c<test_values, j>::value;
69 const static bool value =
70 test_cast_constexpr<T>(make_safe_literal(v, native, trap_exception));
71 };
72
main()73 int main(){
74 using namespace boost::safe_numerics;
75
76 using type_indices = mp_iota_c<mp_size<test_types>::value>;
77 using value_indices = mp_iota_c<mp_size<test_values>::value>;
78
79 // generate all combinations of types <- value
80 using l = mp_product<mp_list,type_indices,value_indices>;
81 //boost::safe_numerics::utility::print_types<l> lp;
82
83 // filter out the invalid ones
84 using l1 = mp_copy_if<l, p>;
85 //boost::safe_numerics::utility::print_types<l1> l1p;
86
87 // verify that all valid ones compile without error
88 static_assert(mp_all_of<l1, test>(), "testing all valid casts");
89 return 0;
90 }
91