如何判断整数类型间的类型转换是否安全无数据损失?
整数类型间的安全转换判断方案
要判断整数类型B能否安全转换为A(无数据丢失),核心标准是:B的所有可能取值都能被A精确表示。以下是基于C++模板元编程的实现方案,仅针对整数类型:
核心逻辑分情况讨论
- 相同类型转换:必然安全,比如
int转int。 - 同符号不同位数转换:若目标类型
A的有效位数(不含符号位)大于等于源类型B的有效位数,则转换安全(比如int32_t转int64_t),反之则不安全(比如int64_t转int32_t)。 - 无符号类型转有符号类型:只有当无符号类型
B的最大值不超过有符号类型A的最大值时,转换才安全(比如uint32_t转int64_t),否则会出现数值溢出变成负数(比如uint32_t转int32_t)。 - 有符号类型转无符号类型:除了
bool转无符号类型(仅0和1,无溢出),其他有符号类型转无符号都会导致负数被转换为超大无符号值,数据丢失,因此默认不安全。
代码实现
#include <limits> #include <type_traits> // 默认模板:转换不安全 template <typename Target, typename Source> struct is_safe_integer_conversion : std::false_type {}; // 相同类型的特化:转换安全 template <typename T> struct is_safe_integer_conversion<T, T> : std::true_type {}; // 同符号整数类型的转换判断 template <typename Target, typename Source> requires (std::is_signed_v<Target> == std::is_signed_v<Source> && std::is_integral_v<Target> && std::is_integral_v<Source>) struct is_safe_integer_conversion<Target, Source> : std::bool_constant< std::numeric_limits<Target>::digits >= std::numeric_limits<Source>::digits > {}; // 无符号源类型转有符号目标类型的判断 template <typename Target, typename Source> requires (std::is_signed_v<Target> && std::is_unsigned_v<Source> && std::is_integral_v<Target> && std::is_integral_v<Source>) struct is_safe_integer_conversion<Target, Source> : std::bool_constant< std::numeric_limits<Source>::max() <= std::numeric_limits<Target>::max() > {}; // bool转任何整数类型都安全 template <typename Target> requires std::is_integral_v<Target> struct is_safe_integer_conversion<Target, bool> : std::true_type {}; // 辅助变量模板,简化使用 template <typename Target, typename Source> constexpr bool is_safe_integer_conversion_v = is_safe_integer_conversion<Target, Source>::value;
测试示例
// 安全转换的情况 static_assert(is_safe_integer_conversion_v<int64_t, int32_t>); // int32_t转int64_t static_assert(is_safe_integer_conversion_v<uint64_t, uint32_t>); // uint32_t转uint64_t static_assert(is_safe_integer_conversion_v<int64_t, uint32_t>); // uint32_t转int64_t static_assert(is_safe_integer_conversion_v<unsigned int, bool>); // bool转unsigned int // 不安全转换的情况 static_assert(!is_safe_integer_conversion_v<int32_t, int64_t>); // int64_t转int32_t static_assert(!is_safe_integer_conversion_v<uint32_t, uint64_t>); // uint64_t转uint32_t static_assert(!is_safe_integer_conversion_v<int32_t, uint32_t>); // uint32_t转int32_t static_assert(!is_safe_integer_conversion_v<uint32_t, int32_t>); // int32_t转uint32_t
关键细节说明
- 使用
std::numeric_limits::digits而非sizeof:digits代表类型的有效位数(有符号类型不含符号位,无符号类型等于总位数),能更准确判断取值范围的容纳能力。 - 利用C++20的
requires约束:确保模板仅作用于整数类型,避免非整数类型的误匹配(比如你提到的int转double属于浮点类型转换,不在本次整数范围讨论内)。
内容的提问来源于stack exchange,提问作者lorem1213
相关产品推荐
相关产品推荐

