是否存在检查类型值域包含关系的type trait?Boost有无相关实现?
嘿,这个问题问到点子上了!我来给你详细说说关于这个类型特性的情况:
Boost库有没有现成的解决方案?
很遗憾,Boost库并没有直接提供你需要的is_included_in<T, U>这种类型特性。Boost.TypeTraits里的is_convertible之类的工具,只关心类型之间能不能做语法上的转换,完全不考虑转换后会不会丢失精度或者溢出——比如double转float语法上是允许的,但值域明显不包含,这和你要的“每个T的值都能被U准确存储”的语义完全不是一回事。
那只能自己实现了?(兼容C++03的思路)
没错,因为你不能用C11,得基于C03的特性来写。核心是利用SFINAE(替换失败不是错误)机制,再结合<limits>里的数值极限来判断类型值域的包含关系。
先理清楚不同类型组合的判断逻辑:
- 整数转整数:要考虑有符号/无符号的匹配,以及T的最小、最大值都在U的范围内
- 整数转浮点数:需要浮点数的有效位数足够容纳整数的所有位,同时值域范围也得覆盖
- 浮点数转浮点数:要求U的范围更大、精度更高(或者至少持平)
- 布尔类型:布尔值只有0和1,能转成任何整数或浮点数,所以直接返回true
这里给你一个C++03兼容的简化实现示例,用到了Boost的一些基础type traits来辅助判断:
#include <limits> #include <boost/type_traits/is_integral.hpp> #include <boost/type_traits/is_floating_point.hpp> #include <boost/type_traits/is_signed.hpp> #include <boost/utility/enable_if.hpp> // 基础模板,默认返回false template <typename T, typename U> struct is_included_in { static const bool value = false; }; // 整数转整数的特化版本 template <typename T, typename U> struct is_included_in<T, U, typename boost::enable_if_c< boost::is_integral<T>::value && boost::is_integral<U>::value >::type> { static const bool value = // 同符号的情况:直接比较值域边界 (boost::is_signed<T>::value == boost::is_signed<U>::value) ? (std::numeric_limits<T>::min() >= std::numeric_limits<U>::min() && std::numeric_limits<T>::max() <= std::numeric_limits<U>::max()) : // 无符号转有符号:只要无符号的最大值不超过有符号的最大值 (!boost::is_signed<T>::value && boost::is_signed<U>::value) ? (std::numeric_limits<T>::max() <= std::numeric_limits<U>::max()) : false; // 有符号转无符号默认不安全(除非T值域全非负,但编译期没法直接判断) }; // 整数转浮点数的特化版本 template <typename T, typename U> struct is_included_in<T, U, typename boost::enable_if_c< boost::is_integral<T>::value && boost::is_floating_point<U>::value >::type> { static const bool value = // 浮点数有效位数足够容纳整数的所有位,且值域覆盖 (std::numeric_limits<U>::digits >= std::numeric_limits<T>::digits) && (std::numeric_limits<T>::min() >= std::numeric_limits<U>::min()) && (std::numeric_limits<T>::max() <= std::numeric_limits<U>::max()); }; // 浮点数转浮点数的特化版本 template <typename T, typename U> struct is_included_in<T, U, typename boost::enable_if_c< boost::is_floating_point<T>::value && boost::is_floating_point<U>::value >::type> { static const bool value = // U的范围更大,且精度不低于T (std::numeric_limits<U>::min() <= std::numeric_limits<T>::min()) && (std::numeric_limits<U>::max() >= std::numeric_limits<T>::max()) && (std::numeric_limits<U>::digits >= std::numeric_limits<T>::digits); }; // 布尔类型转任意类型的特殊处理 template <typename U> struct is_included_in<bool, U> { static const bool value = true; };
这个实现是简化版,你可以根据自己的实际需求调整细节——比如如果需要处理“有符号类型值域全是非负”的特殊情况,可能还要加额外的判断逻辑,但编译期能做到的判断毕竟有限,这个版本已经能覆盖你给出的示例场景了。
内容的提问来源于stack exchange,提问作者Caduchon
相关产品推荐
相关产品推荐

