safe_numerics/test/test_checked_cast.cpp
Robert Ramey c03a279bdd Made changes to constexpr tests hoping to reveal more information on constexpr failures in Clang compilers which support C++17.
Also included a couple of pragmas to suppress bogus warnings on earlier Clang platforms.
2018-12-11 09:17:18 -08:00

96 lines
3.0 KiB
C++

// 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 "test_checked_cast.hpp"
#include <boost/safe_numerics/checked_integer.hpp>
// test conversion to TResult from different literal types
template<class TResult, class TArg>
bool test_cast(
const TArg & v,
const char *tresult_name,
const char *targ_name,
char expected_result
){
std::cout
<< "testing static_cast<" << tresult_name << ">(" << targ_name << ")"
<< std::endl;
boost::safe_numerics::checked_result<TResult> r2 =
boost::safe_numerics::checked::cast<TResult>(v);
if(expected_result == 'x' && ! r2.exception()){
std::cout
<< "failed to detect error in construction "
<< tresult_name << "<-" << targ_name
<< std::endl;
boost::safe_numerics::checked::cast<TResult>(v);
return false;
}
if(expected_result == '.' && r2.exception()){
std::cout
<< "erroneously emitted error "
<< tresult_name << "<-" << targ_name
<< std::endl;
boost::safe_numerics::checked::cast<TResult>(v);
return false;
}
return true; // passed test
}
#include <boost/mp11/algorithm.hpp>
#include <boost/core/demangle.hpp>
using namespace boost::mp11;
// given a list of integral constants I, return a list of values
template<typename I>
struct get_values {
static_assert(mp_is_list<I>(), "must be a list of two types");
static_assert(2 == mp_size<I>::value, "must be a list of two types");
static constexpr const size_t first = mp_first<I>(); // index of first argument
static constexpr const size_t second = mp_second<I>();// index of second argument
};
struct test_pair {
bool m_error;
test_pair(bool b = true) : m_error(b) {}
operator bool(){
return m_error;
}
template<typename I>
void operator()(const I &){
using pair = get_values<I>;
using TResult = mp_at<test_types, mp_first<I>>;
using TArg = typename mp_at<test_values, mp_second<I>>::value_type;
static constexpr TArg v = mp_at<test_values, mp_second<I>>()();
m_error &= test_cast<TResult>(
v,
boost::core::demangle(typeid(TResult).name()).c_str(),
boost::core::demangle(typeid(TArg).name()).c_str(),
test_result_cast[pair::first][pair::second]
);
}
};
int main(){
// list of indices for values (integral constants)
using value_indices = mp_iota_c<mp_size<test_values>::value>;
// list of indices for types (integral constants)
using type_indices = mp_iota_c<mp_size<test_types>::value>;
// test runtime behavior
test_pair rval(true);
mp_for_each<
mp_product<mp_list, type_indices, value_indices>
>(rval);
std::cout << (rval ? "success!" : "failure") << std::endl;
return ! rval ;
}