merge backout

This commit is contained in:
Dão Gottwald 2012-05-17 16:48:12 +02:00
commit 4634d36208
2 changed files with 39 additions and 29 deletions

View File

@ -210,26 +210,31 @@ struct PositionOfSignBit
template<typename IntegerType>
struct MinValue
{
// Bitwise ops may return a larger type, that's why we cast explicitly.
// In C++, left bit shifts on signed values is undefined by the standard
// unless the shifted value is representable.
// Notice that signed-to-unsigned conversions are always well-defined in
// the standard as the value congruent to 2**n, as expected. By contrast,
// unsigned-to-signed is only well-defined if the value is representable.
static const IntegerType value =
IsSigned<IntegerType>::value
? IntegerType(typename UnsignedType<IntegerType>::Type(1)
<< PositionOfSignBit<IntegerType>::value)
: IntegerType(0);
static IntegerType value()
{
// Bitwise ops may return a larger type, that's why we cast explicitly.
// In C++, left bit shifts on signed values is undefined by the standard
// unless the shifted value is representable.
// Notice that signed-to-unsigned conversions are always well-defined in
// the standard as the value congruent to 2**n, as expected. By contrast,
// unsigned-to-signed is only well-defined if the value is representable.
return IsSigned<IntegerType>::value
? IntegerType(typename UnsignedType<IntegerType>::Type(1)
<< PositionOfSignBit<IntegerType>::value)
: IntegerType(0);
}
};
template<typename IntegerType>
struct MaxValue
{
// Tricksy, but covered by the unit test.
// Relies heavily on the type of MinValue<IntegerType>::value
// being IntegerType.
static const IntegerType value = ~MinValue<IntegerType>::value;
static IntegerType value()
{
// Tricksy, but covered by the unit test.
// Relies heavily on the return type of MinValue<IntegerType>::value()
// being IntegerType.
return ~MinValue<IntegerType>::value();
}
};
/*
@ -273,7 +278,8 @@ struct IsInRangeImpl<T, U, true, true>
{
static bool run(U x)
{
return x <= MaxValue<T>::value && x >= MinValue<T>::value;
return x <= MaxValue<T>::value() &&
x >= MinValue<T>::value();
}
};
@ -282,7 +288,7 @@ struct IsInRangeImpl<T, U, false, false>
{
static bool run(U x)
{
return x <= MaxValue<T>::value;
return x <= MaxValue<T>::value();
}
};
@ -291,7 +297,9 @@ struct IsInRangeImpl<T, U, true, false>
{
static bool run(U x)
{
return sizeof(T) > sizeof(U) || x <= U(MaxValue<T>::value);
return sizeof(T) > sizeof(U)
? true
: x <= U(MaxValue<T>::value());
}
};
@ -302,7 +310,7 @@ struct IsInRangeImpl<T, U, false, true>
{
return sizeof(T) >= sizeof(U)
? x >= 0
: x >= 0 && x <= U(MaxValue<T>::value);
: x >= 0 && x <= U(MaxValue<T>::value());
}
};
@ -358,8 +366,8 @@ struct IsMulValidImpl<T, true, false>
{
static bool run(T x, T y)
{
const T max = MaxValue<T>::value;
const T min = MinValue<T>::value;
const T max = MaxValue<T>::value();
const T min = MinValue<T>::value();
if (x == 0 || y == 0)
return true;
@ -382,7 +390,8 @@ struct IsMulValidImpl<T, false, false>
{
static bool run(T x, T y)
{
return y == 0 || x <= MaxValue<T>::value / y;
return y == 0 ||
x <= MaxValue<T>::value() / y;
}
};
@ -398,8 +407,9 @@ inline bool
IsDivValid(T x, T y)
{
// Keep in mind that in the signed case, min/-1 is invalid because abs(min)>max.
return y != 0 &&
!(IsSigned<T>::value && x == MinValue<T>::value && y == T(-1));
return IsSigned<T>::value
? (y != 0) && (x != MinValue<T>::value() || y != T(-1))
: y != 0;
}
// This is just to shut up msvc warnings about negating unsigned ints.

View File

@ -96,8 +96,8 @@ void test()
VERIFY(sizeof(unsignedT) == sizeof(T));
VERIFY(detail::IsSigned<unsignedT>::value == false);
const CheckedInt<T> max(detail::MaxValue<T>::value);
const CheckedInt<T> min(detail::MinValue<T>::value);
const CheckedInt<T> max(detail::MaxValue<T>::value());
const CheckedInt<T> min(detail::MinValue<T>::value());
// Check min() and max(), since they are custom implementations and a mistake there
// could potentially NOT be caught by any other tests... while making everything wrong!
@ -394,10 +394,10 @@ void test()
if (isUSigned) \
VERIFY_IS_VALID_IF(CheckedInt<T>(U(-1)), isTSigned); \
if (sizeof(U) > sizeof(T)) \
VERIFY_IS_INVALID(CheckedInt<T>(U(detail::MaxValue<T>::value) + 1)); \
VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MaxValue<U>::value), \
VERIFY_IS_INVALID(CheckedInt<T>(U(detail::MaxValue<T>::value())+1)); \
VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MaxValue<U>::value()), \
(sizeof(T) > sizeof(U) || ((sizeof(T) == sizeof(U)) && (isUSigned || !isTSigned)))); \
VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MinValue<U>::value), \
VERIFY_IS_VALID_IF(CheckedInt<T>(detail::MinValue<U>::value()), \
isUSigned == false ? 1 : \
bool(isTSigned) == false ? 0 : \
sizeof(T) >= sizeof(U)); \