Ker*_* SB 14
这是一个想法:我们需要使用"通常的算术转换":
如果两种类型都是无符号的,那就进行比较.
如果两种类型都签名,只需比较.
如果签名不同且签名值为负,我们就完成了.
实际工作适用于两个值均为非负且具有不同符号的情况.当无符号值大于有符号类型的最大有符号值时,我们就完成了.否则,可以将无符号值转换为带符号的类型而不更改值,并进行比较.
这是一个尝试:
#include <type_traits>
#include <limits>
template <bool SameSignedness> struct IntComparerImpl;
template <typename T, typename U>
constexpr bool IntCompare(T x, U y)
{
return IntComparerImpl<std::is_signed<T>::value ==
std::is_signed<U>::value>::compare(x, y);
}
// same signedness case:
template <> struct IntComparerImpl<true>
{
template<typename T, typename U>
static constexpr bool compare(T t, U u)
{
return t < u;
}
};
// different signedness case:
template <> struct IntComparerImpl<false>
{
// I1 is signed, I2 is unsigned
template <typename I1, typename I2>
static constexpr typename std::enable_if<std::is_signed<I1>::value, bool>::type
compare(I1 x, I2 y)
{
return x < 0
|| y > std::numeric_limits<I1>::max()
|| x < static_cast<I1>(y);
}
// I1 is unsigned, I2 is signed
template <typename I1, typename I2>
static typename std::enable_if<std::is_signed<I2>::value, bool>::type
compare(I1 x, I2 y)
{
return !(y < 0)
&& !(x > std::numeric_limits<I2>::max())
&& static_cast<I2>(x) < y;
}
};
Run Code Online (Sandbox Code Playgroud)