什么是完全类型安全和最灵活的(根据constexpr
)方式来比较两个通常意外(不同)类型的整数?比较任意类型的整数
12
A
回答
12
这里有一个想法:我们需要使用“通常的算术转换”:
如果两种类型是无符号,只是比较。
如果两种类型都有符号,就比较一下。
如果签名的不同并且签名值为负数,我们就完成了。
实际工作适用于两个值都是非负数且签名不同的情况。当无符号值大于签名类型的最大有符号值时,我们就完成了。否则,可以将无符号值转换为带符号类型而不更改值并进行比较。
下面是一个尝试:
#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>(y) < x;
}
};
1
My own solution这是(根据N3485.pdf§5):
#include <type_traits>
#include <limits>
#include <utility>
#include <cstdint>
#include <cstdlib>
template< typename L, typename R >
inline constexpr
typename std::enable_if< (std::is_signed<L>::value && !std::is_signed<R>::value), bool >::type
less(L const & lhs, R const & rhs)
{
static_assert(std::is_integral<L>::value,
"lhs value must be of integral type");
static_assert(std::is_integral<R>::value,
"rhs value must be of integral type");
using T = typename std::common_type< L, R >::type;
return (lhs < static_cast<L>(0)) || (static_cast< T const & >(lhs) < static_cast< T const & >(rhs));
}
template< typename L, typename R >
inline constexpr
typename std::enable_if< (!std::is_signed<L>::value && std::is_signed<R>::value), bool >::type
less(L const & lhs, R const & rhs)
{
static_assert(std::is_integral<L>::value,
"lhs value must be of integral type");
static_assert(std::is_integral<R>::value,
"rhs value must be of integral type");
using T = typename std::common_type< L, R >::type;
return !(rhs < static_cast<R>(0)) && (static_cast< T const & >(lhs) < static_cast< T const & >(rhs));
}
template< typename L, typename R >
inline constexpr
typename std::enable_if< (std::is_signed<L>::value == std::is_signed<R>::value), bool >::type
less(L const & lhs, R const & rhs)
{
static_assert(std::is_integral<L>::value,
"lhs value must be of integral type");
static_assert(std::is_integral<R>::value,
"rhs value must be of integral type");
return lhs < rhs;
}
namespace
{
static_assert(less(1, 2), "0");
static_assert(less(-1, std::numeric_limits<std::uintmax_t>::max()), "1");
static_assert(less< std::int8_t, std::uintmax_t >(-1, std::numeric_limits<std::uintmax_t>::max()), "2");
static_assert(less< std::intmax_t, std::uint8_t >(-1, std::numeric_limits<std::uint8_t>::max()), "3");
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
static_assert(!(-1 < std::numeric_limits< unsigned long >::max()), "4");
#pragma GCC diagnostic pop
static_assert(less(-1, std::numeric_limits< unsigned long >::max()), "5");
}
int main()
{
return EXIT_SUCCESS;
}
相关问题
- 1. std :: pow与整数参数比较,整数类型比较
- 2. 用于比较任意数组类型的库代码?
- 3. 枚举类型的任意整数值
- 4. 比较任意类型的两个对象的等价性
- 5. 任意类型的数组
- 6. 比较类型
- 7. 比较整数,类实例的数组
- 8. NumPy数据类型比较
- 9. 蟒数据类型比较
- 10. 比较数据类型
- 11. 比较整数
- 12. 比较整数
- 13. 比较整数
- 14. 整数比较
- 15. Scala:比较类型
- 16. Python类型比较
- 17. Javascript类型比较
- 18. 意外的结果时,比较整形
- 19. C++类中的任意数据类型
- 20. 比较返回类型布尔和整数的值
- 21. 高效整型比较函数
- 22. 不使用比较的数据类型的比较
- 23. 比较整数的数字
- 24. 泛型类型比较
- 25. 比较模型类型Laravel
- 26. f#泛型类型比较
- 27. 比较泛型类型Java
- 28. vb.net比较泛型类型
- 29. Coq:Boolean整数比较
- 30. 整数比较C#
似乎对代码审查更适合我 –
^是 - 如果你为此创建了单元测试,并产生了意想不到的行为,那么这将是正确的地方。 –
查看['std :: common_type'](http://en.cppreference.com/w/cpp/types/common_type)。这会给你一个你可以在比较之前投给双方的类型。 – cHao