test_cast.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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. #include <iostream>
  7. #include <cstdlib> // EXIT_SUCCESS
  8. #include <boost/safe_numerics/safe_compare.hpp>
  9. #include <boost/safe_numerics/safe_integer.hpp>
  10. #include <boost/safe_numerics/range_value.hpp>
  11. using namespace boost::safe_numerics;
  12. // works for both GCC and clang
  13. #pragma GCC diagnostic push
  14. #pragma GCC diagnostic ignored "-Wunused-value"
  15. // test conversion to T2 from different literal types
  16. template<class T2, class T1>
  17. bool test_cast(T1 v1, const char *t2_name, const char *t1_name){
  18. std::cout
  19. << "testing static_cast<safe<" << t2_name << ">>(" << t1_name << ")"
  20. << std::endl;
  21. {
  22. /* test conversion constructor to safe<T2> from v1 */
  23. try{
  24. // use auto to avoid checking assignment.
  25. auto result = static_cast<safe<T2>>(v1);
  26. std::cout << make_result_display(result) << " <- " << v1
  27. << std::endl;
  28. if(! safe_compare::equal(base_value(result), v1)){
  29. std::cout
  30. << ' ' << t2_name << "<-" << t1_name
  31. << " failed to detect error in construction"
  32. << std::endl;
  33. static_cast<safe<T2> >(v1);
  34. return false;
  35. }
  36. }
  37. catch(const std::exception &){
  38. if( safe_compare::equal(static_cast<T2>(v1), v1)){
  39. std::cout
  40. << ' ' << t1_name << "<-" << t2_name
  41. << " erroneously emitted error "
  42. << std::endl;
  43. try{
  44. static_cast<safe<T2> >(v1);
  45. }
  46. catch(const std::exception &){}
  47. return false;
  48. }
  49. }
  50. }
  51. {
  52. /* test conversion to T1 from safe<T2>(v2) */
  53. safe<T1> s1(v1);
  54. try{
  55. auto result = static_cast<T2>(s1);
  56. std::cout << make_result_display(result) << " <- " << v1
  57. << std::endl;
  58. if(! safe_compare::equal(result, v1)){
  59. std::cout
  60. << ' ' << t2_name << "<-" << t1_name
  61. << " failed to detect error in construction"
  62. << std::endl;
  63. static_cast<T2>(s1);
  64. return false;
  65. }
  66. }
  67. catch(const std::exception &){
  68. if(safe_compare::equal(static_cast<T2>(v1), v1)){
  69. std::cout
  70. << ' ' << t1_name << "<-" << t2_name
  71. << " erroneously emitted error"
  72. << std::endl;
  73. try{
  74. static_cast<T2>(s1);
  75. }
  76. catch(const std::exception &){}
  77. return false;
  78. }
  79. }
  80. }
  81. return true; // passed test
  82. }
  83. #pragma GCC diagnostic pop
  84. #include <boost/mp11/algorithm.hpp>
  85. #include <boost/core/demangle.hpp>
  86. #include "test_values.hpp"
  87. using namespace boost::mp11;
  88. template<typename T>
  89. using extract_value_type = typename T::value_type;
  90. using test_types = mp_unique<
  91. mp_transform<
  92. extract_value_type,
  93. test_values
  94. >
  95. >;
  96. struct test {
  97. bool m_error;
  98. test(bool b = true) : m_error(b) {}
  99. operator bool(){
  100. return m_error;
  101. }
  102. template<typename T>
  103. 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. int main(){
  117. test rval(true);
  118. mp_for_each<
  119. mp_product<mp_list, test_types, test_values>
  120. >(rval);
  121. std::cout << (rval ? "success!" : "failure") << std::endl;
  122. return ! rval ;
  123. }