给定两种数字类型From
和To
。以下代码是否实际确定类型From
的任何值是否可以表示为类型To
的值而不会丢失信息?如果是,是否有更短或更易读的确定方法?
template <class From, class To>
struct can_cast
{
static const bool value =
(std::numeric_limits<From>::is_integer || // either From is an integer type OR
std::is_floating_point<To>::value) && // ...they're both floating point types AND
(std::numeric_limits<From>::is_signed == false || // either From is unsigned OR
std::numeric_limits<To>::is_signed == true) && // ...they're both signed AND
(std::numeric_limits<From>::digits < std::numeric_limits<To>::digits || // To has more bits for digits than From OR
std::numeric_limits<From>::digits == std::numeric_limits<To>::digits && // To and From have same number of bits, but
std::numeric_limits<From>::is_signed == std::numeric_limits<To>::is_signed); // they're either both signed or both unsigned.
};
答案 0 :(得分:2)
编译器现在内置了此功能:使用list-initialisation时不允许缩小转换。
您可以根据To { std::declval<From>() }
编写传统的表达式测试程序特征,并可能使用std::is_integral
和std::is_floating_point
添加其他检查。
template <typename T>
struct sfinae_true : std::true_type {};
struct can_cast_tester {
template <typename From, typename To>
sfinae_true<decltype(To { std::declval<From>() })> static test(int);
template <typename...>
std::false_type static test(...);
};
template <typename From, typename To>
struct can_cast // terrible name
: decltype(can_cast_tester::test<From, To>(0)) {};
从理论上讲,这应该有效,但目前似乎GCC和clang都没有做对。