确定数字类型A是否可以转换为数字类型B.

Ale*_*ler 6 c++ types casting c++11

给出两种数字类型FromTo.以下代码是否实际确定是否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.
};
Run Code Online (Sandbox Code Playgroud)

R. *_*des 2

编译器现在内置了此功能:使用列表初始化时不允许缩小转换。

您可以基于 和 编写传统的表达式测试器特征,并可能使用和To { std::declval<From>() }添加额外的检查。std::is_integralstd::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)) {};
Run Code Online (Sandbox Code Playgroud)

从理论上讲,这应该可行,但目前看来 GCC 和 clang 都没有做到这一点。

  • 好吧,如果您在 gcc-4.7.1 中尝试 `int x{1.5};`,它只会报告警告,而不是应有的错误。 (2认同)