zoukankan      html  css  js  c++  java
  • Type Trait 和 Type Utility

    所谓Type trait,提供了一种用来处理type 属性的办法,它是个template,可在编译期根据一个或多个template实参(通常也是type)产出一个type或者value。

    template <typename T>
    void foo(const T& val) {
        if (std::is_pointer<T>::value) {
            cout << "foo called for a pointer " << endl;
        }
        else
            cout << "foo() called for a value" << endl;
        //...
    }

    trait std::is_pointer定义于<type_traits>,用来检查T是否pointer type。若是,就是 type true_type,否则type false_type。而::value若非产生true就是false。

    但是,不能如下这么做:

    template <typename T>
    void foo(const T& val) {
        std::cout << (std::is_pointer<T>::value ? *val : val) << endl;
    }

    关键是不确定val到底是指针还是普通值。若是个值得话,*val 就无效了,不能通过编译。

    template <typename T>
    void fool_impl(const T& val,std::true_type){
        cout << "foo() called for pointer to " << *val << endl;
    }
    
    template<typename T>
    void fool_impl(const T7 val, std::false_type){
        cout << "foo() called value to  "<< val << endl;
    }
    
    template<typename T>
    void foo(const T& val){
        fool_impl(val,std::is_pointer<T>());
    }

    这比重载版本要好。是因为,有时候太多重载版本并无必要。一般而言,type trait 的威力来自于一个事实:它们是泛型代码的基石。

    两个例子:

    1 针对整数的弹性重载

    假设一个函数foo(),对于整数类型和浮点类型的实参有不同的实现。通常做法是重载:

    void foo(short);
    void foo(unsigned short);
    void foo(int);
    ...
    void foo(float);
    void foo(double);
    void foo(long double);

    每多一个类型,就需要一个新的重载函数。但是,有了type trait就是不一样:

    template <typename T>
    void foo_impl(T val, true_type);
    
    template<typename T>
    void foo_impl(T val, false_type);
    
    template<typename T>
    void foo(const T& val){
        fool_impl(val,std::is_integral<T>());
    }

    只需提供两份实现,整数和浮点,完事儿。

    2 处理共通类型

    共通类型是一个可以“用来处理两个不同类型的值”的类型,前提是存在这个一个共通类型。举例而言,不同类型的两个值的总和或最小值,就该使用共通类型。

    template<typename T1, typename T2>
    typename std::common_type<T1,T2>::type min(const T1& x, const T2& T);

    如果两个实参都是int 或者都是long,或者一个是int一个是long,std::common_type<T1,T2>::type 会产生int。如果实参之一是string而另一个是字符串字面常量,就产生std::string.  其通过以下规则实现:

    template<typename T1, typename T2>
    struct common_type<T1,T2>{
        typedef decltype(true ? decval<T1>() : decval<T2>()) type;
    };

    其中 decltype是c++11提供的关键字,用以到处表达式类型,declval()是辅助性trait,依据传入的类型提供一个值 ,但是不去核算它。

    该头文件下的函数等 。cppreference.com

  • 相关阅读:
    操作系统——理论知识
    BEGIN-4 Fibonacci数列
    BEGIN-3 圆的面积
    面向对象三大特征之一:多态
    面向对象三大特征之二:继承
    package---包
    面向对象三大特征之一:封装
    关键字:This(上)
    无参构造与有参构造
    面向对象
  • 原文地址:https://www.cnblogs.com/gardenofhu/p/9310287.html
Copyright © 2011-2022 走看看