【问题标题】:is there type trait that show if one type might contain value of other type是否存在显示一种类型是否可能包含另一种类型的值的类型特征
【发布时间】:2017-11-01 21:28:19
【问题描述】:

是否有一些类型特征可以检查一个整数类型是否可以保持其他整数类型的值而不会丢失数据?

例如int32_t 可能包含uint16_tuint8_tint32_tint16_tint8_t

但是int32_t不能容纳uint32_t,也不能容纳uint64_tint64_t

更新

我提出了幼稚的解决方案,并将其发布为答案。我知道可以使用std::is_same,但我认为这种方式更具表现力。

【问题讨论】:

    标签: c++ c++11 c++14


    【解决方案1】:

    我们可以在这里利用现有的语言规则。

    对于list-initialization,缩小转换的格式不正确。我们正在尝试检测缩小转换。因此,void_t!

    template <class X, class Y, class = void>
    struct can_hold : std::false_type { };
    
    template <class X, class Y>
    struct can_hold<X, Y,
        void_t<decltype(X{std::declval<Y>()})>>
    : std::true_type { };
    

    【讨论】:

    • 有趣的是,这似乎适用于 g++,尽管 g++ 出于某种原因通常将缩小转换视为警告而不是错误。
    • @aschepler 也许 gcc 比我们想象的更聪明。如果看到缩小转换,则替换失败,然后仅在未找到匹配项时尝试使用失败的候选者,并发出警告。
    【解决方案2】:

    天真的解决方案:


    #include <type_traits>
    #include <cstdint>
    
    
    
    template<typename A, typename B>
    struct can_hold : std::false_type{};
    
    
    
    template<>
    struct can_hold<int8_t,int8_t> : std::true_type{};
    
    
    
    template<>
    struct can_hold<int16_t,int8_t> : std::true_type{};
    
    template<>
    struct can_hold<int16_t,int16_t> : std::true_type{};
    
    template<>
    struct can_hold<int16_t,uint8_t> : std::true_type{};
    
    
    
    template<>
    struct can_hold<int32_t,int8_t> : std::true_type{};
    
    template<>
    struct can_hold<int32_t,int16_t> : std::true_type{};
    
    template<>
    struct can_hold<int32_t,int32_t> : std::true_type{};
    
    template<>
    struct can_hold<int32_t,uint8_t> : std::true_type{};
    
    template<>
    struct can_hold<int32_t,uint16_t> : std::true_type{};
    
    
    
    template<>
    struct can_hold<int64_t,int8_t> : std::true_type{};
    
    template<>
    struct can_hold<int64_t,int16_t> : std::true_type{};
    
    template<>
    struct can_hold<int64_t,int32_t> : std::true_type{};
    
    template<>
    struct can_hold<int64_t,int64_t> : std::true_type{};
    
    template<>
    struct can_hold<int64_t,uint8_t> : std::true_type{};
    
    template<>
    struct can_hold<int64_t,uint16_t> : std::true_type{};
    
    template<>
    struct can_hold<int64_t,uint32_t> : std::true_type{};
    
    
    
    template<>
    struct can_hold<uint8_t,uint8_t> : std::true_type{};
    
    
    
    template<>
    struct can_hold<uint16_t,uint8_t> : std::true_type{};
    
    template<>
    struct can_hold<uint16_t,uint16_t> : std::true_type{};
    
    
    
    template<>
    struct can_hold<uint32_t,uint8_t> : std::true_type{};
    
    template<>
    struct can_hold<uint32_t,uint16_t> : std::true_type{};
    
    template<>
    struct can_hold<uint32_t,uint32_t> : std::true_type{};
    
    
    
    template<>
    struct can_hold<uint64_t,uint8_t> : std::true_type{};
    
    template<>
    struct can_hold<uint64_t,uint16_t> : std::true_type{};
    
    template<>
    struct can_hold<uint64_t,uint32_t> : std::true_type{};
    
    template<>
    struct can_hold<uint64_t,uint64_t> : std::true_type{};
    
    
    
    template<>
    struct can_hold<float,float> : std::true_type{};
    
    template<>
    struct can_hold<double,float> : std::true_type{};
    
    template<>
    struct can_hold<double,double> : std::true_type{};
    
    
    
    int main(){
    }
    

    【讨论】:

    • 我知道浮点是一个额外的好处,但您可能还想在浮点转换中添加积分(float 可以保存 16 位整数,double 可以保存 32 位整数) . 更新:即根据最低要求/IEEE。
    • @ArneVogel 但它们可能不符合 IEEE 754 =) 参见,例如,is_iec559
    • @Sergey.quixoticaxis.Ivanov 我不明白你的意思。如果 IEEE 754 float 不能容纳任何 16 位整数,您应该很容易想出一个作为反例。
    • @ArneVogel 我的意思是没有理由实现 int 到浮点转换,因为 C++ 对浮点类型几乎没有保证。浮点类型可以符合 IEEE,也可以不符合。 float 不必是“IEEE 754 浮点数”
    • 抱歉回复晚了,C/C++ 不强制要求 IEEE 754 是对的。但是,C 标准(以及间接的 C++ 标准)确实要求至少 6 位小数的精度float (FLT_DIG) 的数字和 double (DBL_DIG) 的 10。这意味着我提到的往返保证是无损的。
    猜你喜欢
    • 2012-04-11
    • 2011-05-07
    • 1970-01-01
    • 2021-10-16
    • 1970-01-01
    • 2010-12-27
    • 2023-03-30
    • 1970-01-01
    • 2021-12-26
    相关资源
    最近更新 更多