| 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> |
| 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 | constexpr static const size_t first = mp_first<I>(); // index of first argument |
| 57 | constexpr static const size_t second = mp_second<I>();// index of second argument |
| 58 | }; |
| 59 | |
| 60 | struct test_pair { |
| 61 | bool m_error; |
| 62 | test_pair(bool b = true) : m_error(b) {} |
| 63 | operator bool(){ |
| 64 | return m_error; |
| 65 | } |
| 66 | template<typename I> |
| 67 | 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 | constexpr static const TArg v = mp_at<test_values, mp_second<I>>()(); |
| 72 | m_error &= test_cast<TResult>( |
| 73 | v, |
| 74 | boost::core::demangle(name: typeid(TResult).name()).c_str(), |
| 75 | boost::core::demangle(name: typeid(TArg).name()).c_str(), |
| 76 | test_result_cast[pair::first][pair::second] |
| 77 | ); |
| 78 | } |
| 79 | }; |
| 80 | |
| 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 | >(f&: rval); |
| 92 | |
| 93 | std::cout << (rval ? "success!" : "failure" ) << std::endl; |
| 94 | return ! rval ; |
| 95 | } |
| 96 | |