boost/libs/safe_numerics/test/test_cast_constexpr.cpp
2021-10-05 21:37:46 +02:00

91 lines
2.9 KiB
C++

// Copyright (c) 2019 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)
// compile only test to test constexpr casting
#include <boost/safe_numerics/safe_integer.hpp>
#include <boost/safe_numerics/native.hpp>
#include <boost/safe_numerics/exception_policies.hpp>
template <class T>
using safe_t = boost::safe_numerics::safe<
T,
boost::safe_numerics::native,
boost::safe_numerics::trap_exception
>;
constexpr const char * test_casting_results[] = {
// 0 0 0 0
// 012345670123456701234567012345670
// 012345678901234567890123456789012
/* 0*/ ".....xxx.xxx.xxx.xxx.xxx.xxx.xxx.",
/* 1*/ ".........xxx.xxx...x.xxx.xxx.xxx.",
/* 2*/ ".............xxx...x...x.xxx.xxx.",
/* 3*/ "...................x...x...x.xxx.",
/* 4*/ "..xx.xxx.xxx.xxx..xx.xxx.xxx.xxx.",
/* 5*/ "..xx..xx.xxx.xxx......xx.xxx.xxx.",
/* 6*/ "..xx..xx..xx.xxx..........xx.xxx.",
/* 7*/ "..xx..xx..xx..xx..............xx.",
};
#include <boost/safe_numerics/safe_integer_literal.hpp>
using namespace boost::safe_numerics;
#include <boost/mp11/algorithm.hpp>
using namespace boost::mp11;
template<class T>
struct p {
constexpr static bool value = '.' == test_casting_results[mp_first<T>::value][mp_second<T>::value];
};
template<class T2, class T1>
constexpr bool test_cast_constexpr(const T1 & v1){
// if we don't expect the operation to pass, we can't
// check the constexpr version of the calculation so
// just return success.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-value"
static_cast<safe_t<T2>>(v1);
static_cast<T2>(v1);
#pragma GCC diagnostic pop
return true;
}
#include "test_values.hpp"
template<typename L2>
struct test {
static_assert(mp_is_list<L2>(), "must be a list of two indices");
const static std::size_t i = mp_first<L2>();
const static std::size_t j = mp_second<L2>();
using T = mp_at_c<test_types, i>; // first element is a type
using T1 = typename mp_at_c<test_values, j>::value_type;
const static T1 v = mp_at_c<test_values, j>::value;
const static bool value =
test_cast_constexpr<T>(make_safe_literal(v, native, trap_exception));
};
int main(){
using namespace boost::safe_numerics;
using type_indices = mp_iota_c<mp_size<test_types>::value>;
using value_indices = mp_iota_c<mp_size<test_values>::value>;
// generate all combinations of types <- value
using l = mp_product<mp_list,type_indices,value_indices>;
//boost::safe_numerics::utility::print_types<l> lp;
// filter out the invalid ones
using l1 = mp_copy_if<l, p>;
//boost::safe_numerics::utility::print_types<l1> l1p;
// verify that all valid ones compile without error
static_assert(mp_all_of<l1, test>(), "testing all valid casts");
return 0;
}