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 
9 #include "test_checked_cast.hpp"
10 #include <boost/safe_numerics/checked_integer.hpp>
11 
12 // test conversion to TResult from different literal types
13 template<class TResult, class TArg>
test_cast(const TArg & v,const char * tresult_name,const char * targ_name,char expected_result)14 bool test_cast(
15     const TArg & v,
16     const char *tresult_name,
17     const char *targ_name,
18     char expected_result
19 ){
20     std::cout
21         << "testing static_cast<" << tresult_name << ">(" << targ_name << ")"
22         << std::endl;
23 
24     boost::safe_numerics::checked_result<TResult> r2 =
25         boost::safe_numerics::checked::cast<TResult>(v);
26 
27     if(expected_result == 'x' && ! r2.exception()){
28         std::cout
29             << "failed to detect error in construction "
30             << tresult_name << "<-" << targ_name
31             << std::endl;
32         boost::safe_numerics::checked::cast<TResult>(v);
33         return false;
34     }
35     if(expected_result == '.' && r2.exception()){
36         std::cout
37             << "erroneously emitted error "
38             << tresult_name << "<-" << targ_name
39             << std::endl;
40         boost::safe_numerics::checked::cast<TResult>(v);
41         return false;
42     }
43     return true; // passed test
44 }
45 
46 #include <boost/mp11/algorithm.hpp>
47 #include <boost/core/demangle.hpp>
48 
49 using namespace boost::mp11;
50 
51 // given a list of integral constants I, return a list of values
52 template<typename I>
53 struct get_values {
54     static_assert(mp_is_list<I>(), "must be a list of two types");
55     static_assert(2 == mp_size<I>::value, "must be a list of two types");
56     static constexpr const size_t first = mp_first<I>(); // index of first argument
57     static constexpr const size_t second = mp_second<I>();// index of second argument
58 };
59 
60 struct test_pair {
61     bool m_error;
test_pairtest_pair62     test_pair(bool b = true) : m_error(b) {}
operator booltest_pair63     operator bool(){
64         return m_error;
65     }
66     template<typename I>
operator ()test_pair67     void operator()(const I &){
68         using pair = get_values<I>;
69         using TResult = mp_at<test_types, mp_first<I>>;
70         using TArg = typename mp_at<test_values, mp_second<I>>::value_type;
71         static constexpr TArg v = mp_at<test_values, mp_second<I>>()();
72         m_error &= test_cast<TResult>(
73             v,
74             boost::core::demangle(typeid(TResult).name()).c_str(),
75             boost::core::demangle(typeid(TArg).name()).c_str(),
76             test_result_cast[pair::first][pair::second]
77         );
78     }
79 };
80 
main()81 int main(){
82     // list of indices for values (integral constants)
83     using value_indices = mp_iota_c<mp_size<test_values>::value>;
84     // list of indices for types (integral constants)
85     using type_indices = mp_iota_c<mp_size<test_types>::value>;
86 
87     // test runtime behavior
88     test_pair rval(true);
89     mp_for_each<
90         mp_product<mp_list, type_indices, value_indices>
91     >(rval);
92 
93     std::cout << (rval ? "success!" : "failure") << std::endl;
94     return ! rval ;
95 }
96