summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/safe_numerics/test/test_cast.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/boost/libs/safe_numerics/test/test_cast.cpp126
1 files changed, 126 insertions, 0 deletions
diff --git a/src/boost/libs/safe_numerics/test/test_cast.cpp b/src/boost/libs/safe_numerics/test/test_cast.cpp
new file mode 100644
index 000000000..a7b48b8d2
--- /dev/null
+++ b/src/boost/libs/safe_numerics/test/test_cast.cpp
@@ -0,0 +1,126 @@
+// Copyright (c) 2012 Robert Ramey
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#include <iostream>
+#include <cstdlib> // EXIT_SUCCESS
+
+#include <boost/safe_numerics/safe_compare.hpp>
+#include <boost/safe_numerics/safe_integer.hpp>
+#include <boost/safe_numerics/range_value.hpp>
+
+using namespace boost::safe_numerics;
+
+// works for both GCC and clang
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-value"
+
+// test conversion to T2 from different literal types
+template<class T2, class T1>
+bool test_cast(T1 v1, const char *t2_name, const char *t1_name){
+ std::cout
+ << "testing static_cast<safe<" << t2_name << ">>(" << t1_name << ")"
+ << std::endl;
+ {
+ /* test conversion constructor to safe<T2> from v1 */
+ try{
+ // use auto to avoid checking assignment.
+ auto result = static_cast<safe<T2>>(v1);
+ std::cout << make_result_display(result) << " <- " << v1
+ << std::endl;
+ if(! safe_compare::equal(base_value(result), v1)){
+ std::cout
+ << ' ' << t2_name << "<-" << t1_name
+ << " failed to detect error in construction"
+ << std::endl;
+ static_cast<safe<T2> >(v1);
+ return false;
+ }
+ }
+ catch(const std::exception &){
+ if( safe_compare::equal(static_cast<T2>(v1), v1)){
+ std::cout
+ << ' ' << t1_name << "<-" << t2_name
+ << " erroneously emitted error "
+ << std::endl;
+ try{
+ static_cast<safe<T2> >(v1);
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ {
+ /* test conversion to T2 from safe<T1>(v1) */
+ safe<T1> s1(v1);
+ try{
+ auto result = static_cast<T2>(s1);
+ std::cout << make_result_display(result) << " <- " << v1
+ << std::endl;
+ if(! safe_compare::equal(result, v1)){
+ std::cout
+ << ' ' << t2_name << "<-" << t1_name
+ << " failed to detect error in construction"
+ << std::endl;
+ static_cast<T2>(s1);
+ return false;
+ }
+ }
+ catch(const std::exception &){
+ if(safe_compare::equal(static_cast<T2>(v1), v1)){
+ std::cout
+ << ' ' << t1_name << "<-" << t2_name
+ << " erroneously emitted error"
+ << std::endl;
+ try{
+ static_cast<T2>(s1);
+ }
+ catch(const std::exception &){}
+ return false;
+ }
+ }
+ }
+ return true; // passed test
+}
+#pragma GCC diagnostic pop
+
+#include <boost/mp11/algorithm.hpp>
+#include <boost/core/demangle.hpp>
+#include "test_values.hpp"
+
+using namespace boost::mp11;
+
+struct test {
+ bool m_error;
+ test(bool b = true) : m_error(b) {}
+ operator bool(){
+ return m_error;
+ }
+ template<typename T>
+ void operator()(const T &){
+ static_assert(mp_is_list<T>(), "must be a list of two types");
+ using T1 = mp_first<T>; // first element is a type
+ // second element is an integral constant
+ using T2 = typename mp_second<T>::value_type; // get it's type
+ constexpr T2 v2 = mp_second<T>(); // get it's value
+ m_error &= test_cast<T1>(
+ v2,
+ boost::core::demangle(typeid(T1).name()).c_str(),
+ boost::core::demangle(typeid(T2).name()).c_str()
+ );
+ }
+};
+
+int main(){
+ test rval(true);
+
+ mp_for_each<
+ mp_product<mp_list, test_types, test_values>
+ >(rval);
+
+ std::cout << (rval ? "success!" : "failure") << std::endl;
+ return ! rval ;
+}