1 // Copyright (c) 2012 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 #include <iostream>
8 #include <cstdlib> // EXIT_SUCCESS
9
10 #include <boost/safe_numerics/safe_compare.hpp>
11 #include <boost/safe_numerics/safe_integer.hpp>
12 #include <boost/safe_numerics/range_value.hpp>
13
14 using namespace boost::safe_numerics;
15
16 // works for both GCC and clang
17 #pragma GCC diagnostic push
18 #pragma GCC diagnostic ignored "-Wunused-value"
19
20 // test conversion to T2 from different literal types
21 template<class T2, class T1>
test_cast(T1 v1,const char * t2_name,const char * t1_name)22 bool test_cast(T1 v1, const char *t2_name, const char *t1_name){
23 std::cout
24 << "testing static_cast<safe<" << t2_name << ">>(" << t1_name << ")"
25 << std::endl;
26 {
27 /* test conversion constructor to safe<T2> from v1 */
28 try{
29 // use auto to avoid checking assignment.
30 auto result = static_cast<safe<T2>>(v1);
31 std::cout << make_result_display(result) << " <- " << v1
32 << std::endl;
33 if(! safe_compare::equal(base_value(result), v1)){
34 std::cout
35 << ' ' << t2_name << "<-" << t1_name
36 << " failed to detect error in construction"
37 << std::endl;
38 static_cast<safe<T2> >(v1);
39 return false;
40 }
41 }
42 catch(const std::exception &){
43 if( safe_compare::equal(static_cast<T2>(v1), v1)){
44 std::cout
45 << ' ' << t1_name << "<-" << t2_name
46 << " erroneously emitted error "
47 << std::endl;
48 try{
49 static_cast<safe<T2> >(v1);
50 }
51 catch(const std::exception &){}
52 return false;
53 }
54 }
55 }
56 {
57 /* test conversion to T2 from safe<T1>(v1) */
58 safe<T1> s1(v1);
59 try{
60 auto result = static_cast<T2>(s1);
61 std::cout << make_result_display(result) << " <- " << v1
62 << std::endl;
63 if(! safe_compare::equal(result, v1)){
64 std::cout
65 << ' ' << t2_name << "<-" << t1_name
66 << " failed to detect error in construction"
67 << std::endl;
68 static_cast<T2>(s1);
69 return false;
70 }
71 }
72 catch(const std::exception &){
73 if(safe_compare::equal(static_cast<T2>(v1), v1)){
74 std::cout
75 << ' ' << t1_name << "<-" << t2_name
76 << " erroneously emitted error"
77 << std::endl;
78 try{
79 static_cast<T2>(s1);
80 }
81 catch(const std::exception &){}
82 return false;
83 }
84 }
85 }
86 return true; // passed test
87 }
88 #pragma GCC diagnostic pop
89
90 #include <boost/mp11/algorithm.hpp>
91 #include <boost/core/demangle.hpp>
92 #include "test_values.hpp"
93
94 using namespace boost::mp11;
95
96 struct test {
97 bool m_error;
testtest98 test(bool b = true) : m_error(b) {}
operator booltest99 operator bool(){
100 return m_error;
101 }
102 template<typename T>
operator ()test103 void operator()(const T &){
104 static_assert(mp_is_list<T>(), "must be a list of two types");
105 using T1 = mp_first<T>; // first element is a type
106 // second element is an integral constant
107 using T2 = typename mp_second<T>::value_type; // get it's type
108 constexpr T2 v2 = mp_second<T>(); // get it's value
109 m_error &= test_cast<T1>(
110 v2,
111 boost::core::demangle(typeid(T1).name()).c_str(),
112 boost::core::demangle(typeid(T2).name()).c_str()
113 );
114 }
115 };
116
main()117 int main(){
118 test rval(true);
119
120 mp_for_each<
121 mp_product<mp_list, test_types, test_values>
122 >(rval);
123
124 std::cout << (rval ? "success!" : "failure") << std::endl;
125 return ! rval ;
126 }
127