• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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