写点什么

C++--- 类型萃取 ---is_integral && is_floating_point

作者:桑榆
  • 2022-11-25
    广东
  • 本文字数:2382 字

    阅读完需:约 8 分钟

背景

定义在<type_traits>中,用于判断一个类型是否是 int 类型,是否浮点类型,属于基础的类型判断。

代码实现

gcc 官网:https://gcc.gnu.org/

gcc 代码下载:https://mirrors.tuna.tsinghua.edu.cn/help/gcc.git/

gcc 版本代码:gcc-7.5.0(branch 分支)

文件位置:gcc/libstdc++-v3/include/std/type_traits

注意:以下的代码实现省略了一些宏定义部分,实际的代码还是参考 gcc 源码,这里仅用作相关原理分析。

实现分析

is_integral

  template<typename>    struct __is_integral_helper    : public false_type { };
template<> struct __is_integral_helper<bool> : public true_type { };
template<> struct __is_integral_helper<char> : public true_type { };
...signed char......unsigned char......wchar_t......char16_t......char32_t......short......unsigend short......int......unsigend int......long......unsigned long......long long......unsigned long long...
/// is_integral template<typename _Tp> struct is_integral : public __is_integral_helper<typename remove_cv<_Tp>::type>::type { };
复制代码

可以看到,实际上还是借助了模板特化的方法,对一系列 int 类型(bool,char...unsigned long long ),直接特化为继承 true_type 的类(value 值为 true),原始的类模板直接继承 false_type 类(value 值为 false)。最后在传入各个特化模板之前,需要先调用 remove_cv 去除 const 和 volatile 属性。

is_floating_point

  template<typename>    struct __is_floating_point_helper    : public false_type { };
template<> struct __is_floating_point_helper<float> : public true_type { };
template<> struct __is_floating_point_helper<double> : public true_type { };
template<> struct __is_floating_point_helper<long double> : public true_type { };
#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) template<> struct __is_floating_point_helper<__float128> : public true_type { };#endif
/// is_floating_point template<typename _Tp> struct is_floating_point : public __is_floating_point_helper<typename remove_cv<_Tp>::type>::type { };
复制代码

is_floating_point 的方式也是一致的,针对 float/double/long double/__float128 做了特化版本,同样的,使用 remove_cv 去除 const 和 volatile 属性。

使用案例

#include <iostream>             #include <type_traits>                                                                                                       class EmptyClass{};                                                                                                                                                       enum EnumTest : int{};                                                                                                                                            struct IntStruct{int x;};                                                                            using IntStructMemberType = decltype(IntStruct::x);                                                                                                                                                                                       int main(){                                                                        std::cout << std::boolalpha;                                                     std::cout << "------is_integral------" << std::endl;                                     std::cout << "int:" << std::is_integral<int>::value << std::endl;    std::cout << "char:" << std::is_integral<char>::value << std::endl;    std::cout << "const volatile int:" << std::is_integral<const volatile int>::value << std::endl;                          std::cout << "EmptyClass:" << std::is_integral<EmptyClass>::value << std::endl;    std::cout << "EnumTest:" << std::is_integral<EnumTest>::value << std::endl;    std::cout << "IntStructMemberType:" << std::is_integral<IntStructMemberType>::value << std::endl;                                          std::cout << "------is_floating_point------" << std::endl;    std::cout << "int:" << std::is_floating_point<int>::value << std::endl;                                                                                  std::cout << "float:" << std::is_floating_point<float>::value << std::endl;    std::cout << "float&:" << std::is_floating_point<float&>::value << std::endl;    std::cout << "EmptyClass:" << std::is_floating_point<EmptyClass>::value << std::endl;                                                          return 0;}
复制代码

需要注意的点:

  • 空类并不是 int 型;

  • 继承 int 型的枚举不是 int 型;

  • 类中对应成员变量的类型与元类型保持一致;

  • 空类不是 float 型;

  • float&不是 float 型,因为有引用的存在

总结

is_integral 和 is_floating_point 利用了模板特化的方式,指定了一些固定的类型可以返回 true,其他类型返回 false.

is_integral :bool/char/signed char/unsigned char/wchar_t/char16_t/char32_t/short/unsigend short/int/unsigend int/long/unsigned long/long long/unsigned long long

is_floating_point :loat/double/long double/__float128

发布于: 刚刚阅读数: 4
用户头像

桑榆

关注

北海虽赊,扶摇可接;东隅已逝,桑榆非晚! 2020-02-29 加入

Android手机厂商-相机软件系统工程师 爬山/徒步/Coding

评论

发布
暂无评论
C++---类型萃取---is_integral && is_floating_point_C++ STL_桑榆_InfoQ写作社区