zoukankan      html  css  js  c++  java
  • 第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;
    }
  • 相关阅读:
    Hadoop-MyEclipse安装配置
    grid搜索最优参数
    python数据集处理
    集合框架
    Java泛型集合
    python机器学习工具包
    IO流
    Eclipse导入Hadoop源码项目及编写Hadoop程序
    Hadoop日志以及日志的格式和命名组成
    VIM键盘映射 (Map)
  • 原文地址:https://www.cnblogs.com/5iedu/p/7767937.html
Copyright © 2011-2022 走看看