Use std::is_signed and std::enable_if.
This commit is contained in:
parent
335e13251e
commit
ddd7ccf722
@ -5,6 +5,7 @@
|
||||
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <Intsafe.h>
|
||||
@ -37,35 +38,6 @@ namespace Safe {
|
||||
* is available.
|
||||
*/
|
||||
namespace Internal {
|
||||
/*!
|
||||
* @brief Helper struct to determine whether a type is signed or unsigned
|
||||
*
|
||||
* This struct is a backport of std::is_signed from C++11. It has a public
|
||||
* enum with the property VALUE which is true when the type is signed or
|
||||
* false if it is unsigned.
|
||||
*/
|
||||
template <typename T>
|
||||
struct is_signed {
|
||||
enum { VALUE = static_cast<T>(-1) < static_cast<T>(0) };
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Helper struct for SFINAE, from C++11
|
||||
|
||||
* This struct has a public typedef called type typedef'd to T if B is
|
||||
* true. Otherwise there is no typedef.
|
||||
*/
|
||||
template <bool B, class T = void>
|
||||
struct enable_if {};
|
||||
|
||||
/*!
|
||||
* @brief Specialization of enable_if for the case B == true
|
||||
*/
|
||||
template <class T>
|
||||
struct enable_if<true, T> {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
/*!
|
||||
* @brief Check the addition of two numbers for overflows for signed
|
||||
* integer types larger than int or with the same size as int.
|
||||
@ -84,9 +56,8 @@ struct enable_if<true, T> {
|
||||
* https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
|
||||
*/
|
||||
template <typename T>
|
||||
typename enable_if<is_signed<T>::VALUE && sizeof(T) >= sizeof(int), bool>::type fallback_add_overflow(T summand_1,
|
||||
T summand_2,
|
||||
T& result) {
|
||||
typename std::enable_if<std::is_signed<T>::value && sizeof(T) >= sizeof(int), bool>::type fallback_add_overflow(
|
||||
T summand_1, T summand_2, T& result) {
|
||||
if (((summand_2 >= 0) && (summand_1 > std::numeric_limits<T>::max() - summand_2)) ||
|
||||
((summand_2 < 0) && (summand_1 < std::numeric_limits<T>::min() - summand_2))) {
|
||||
return true;
|
||||
@ -116,9 +87,8 @@ typename enable_if<is_signed<T>::VALUE && sizeof(T) >= sizeof(int), bool>::type
|
||||
* https://wiki.sei.cmu.edu/confluence/display/c/INT02-C.+Understand+integer+conversion+rules
|
||||
*/
|
||||
template <typename T>
|
||||
typename enable_if<is_signed<T>::VALUE && sizeof(T) < sizeof(int), bool>::type fallback_add_overflow(T summand_1,
|
||||
T summand_2,
|
||||
T& result) {
|
||||
typename std::enable_if<std::is_signed<T>::value && sizeof(T) < sizeof(int), bool>::type fallback_add_overflow(
|
||||
T summand_1, T summand_2, T& result) {
|
||||
const int res = summand_1 + summand_2;
|
||||
if ((res > std::numeric_limits<T>::max()) || (res < std::numeric_limits<T>::min())) {
|
||||
return true;
|
||||
@ -145,7 +115,8 @@ typename enable_if<is_signed<T>::VALUE && sizeof(T) < sizeof(int), bool>::type f
|
||||
* https://wiki.sei.cmu.edu/confluence/display/c/INT30-C.+Ensure+that+unsigned+integer+operations+do+not+wrap
|
||||
*/
|
||||
template <typename T>
|
||||
typename enable_if<!is_signed<T>::VALUE, bool>::type fallback_add_overflow(T summand_1, T summand_2, T& result) {
|
||||
typename std::enable_if<!std::is_signed<T>::value, bool>::type fallback_add_overflow(T summand_1, T summand_2,
|
||||
T& result) {
|
||||
result = summand_1 + summand_2;
|
||||
return result < summand_1;
|
||||
}
|
||||
@ -255,7 +226,7 @@ T add(T summand_1, T summand_2) {
|
||||
* when `num == std::numeric_limits<T>::min()`.
|
||||
*/
|
||||
template <typename T>
|
||||
typename Internal::enable_if<Internal::is_signed<T>::VALUE, T>::type abs(T num) throw() {
|
||||
typename std::enable_if<std::is_signed<T>::value, T>::type abs(T num) throw() {
|
||||
if (num == std::numeric_limits<T>::min()) {
|
||||
return std::numeric_limits<T>::max();
|
||||
}
|
||||
|
||||
@ -26,42 +26,42 @@ struct AdditionTestValues;
|
||||
* Overload for unsigned types.
|
||||
*/
|
||||
template <typename T>
|
||||
struct AdditionTestValues<T, typename si::enable_if<!si::is_signed<T>::VALUE>::type> {
|
||||
struct AdditionTestValues<T, typename std::enable_if<!std::is_signed<T>::VALUE>::type> {
|
||||
static const size_t case_count = 5;
|
||||
static const T summand[case_count];
|
||||
static const bool overflow[case_count][case_count];
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
const T AdditionTestValues<T, typename si::enable_if<!si::is_signed<T>::VALUE>::type>::summand[] = {
|
||||
const T AdditionTestValues<T, typename std::enable_if<!std::is_signed<T>::VALUE>::type>::summand[] = {
|
||||
0, 1, 2, static_cast<T>(std::numeric_limits<T>::max() - 1), std::numeric_limits<T>::max()};
|
||||
|
||||
template <typename T>
|
||||
const bool
|
||||
AdditionTestValues<T, typename si::enable_if<!si::is_signed<T>::VALUE>::type>::overflow[case_count][case_count] = {
|
||||
// 0
|
||||
{false, false, false, false, false},
|
||||
// 1
|
||||
{false, false, false, false, true},
|
||||
// 2
|
||||
{false, false, false, true, true},
|
||||
// max - 1
|
||||
{false, false, true, true, true},
|
||||
// max
|
||||
{false, true, true, true, true}};
|
||||
const bool AdditionTestValues<
|
||||
T, typename std::enable_if<!std::is_signed<T>::VALUE>::type>::overflow[case_count][case_count] = {
|
||||
// 0
|
||||
{false, false, false, false, false},
|
||||
// 1
|
||||
{false, false, false, false, true},
|
||||
// 2
|
||||
{false, false, false, true, true},
|
||||
// max - 1
|
||||
{false, false, true, true, true},
|
||||
// max
|
||||
{false, true, true, true, true}};
|
||||
|
||||
/*!
|
||||
* Overload for signed integers
|
||||
*/
|
||||
template <typename T>
|
||||
struct AdditionTestValues<T, typename si::enable_if<si::is_signed<T>::VALUE>::type> {
|
||||
struct AdditionTestValues<T, typename std::enable_if<std::is_signed<T>::VALUE>::type> {
|
||||
static const size_t case_count = 8;
|
||||
static const T summand[case_count];
|
||||
static const bool overflow[case_count][case_count];
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
const T AdditionTestValues<T, typename si::enable_if<si::is_signed<T>::VALUE>::type>::summand[] = {
|
||||
const T AdditionTestValues<T, typename std::enable_if<std::is_signed<T>::VALUE>::type>::summand[] = {
|
||||
std::numeric_limits<T>::min(),
|
||||
static_cast<T>(std::numeric_limits<T>::min() + 1),
|
||||
-1,
|
||||
@ -73,7 +73,7 @@ const T AdditionTestValues<T, typename si::enable_if<si::is_signed<T>::VALUE>::t
|
||||
|
||||
template <typename T>
|
||||
const bool
|
||||
AdditionTestValues<T, typename si::enable_if<si::is_signed<T>::VALUE>::type>::overflow[case_count][case_count] = {
|
||||
AdditionTestValues<T, typename std::enable_if<std::is_signed<T>::VALUE>::type>::overflow[case_count][case_count] = {
|
||||
// min
|
||||
{true, true, true, false, false, false, false, false},
|
||||
// min + 1
|
||||
|
||||
Loading…
Reference in New Issue
Block a user