• 第17课 类型萃取(1)_基本的type_traits


    1. type_traits类型萃取

    (1)type_traits通过定义一些结构体或类并利用模板类特化和偏特化的能力,给类型赋予一些特性,这些特性根据类型的不同而异。在程序设计中可以使用这些traits来判断一个类型的一些特性,引发C++的函数重载机制,实现同一种操作因类型不同而异的效果。

    (2)type_traits提供了丰富的编译期计算、查询、判断、转换和选择的帮助类。

    (3)type_traits的类型选择功能,在一定程序上可以消除冗长的switch-cast或if-else的语句。提高代码可维护性。type_traits的类型判断功能,在编译期可以检查出是否是正确的类型,以能编写更安全的代码。

    【实例分析】部分类型萃取的实现(类模板)

    //#include <iostream>
    //using namespace std;
    /*********************const/volatile************************/
    //remove const
    template<typename _Tp>  //泛化
    struct remove_const
    {
        typedef _Tp   type;
    };
    
    template<typename _Tp>
    struct remove_const<_Tp const> //特化
    {
        typedef _Tp type;
    };
    
    //remove_volatile
    template<typename _Tp>  //泛化
    struct remove_volatile
    {
        typedef _Tp  type;
    };
    
    template<typename _Tp>
    struct remove_volatile<_Tp volatile>  //特化
    {
        typedef _Tp  type;
    };
    
    //remove_cv
    template<typename _Tp>
    struct remove_cv
    {
        typedef typename
        remove_const<typename remove_volatile<_Tp>::type>::type  type;
    };
    
    //add_const
    template<typename _Tp>
    struct add_const
    {
        typedef _Tp const type;
    };
    
    /***********************integral_constant*************************/
    //常量包装类型
    template <class T, T v>
    struct integral_constant
    {
        static const T     value = v;
        typedef T          value_type;
        typedef integral_constant<T, v> type;
    };
    
    //定义true和false两个类型
    typedef integral_constant<bool, true>  true_type;
    typedef integral_constant<bool, false> false_type;
    
    template<typename> //泛化
    struct __is_void_helper : public false_type{};
    
    template<>  //特化
    struct __is_void_helper<void> : public true_type{};
    
    //is_void
    template<typename _Tp>
    struct is_void : public __is_void_helper<typename remove_cv<_Tp>::type>::type{};
    
    /***********************integral*************************/
    template<typename>    //泛化
    struct __is_integral_helper : public false_type{};
    
    template<>  //特化: bool是intergal类型
    struct __is_integral_helper<bool> : public true_type{};
    
    template<>  //特化: char是intergal类型
    struct __is_integral_helper<char> : public true_type{};
    
    template<>  //特化: int是intergal类型
    struct __is_integral_helper<int> : public true_type{};
    
    template<>  //特化: usigned long long是intergal类型
    struct __is_integral_helper<unsigned long long> : public true_type{};
    
    //...
    
    //is_integral
    template<typename _Tp>
    struct is_integral : public __is_integral_helper<typename remove_cv<_Tp>::type>::type{};
    
    //is_const
    template <class _Tp> 
    struct is_const : public integral_constant<bool, false> {};
    
    template <class _Tp>
    struct is_const<_Tp const> : public integral_constant<bool, true> {};
    
    /********************enum/class/union**********************/
    //is_enum  注意:__is_enum是编译器内置类型
    template<typename _Tp>
    struct is_enum : public integral_constant<bool, __is_enum(_Tp)>{};
    
    //is_union 注意:__is_union是编译器内置类型
    template<typename _Tp>
    struct is_union : public integral_constant<bool, __is_union(_Tp)>{};
    
    //is_class 注意:__is_class是编译器内置类型
    template<typename _Tp>
    struct is_class : public integral_constant<bool, __is_class(_Tp)>{};
    
    //is_pod: 注意:__is_pod是编译器内置类型
    template<typename _Tp>
    struct is_pod : public integral_constant<bool, __is_pod(_Tp)>{};
    
    int main()
    {
        return 0;
    }

    2. 类型判断

    (1)基本类型(类模板判断T是否是相应的类型

      ①is_void、is_integral、is_array、is_floating_point(浮点)、 is_pointer

      ②is_enum、is_union、is_class

      ③is_lvalue_reference、is_rvalue_reference

      ④is_function、is_member_object_pointer(成员对象指针)、is_member_function_pointer(成员函数指针)

    (2)复合类型(类模板

      ①is_fundamental:是否是整型、浮点、void或null_ptr类型。

      ②is_arithemetic:是否是整型和浮点类型

      ③is_scalar:是否是arithemetic、enumeration、pointer、pointer to member或std::nullptr_t类型。

      ④is_object:是否为对象类型(不是函数、引用或void)

      ⑤is_compound:是否非fundamental类型构造的

      ⑥is_reference:是否为引用(含左值引用和右值引用)

      ⑦is_member_pointer:是否是成员指针(即非静态成员对象或函数的指针)

    (3)类型的属性

      ①is_const、is_volatile、is_literal_type、is_signed、is_unsigned。

      ②is_trivial、is_trivially_copyable、is_standart_layout(标准内存布局,一般用于跨语言的兼容)、is_pod、is_empty(空类)

      ③is_polymorphic(是否有虚函数)、is_abstract(是否是抽象类)

    3. 两个类型之间的关系

    (1)is_same<T, U>: T和U的类型是否相同

    (2)is_base_of<Base, Derived>:Base是否为Derived类型的基类

    (3)is_convertible<From, To>:From是否能转为To模板参数类型

    【编程实验】基本type_traits和判断两个类型之间的关系

    #include <iostream>
    
    using namespace std;
    
    class Parent{};
    class Child : public Parent{}; //class Child : Parent{},为private继承
    class Alone{};
    
    int main()
    {
        cout << std::boolalpha; //以下的0、1按false和true格式输出
        
        /*基本的type_traits用法*/
        cout << is_const<int>::value << endl;         //false
        cout << is_const<const int>::value << endl;   //true
        cout << is_const<const int&>::value << endl;  //false
        cout << is_const<const int*>::value << endl;  //false
        cout << is_const<int* const>::value << endl;  //true
        
        /*is_same用法*/
        cout << is_same<int, int>::value << endl;         //true
        cout << is_same<int, unsigned int>::value << endl;//false
        cout << is_same<int, signed int>:: value << endl; //true
        
        /*is_base_of*/
        cout << is_base_of<Parent, Child>:: value << endl; //true
        cout << is_base_of<Child, Parent>:: value << endl; //false
        cout << is_base_of<Parent, Alone>:: value << endl; //false
        
        /*is_convertible<From, To>用法:判断From类型是否可以转为To类型*/
        cout << is_convertible<Parent*, Child*>:: value << endl; //false
        cout << is_convertible<Child*, Parent*>:: value << endl; //true
        cout << is_convertible<Parent*, Alone*>:: value << endl; //false    
        return 0;
    }

    4. 类型转换traits

    (1)const-volatile限定符

      ①remove_cv<T>、remove_const<T>、remove_volatile<T>

      ②add_cv<T>、add_const<T>、add_volatile<T>

    (2)引用: remove_reference<T>、add_lvalue_reference<T>、add_rlvalue_reference。

    (3)指针: remove_pointer<T>、add_pointer<T>

    (4)数组:remove_extent<T>移除数组顶层维度、remove_all_extents<T>移除所有维度。

    (5)其它

      ①decay<T>类型退化,主要用移除引用、cv符及为函数或数组添加指针。其转换规则如下。

        A.先移除T的类型引用,得到类型U,U定义为remove_reference<T>::type

        B.如果is_array<U>::value为true,最终转换为remove_extent<U>::type*

        C.否则,如果is_function<U>::value为true,转换为add_pointer<U>::type

        D.否则,转换为remove_cv<U>::type

      ②common_type<T1, T2, T3…>:获取公共类型

    【编程实验】类型转换traits

    #include <iostream>
    #include <memory>
    
    using namespace std;
    //类型转换type_traits
    
    //根据模板参数类创建对象时,要注意移除cv和引用
    template<typename T>
    class Test
    {
        //typedef typename std::remove_cv<typename std::remove_reference<T>::type>::type U;  //移除可能的引用和cv    
        //以上的等价写法
        typedef typename std::decay<T>::type U; //先移除T的引用,再移除cv符,
        
        std::unique_ptr<U> m_ptr; //m_ptr智能指针
        
    public:
        Test(): m_ptr(new U){} //创建智能指针时,需要获取T的原始类型
        
        typename std::add_lvalue_reference<U>::type //返回值类型,添加左值引用
        get() const
        {
            return *m_ptr.get();
        }
    };
    
    //利用std::decay保存函数指针
    template<typename T>
    class Sample
    {
        using FnType = typename std::decay<T>::type; //为函数添加指针
        FnType m_fn;
    public:
        Sample(T& f) : m_fn(f){};
        
        void run()
        {
            m_fn();
        }
    };
    
    void func()
    {
        cout <<"void func()" << endl;
    }
    
    int main()
    {
        cout << std::boolalpha; //以下的0、1按false和true格式输出
        
        //添加和移除const、reference
        cout <<is_same<const int, add_const<int>::type>::value << endl;         //true
        cout <<is_same<int, remove_const<const int>::type>::value << endl;      //true
        cout <<is_same<int&, add_lvalue_reference<int>::type>::value << endl;   //true
        cout <<is_same<int&&,add_rvalue_reference<int>::type>::value << endl;   //true
        cout <<is_same<int, remove_reference<int&>::type>::value << endl;       //true
        cout <<is_same<int, remove_reference<int&&>::type>::value << endl;      //true
    
          cout <<is_same<int*, add_pointer<int>::type>::value << endl;    //true
    
        //移除数组顶层维度
        cout <<is_same<int, remove_extent<int[]>::type>::value << endl;             //true     
        cout <<is_same<int[2], remove_extent<int[][2]>::type>::value << endl;       //true     
        cout <<is_same<int[2][3], remove_extent<int[][2][3]>::type>::value << endl; //true 
        cout <<is_same<int, remove_all_extents<int[][2][3]>::type>::value << endl;  //true,移除所有维度
        
        //取公共类型
        typedef common_type<unsigned char, short, int>::type NumericType;
        cout <<is_same<int, NumericType>::value << endl;   //true
        
        //测试Test类
        Test<const int&> t; //T类型故意传入带cv和引用,Test类部在创建对象时,需去除这些属性
        int a = t.get();
        cout << a << endl;
        
        //std::decay
        cout <<is_same<int, decay<int>::type>::value << endl;              //true
        cout <<is_same<int, decay<int&&>::type>::value << endl;            //true,移除引用
        cout <<is_same<int, decay<const int&>::type>::value << endl;       //true,移除cv和引用
        cout <<is_same<int*, decay<int[2]>::type>::value << endl;          //true,移除数组顶层维度
        cout <<is_same<int(*)(int), decay<int(int)>::type>::value << endl; //true,将函数变为函数指针
        
        Sample<decltype(func)> s(func);
        s.run();  //void func();
        
        return 0;
    }
  • 相关阅读:
    格式化数字,将字符串格式的数字,如:1000000 改为 1 000 000 这种展示方式
    jquery图片裁剪插件
    前端开发采坑之安卓和ios的兼容问题
    页面消息提示,上下滚动
    可以使用css的方式让input不能输入文字吗?
    智慧农村“三网合一”云平台测绘 大数据 农业 信息平台 应急
    三维虚拟城市平台测绘 大数据 规划 三维 信息平台 智慧城市
    农业大数据“一张图”平台测绘 大数据 房产 国土 农业 信息平台
    应急管理管理局安全生产预警平台应急管理系统不动产登记 测绘 大数据 规划 科教 三维 信息平台
    地下综合管廊管理平台测绘 大数据 地下管线 三维 信息平台
  • 原文地址:https://www.cnblogs.com/5iedu/p/7767937.html
Copyright © 2020-2023  润新知