700 lines
19 KiB
C++
700 lines
19 KiB
C++
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
#if !defined __GNUC__
|
|
// relative include path contains '..', specific to this file
|
|
#pragma warning( disable: 4464 )
|
|
|
|
#else
|
|
#pragma GCC diagnostic ignored "-Wunused-variable"
|
|
#endif
|
|
|
|
#if !defined __clang__ && defined __GNUC__ && __cplusplus >= 201402L
|
|
// The gcc compiler isn't smart enough to sort out that the constexpr exception functions
|
|
// are never hit, so create a null exception handler. Nothing in this file is tested at runtime in any case.
|
|
class SafeIntGccCompileOnly
|
|
{
|
|
public:
|
|
constexpr static void SafeIntOnOverflow()
|
|
{
|
|
}
|
|
|
|
constexpr static void SafeIntOnDivZero()
|
|
{
|
|
}
|
|
};
|
|
|
|
#define SafeIntDefaultExceptionHandler SafeIntGccCompileOnly
|
|
|
|
#endif
|
|
|
|
#include "../SafeInt.hpp"
|
|
|
|
namespace TestConstExpr
|
|
{
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR11 bool LessThanTest()
|
|
{
|
|
return
|
|
(U)2 < SafeInt<T>(3) &&
|
|
SafeInt<T>(4) < (U)5 &&
|
|
SafeInt<T>(6) < SafeInt<U>(7);
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR11 bool GreaterThanTest()
|
|
{
|
|
return
|
|
(U)2 > SafeInt<T>(3) &&
|
|
SafeInt<T>(4) > (U)5 &&
|
|
SafeInt<T>(6) > SafeInt<U>(7);
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR11 bool LessThanEqualTest()
|
|
{
|
|
return
|
|
(U)2 <= SafeInt<T>(3) &&
|
|
SafeInt<T>(4) <= (U)5 &&
|
|
SafeInt<T>(6) <= SafeInt<U>(7);
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR11 bool GreaterThanEqualTest()
|
|
{
|
|
return
|
|
(U)2 >= SafeInt<T>(3) &&
|
|
SafeInt<T>(4) >= (U)5 &&
|
|
SafeInt<T>(6) >= SafeInt<U>(7);
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR11 bool EqualTest()
|
|
{
|
|
return
|
|
(U)2 == SafeInt<T>(3) &&
|
|
SafeInt<T>(4) == (U)5 &&
|
|
SafeInt<T>(6) == SafeInt<U>(7) &&
|
|
true == SafeInt<T>(1) &&
|
|
false == SafeInt<T>(0);
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR11 bool NotEqualTest()
|
|
{
|
|
return
|
|
(U)2 != SafeInt<T>(3) &&
|
|
SafeInt<T>(4) != (U)5 &&
|
|
SafeInt<T>(6) != SafeInt<U>(7) &&
|
|
true != SafeInt<T>(1) &&
|
|
false != SafeInt<T>(0);
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
void ComparisonTestTU()
|
|
{
|
|
static bool b1 = LessThanTest<T, U>();
|
|
static bool b2 = LessThanEqualTest<T, U>();
|
|
static bool b3 = GreaterThanTest<T, U>();
|
|
static bool b4 = GreaterThanEqualTest<T, U>();
|
|
static bool b5 = EqualTest<T, U>();
|
|
static bool b6 = NotEqualTest<T, U>();
|
|
}
|
|
|
|
template <typename T> void ComparisonTestT()
|
|
{
|
|
ComparisonTestTU<T, char>();
|
|
ComparisonTestTU<T, signed char>();
|
|
ComparisonTestTU<T, unsigned char>();
|
|
ComparisonTestTU<T, signed short>();
|
|
ComparisonTestTU<T, unsigned short>();
|
|
ComparisonTestTU<T, signed int>();
|
|
ComparisonTestTU<T, unsigned int>();
|
|
ComparisonTestTU<T, signed long>();
|
|
ComparisonTestTU<T, unsigned long>();
|
|
ComparisonTestTU<T, signed long long>();
|
|
ComparisonTestTU<T, unsigned long long>();
|
|
}
|
|
|
|
template <typename T>
|
|
SAFEINT_CONSTEXPR11 T ConstConstructor()
|
|
{
|
|
// Constructors, also add in the useless unary + operator
|
|
return SafeInt<T>() + SafeInt<T>(1) + SafeInt<T>(false) + (+SafeInt<T>(3));
|
|
}
|
|
|
|
template <typename T>
|
|
SAFEINT_CONSTEXPR11 bool ConstBool()
|
|
{
|
|
return (bool)SafeInt<T>(2) && !SafeInt<T>(0);
|
|
}
|
|
|
|
template <typename T>
|
|
void ConstTestT()
|
|
{
|
|
static const T t = ConstConstructor<T>();
|
|
static const bool b = ConstBool<T>();
|
|
}
|
|
|
|
template <typename T>
|
|
SAFEINT_CONSTEXPR11 SafeInt<T> ConstSafeInt()
|
|
{
|
|
return SafeInt<T>(1);
|
|
}
|
|
|
|
template <typename T>
|
|
void ConstCastTestT()
|
|
{
|
|
static const bool b = ConstSafeInt<T>();
|
|
static const wchar_t w = ConstSafeInt<T>();
|
|
static const char c = ConstSafeInt<T>();
|
|
static const signed char sc = ConstSafeInt<T>();
|
|
static const unsigned char uc = ConstSafeInt<T>();
|
|
static const signed short s = ConstSafeInt<T>();
|
|
static const unsigned short us = ConstSafeInt<T>();
|
|
static const signed int i = ConstSafeInt<T>();
|
|
static const unsigned int ui = ConstSafeInt<T>();
|
|
static const signed long l = ConstSafeInt<T>();
|
|
static const unsigned long ul = ConstSafeInt<T>();
|
|
static const signed long long ll = ConstSafeInt<T>();
|
|
static const unsigned long long ull = ConstSafeInt<T>();
|
|
static const size_t st = ConstSafeInt<T>();
|
|
static const ptrdiff_t pt = ConstSafeInt<T>();
|
|
|
|
// Also catch the useless unary + operator
|
|
static const int pl = +ConstSafeInt<T>();
|
|
}
|
|
|
|
#if CPLUSPLUS_STD == CPLUSPLUS_14
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 T DivOperator()
|
|
{
|
|
// Have to explicitly force this operator
|
|
// to be used
|
|
T lhs = 3;
|
|
SafeInt<U> s(2);
|
|
|
|
T& r = operator /=(lhs, s);
|
|
return r;
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 T AddOperator()
|
|
{
|
|
// Have to explicitly force this operator
|
|
// to be used
|
|
T lhs = 3;
|
|
SafeInt<U> s(2);
|
|
|
|
T& r = operator +=(lhs, s);
|
|
return r;
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 T SubOperator()
|
|
{
|
|
// Have to explicitly force this operator
|
|
// to be used
|
|
T lhs = 3;
|
|
SafeInt<U> s(2);
|
|
|
|
T& r = operator -=(lhs, s);
|
|
return r;
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 T LShiftOperator()
|
|
{
|
|
// Have to explicitly force this operator
|
|
// to be used
|
|
// T& operator <<=(T& lhs, SafeInt< U, E > rhs)
|
|
|
|
T lhs = 3;
|
|
SafeInt<U> s(2);
|
|
|
|
T& r = operator <<=(lhs, s);
|
|
return r;
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 U LShiftOperator2()
|
|
{
|
|
// Have to explicitly force this operator
|
|
// to be used
|
|
U lhs = 3;
|
|
SafeInt<T> s(2);
|
|
|
|
SafeInt<U> r = operator <<(lhs, s);
|
|
return r;
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 T RShiftOperator()
|
|
{
|
|
// Have to explicitly force this operator
|
|
// to be used
|
|
|
|
T lhs = 3;
|
|
SafeInt<U> s(1);
|
|
|
|
T& r = operator >>=(lhs, s);
|
|
return r;
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 U RShiftOperator2()
|
|
{
|
|
// Have to explicitly force this operator
|
|
// to be used
|
|
U lhs = 3;
|
|
SafeInt<T> s(1);
|
|
|
|
SafeInt<U> r = operator >>(lhs, s);
|
|
return r;
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 T AndOperator()
|
|
{
|
|
// Have to explicitly force this operator
|
|
// to be used
|
|
|
|
T lhs = 3;
|
|
SafeInt<U> s(1);
|
|
|
|
T& r = operator &=(lhs, s);
|
|
return r;
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 U AndOperator2()
|
|
{
|
|
// Have to explicitly force this operator
|
|
// to be used
|
|
U lhs = 3;
|
|
SafeInt<T> s(1);
|
|
|
|
SafeInt<T> r = operator &(lhs, s);
|
|
return r;
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 T XorOperator()
|
|
{
|
|
// Have to explicitly force this operator
|
|
// to be used
|
|
|
|
T lhs = 3;
|
|
SafeInt<U> s(1);
|
|
|
|
T& r = operator ^=(lhs, s);
|
|
return r;
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 U XorOperator2()
|
|
{
|
|
// Have to explicitly force this operator
|
|
// to be used
|
|
U lhs = 3;
|
|
SafeInt<T> s(1);
|
|
|
|
SafeInt<T> r = operator ^(lhs, s);
|
|
return r;
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 T OrOperator()
|
|
{
|
|
// Have to explicitly force this operator
|
|
// to be used
|
|
|
|
T lhs = 3;
|
|
SafeInt<U> s(1);
|
|
|
|
T& r = operator |=(lhs, s);
|
|
return r;
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 U OrOperator2()
|
|
{
|
|
// Have to explicitly force this operator
|
|
// to be used
|
|
U lhs = 3;
|
|
SafeInt<T> s(1);
|
|
|
|
SafeInt<T> r = operator |(lhs, s);
|
|
return r;
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 bool SafeCastTest()
|
|
{
|
|
U to = 0;
|
|
return SafeCast((T)3, to);
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 bool SafeModulusTest()
|
|
{
|
|
U u = 2;
|
|
T result = 0;
|
|
return SafeModulus((T)3, u, result);
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 bool SafeMultiplyTest()
|
|
{
|
|
U u = 2;
|
|
T result = 0;
|
|
return SafeMultiply((T)3, u, result);
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 bool SafeDivideTest()
|
|
{
|
|
U u = 2;
|
|
T result = 0;
|
|
return SafeDivide((T)3, u, result);
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 bool SafeAddTest()
|
|
{
|
|
U u = 2;
|
|
T result = 0;
|
|
return SafeAdd((T)3, u, result);
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
void StaticAssertTU()
|
|
{
|
|
// Constructors
|
|
static_assert(SafeInt<T>(SafeInt<U>(1)), "SafeInt U constr");
|
|
static_assert(SafeInt<T>((U)1), "U constr");
|
|
|
|
// Assignment operators
|
|
static_assert((SafeInt<T>() = (U)1), "Assignment U");
|
|
static_assert((SafeInt<T>() = (T)1), "Assignment T");
|
|
static_assert((SafeInt<T>() = SafeInt<U>(1)), "Assignment SafeInt U");
|
|
// Next one happens when T == U, so already included
|
|
// static_assert((SafeInt<T>() = SafeInt<T>(1)), "Assignment SafeInt T");
|
|
|
|
// Test the casting operators
|
|
static_assert((U)(SafeInt<T>((T)1)), "Casting");
|
|
|
|
// Modulus
|
|
static_assert(SafeInt<T>((T)3) % (U)2, "Modulus");
|
|
static_assert(SafeInt<T>((T)3) % SafeInt<T>(2), "Modulus");
|
|
static_assert((SafeInt<T>((T)3) %= (U)2), "Modulus");
|
|
static_assert((SafeInt<T>((T)3) %= SafeInt<U>(2)), "Modulus");
|
|
static_assert((U)3 % SafeInt<T>(2), "Modulus");
|
|
static_assert((T)3 % SafeInt<U>(2), "Modulus");
|
|
|
|
// Multiplication
|
|
// Multiplication must either use intrinsics OR constexpr, but not both because the intrinsics aren't marked constexpr
|
|
#if !SAFEINT_USE_INTRINSICS
|
|
static_assert(SafeInt<T>((T)3) * (U)2, "Multiplication");
|
|
static_assert(SafeInt<T>((T)3) * SafeInt<T>(2), "Multiplication");
|
|
static_assert((SafeInt<T>((T)3) *= (U)2), "Multiplication");
|
|
static_assert((SafeInt<T>((T)3) *= SafeInt<U>(2)), "Multiplication");
|
|
static_assert((U)3 * SafeInt<T>(2), "Multiplication");
|
|
static_assert(((T)3 * SafeInt<U>(2)), "Multiplication");
|
|
#endif
|
|
|
|
// Division
|
|
static_assert(SafeInt<T>((T)3) / (U)2, "Division");
|
|
static_assert(SafeInt<T>((T)3) / SafeInt<T>(2), "Division");
|
|
static_assert((SafeInt<T>((T)3) /= (U)2), "Division");
|
|
#if SAFEINT_COMPILER != GCC_COMPILER
|
|
// gcc is not happy with this one
|
|
static_assert((SafeInt<T>((T)3) /= SafeInt<U>(2)), "Division");
|
|
static_assert((U)3 / SafeInt<T>(2), "Division");
|
|
#endif
|
|
static_assert(DivOperator<T,U>(), "Division");
|
|
|
|
// Addition
|
|
static_assert(SafeInt<T>((T)3) + (U)2, "Addition");
|
|
static_assert(SafeInt<T>((T)3) + SafeInt<T>(2), "Addition");
|
|
static_assert((SafeInt<T>((T)3) += (U)2), "Addition");
|
|
static_assert((SafeInt<T>((T)3) += SafeInt<U>(2)), "Addition");
|
|
static_assert((U)3 + SafeInt<T>(2), "Addition");
|
|
static_assert(AddOperator<T, U>(), "Addition");
|
|
|
|
// Subtraction
|
|
static_assert(SafeInt<T>((T)3) - (U)2, "Subtraction");
|
|
static_assert(SafeInt<T>((T)3) - SafeInt<T>(2), "Subtraction");
|
|
static_assert((SafeInt<T>((T)3) -= (U)2), "Subtraction");
|
|
static_assert((SafeInt<T>((T)3) -= SafeInt<U>(2)), "Subtraction");
|
|
static_assert((U)3 - SafeInt<T>(2), "Subtraction");
|
|
static_assert(SubOperator<T, U>(), "Subtraction");
|
|
|
|
// Shift
|
|
// Left
|
|
static_assert(SafeInt<T>((T)3) << (U)2, "Shift");
|
|
static_assert(SafeInt<T>((T)3) << SafeInt<U>(2), "Shift");
|
|
static_assert((SafeInt<T>((T)3) <<= (U)2), "Shift");
|
|
static_assert((SafeInt<T>((T)3) <<= SafeInt<U>(2)), "Shift");
|
|
static_assert(LShiftOperator<T, U>(), "Shift");
|
|
static_assert(LShiftOperator2<T, U>(), "Shift");
|
|
|
|
// Right
|
|
static_assert(SafeInt<T>((T)3) >> (U)1, "Shift");
|
|
static_assert(SafeInt<T>((T)3) >> SafeInt<U>(1), "Shift");
|
|
static_assert((SafeInt<T>((T)3) >>= (U)1), "Shift");
|
|
static_assert((SafeInt<T>((T)3) >>= SafeInt<U>(1)), "Shift");
|
|
static_assert(RShiftOperator<T, U>(), "Shift");
|
|
static_assert(RShiftOperator2<T, U>(), "Shift");
|
|
|
|
// Binary And
|
|
static_assert(SafeInt<T>((T)3) & SafeInt<T>(1), "And");
|
|
static_assert(SafeInt<T>((T)3) & (U)1, "And");
|
|
static_assert((SafeInt<T>((T)3) &= (U)(1)), "And");
|
|
static_assert((SafeInt<T>((T)3) &= SafeInt<U>(1)), "And");
|
|
static_assert(AndOperator<T, U>(), "And");
|
|
static_assert(AndOperator2<T, U>(), "And");
|
|
|
|
// Binary Xor
|
|
static_assert(SafeInt<T>((T)3) ^ SafeInt<T>(1), "Xor");
|
|
static_assert(SafeInt<T>((T)3) ^ (U)1, "Xor");
|
|
static_assert((SafeInt<T>((T)3) ^= (U)(1)), "Xor");
|
|
static_assert((SafeInt<T>((T)3) ^= SafeInt<U>(1)), "Xor");
|
|
static_assert(XorOperator<T, U>(), "Xor");
|
|
static_assert(XorOperator2<T, U>(), "Xor");
|
|
|
|
// Binary Or
|
|
static_assert(SafeInt<T>((T)3) | SafeInt<T>(1), "Or");
|
|
static_assert(SafeInt<T>((T)3) | (U)1, "Or");
|
|
static_assert((SafeInt<T>((T)3) |= (U)(1)), "Or");
|
|
static_assert((SafeInt<T>((T)3) |= SafeInt<U>(1)), "Or");
|
|
static_assert(OrOperator<T, U>(), "Or");
|
|
static_assert(OrOperator2<T, U>(), "Or");
|
|
|
|
// Comparisons
|
|
// Less than
|
|
static_assert(SafeInt<T>((T)2) < (U)3, "LT");
|
|
static_assert((T)2 < SafeInt<U>((U)3), "LT");
|
|
static_assert(SafeInt<T>((T)2) < SafeInt<U>((U)3), "LT");
|
|
|
|
// Less than or equal
|
|
static_assert(SafeInt<T>((T)2) <= (U)3, "LTE");
|
|
static_assert((T)2 <= SafeInt<U>((U)3), "LTE");
|
|
static_assert(SafeInt<T>((T)2) <= SafeInt<U>((U)3), "LTE");
|
|
|
|
// Greater than
|
|
static_assert(SafeInt<T>((T)4) > (U)3, "GT");
|
|
static_assert((T)4 > SafeInt<U>((U)3), "GT");
|
|
static_assert(SafeInt<T>((T)4) > SafeInt<U>((U)3), "GT");
|
|
|
|
// Less than or equal
|
|
static_assert(SafeInt<T>((T)4) >= (U)3, "GTE");
|
|
static_assert((T)4 >= SafeInt<U>((U)3), "GTE");
|
|
static_assert((SafeInt<T>((T)4) >= SafeInt<U>((U)3)), "GTE");
|
|
|
|
// Equals
|
|
static_assert(SafeInt<T>((T)3) == (U)3, "EQ");
|
|
static_assert((T)3 == SafeInt<U>((U)3), "EQ");
|
|
static_assert(SafeInt<T>((T)3) == SafeInt<U>((U)3), "EQ");
|
|
|
|
// Not equal
|
|
static_assert(SafeInt<T>((T)4) != (U)3, "NEQ");
|
|
static_assert((T)4 != SafeInt<U>((U)3), "NEQ");
|
|
static_assert(SafeInt<T>((T)4) != SafeInt<U>((U)3), "NEQ");
|
|
|
|
// Now need coverage for these:
|
|
static_assert(SafeCastTest<T,U>(), "SafeCast");
|
|
static_assert(SafeEquals((T)2, (U)2), "SafeEquals");
|
|
static_assert(SafeNotEquals((T)3, (U)2), "SafeNotEquals");
|
|
static_assert(SafeGreaterThan((T)3, (U)2), "SafeGreaterThan");
|
|
static_assert(SafeGreaterThanEquals((T)3, (U)2), "SafeGreaterThanEquals");
|
|
static_assert(SafeLessThan((T)1, (U)2), "SafeLessThan");
|
|
static_assert(SafeLessThanEquals((T)1, (U)2), "SafeLessThanEquals");
|
|
static_assert(SafeModulusTest<T, U>(), "SafeModulus");
|
|
#if !SAFEINT_USE_INTRINSICS
|
|
static_assert(SafeMultiplyTest<T, U>(), "SafeMultiply");
|
|
#endif
|
|
static_assert(SafeDivideTest<T, U>(), "SafeDivide");
|
|
static_assert(SafeAddTest<T, U>(), "SafeAdd");
|
|
}
|
|
|
|
template <typename T>
|
|
void StaticAssertTest()
|
|
{
|
|
static_assert(SafeInt<T>() == 0, "Default constr");
|
|
static_assert(SafeInt<T>((T)1), "T constr");
|
|
static_assert(SafeInt<T>(true), "bool constr");
|
|
// Floating point will not work due to presence of fpclassify
|
|
// static_assert(SafeInt<T>((float)1.0), "float constr");
|
|
|
|
StaticAssertTU<T, char>();
|
|
StaticAssertTU<T, signed char>();
|
|
StaticAssertTU<T, unsigned char>();
|
|
StaticAssertTU<T, signed short>();
|
|
StaticAssertTU<T, unsigned short>();
|
|
StaticAssertTU<T, signed int>();
|
|
StaticAssertTU<T, unsigned int>();
|
|
StaticAssertTU<T, signed long>();
|
|
StaticAssertTU<T, unsigned long>();
|
|
StaticAssertTU<T, signed long long>();
|
|
StaticAssertTU<T, unsigned long long>();
|
|
|
|
// Special case casting
|
|
static_assert((bool)(SafeInt<T>((T)1)), "Casting");
|
|
static_assert((wchar_t)(SafeInt<T>((T)1)), "Casting");
|
|
static_assert((float)(SafeInt<T>((T)1)), "Casting");
|
|
static_assert((double)(SafeInt<T>((T)1)), "Casting");
|
|
static_assert((long double)(SafeInt<T>((T)1)), "Casting");
|
|
|
|
// Unary operations
|
|
static_assert(!SafeInt<T>((T)0), "operator !");
|
|
static_assert(++SafeInt<T>((T)1), "operator ++");
|
|
static_assert(SafeInt<T>((T)1)++, "operator ++");
|
|
static_assert(--SafeInt<T>((T)2), "operator --");
|
|
static_assert(SafeInt<T>((T)2)--, "operator --");
|
|
static_assert(~SafeInt<T>((T)0), "operator ~");
|
|
|
|
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 T ConstMultiplyTU()
|
|
{
|
|
return (SafeInt<T>(2) * (U)1) + (U(4) * SafeInt<T>(3)) + (SafeInt<T>(6) * SafeInt<T>(5));
|
|
}
|
|
|
|
template <typename T>
|
|
void ConstMultiplyT()
|
|
{
|
|
static const T c = ConstMultiplyTU< T, char >();
|
|
static const T sc = ConstMultiplyTU< T, signed char >();
|
|
static const T uc = ConstMultiplyTU< T, unsigned char >();
|
|
static const T ss = ConstMultiplyTU< T, signed short >();
|
|
static const T us = ConstMultiplyTU< T, unsigned short >();
|
|
static const T si = ConstMultiplyTU< T, signed int >();
|
|
static const T ui = ConstMultiplyTU< T, unsigned int >();
|
|
static const T sl = ConstMultiplyTU< T, signed long >();
|
|
static const T ul = ConstMultiplyTU< T, unsigned long >();
|
|
static const T sll = ConstMultiplyTU< T, signed long long >();
|
|
static const T ull = ConstMultiplyTU< T, unsigned long long >();
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 T ConstSubtractTU()
|
|
{
|
|
return (SafeInt<T>(2) - (U)1) + (U(4) - SafeInt<T>(3)) + (SafeInt<T>(6) - SafeInt<T>(5));
|
|
}
|
|
|
|
template <typename T>
|
|
void ConstSubtractT()
|
|
{
|
|
static const T c = ConstSubtractTU< T, char >();
|
|
static const T sc = ConstSubtractTU< T, signed char >();
|
|
static const T uc = ConstSubtractTU< T, unsigned char >();
|
|
static const T ss = ConstSubtractTU< T, signed short >();
|
|
static const T us = ConstSubtractTU< T, unsigned short >();
|
|
static const T si = ConstSubtractTU< T, signed int >();
|
|
static const T ui = ConstSubtractTU< T, unsigned int >();
|
|
static const T sl = ConstSubtractTU< T, signed long >();
|
|
static const T ul = ConstSubtractTU< T, unsigned long >();
|
|
static const T sll = ConstSubtractTU< T, signed long long >();
|
|
static const T ull = ConstSubtractTU< T, unsigned long long >();
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
SAFEINT_CONSTEXPR14 T ConstAddTU()
|
|
{
|
|
return (SafeInt<T>(1) + (U)2) + (U(3) + SafeInt<T>(4)) + (SafeInt<T>(5) + SafeInt<T>(6));
|
|
}
|
|
|
|
template <typename T>
|
|
void ConstAddT()
|
|
{
|
|
static const T c = ConstAddTU< T, char >();
|
|
static const T sc = ConstAddTU< T, signed char >();
|
|
static const T uc = ConstAddTU< T, unsigned char >();
|
|
static const T ss = ConstAddTU< T, signed short >();
|
|
static const T us = ConstAddTU< T, unsigned short >();
|
|
static const T si = ConstAddTU< T, signed int >();
|
|
static const T ui = ConstAddTU< T, unsigned int >();
|
|
static const T sl = ConstAddTU< T, signed long >();
|
|
static const T ul = ConstAddTU< T, unsigned long >();
|
|
static const T sll = ConstAddTU< T, signed long long >();
|
|
static const T ull = ConstAddTU< T, unsigned long long >();
|
|
}
|
|
|
|
template <typename T>
|
|
SAFEINT_CONSTEXPR14 T PrefixInc(T i)
|
|
{
|
|
return ++SafeInt<T>(i);
|
|
}
|
|
|
|
template <typename T>
|
|
SAFEINT_CONSTEXPR14 T PostfixInc(T i)
|
|
{
|
|
return SafeInt<T>(i)++;
|
|
}
|
|
|
|
template <typename T>
|
|
SAFEINT_CONSTEXPR14 void SignedOnly()
|
|
{
|
|
static_assert(-SafeInt<T>((T)1), "operator -");
|
|
}
|
|
|
|
void TestSignedOnly()
|
|
{
|
|
SignedOnly<signed char>();
|
|
SignedOnly<signed short>();
|
|
SignedOnly<signed int>();
|
|
SignedOnly<signed long>();
|
|
SignedOnly<signed long long>();
|
|
}
|
|
|
|
#endif // CPLUSPLUS_14
|
|
|
|
template <typename T>
|
|
void ConstExprTestT()
|
|
{
|
|
ConstTestT<T>();
|
|
ComparisonTestT<T>();
|
|
ConstCastTestT<T>();
|
|
|
|
#if CPLUSPLUS_STD == CPLUSPLUS_14
|
|
StaticAssertTest<T>();
|
|
TestSignedOnly();
|
|
|
|
ConstAddT<T>();
|
|
ConstSubtractT<T>();
|
|
ConstMultiplyT<T>();
|
|
#endif
|
|
}
|
|
|
|
void ConstExprTest()
|
|
{
|
|
ConstExprTestT<char>();
|
|
ConstExprTestT<signed char>();
|
|
ConstExprTestT<unsigned char>();
|
|
ConstExprTestT<signed short>();
|
|
ConstExprTestT<unsigned short>();
|
|
ConstExprTestT<signed int>();
|
|
ConstExprTestT<unsigned int>();
|
|
ConstExprTestT<signed long>();
|
|
ConstExprTestT<unsigned long>();
|
|
ConstExprTestT<signed long long>();
|
|
ConstExprTestT<unsigned long long>();
|
|
|
|
// Catch the SafePtrDiff function, since it is marked. Can't think of a scenario for this being constexpr, though.
|
|
const char* p1 = (char*)1;
|
|
const char* p2 = nullptr;
|
|
|
|
static const SafeInt<ptrdiff_t> pt = SafePtrDiff(p1, p2);
|
|
if (pt > 0)
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
void ConstExpr()
|
|
{
|
|
TestConstExpr::ConstExprTest();
|
|
} |