zoukankan      html  css  js  c++  java
  • c++ template(9)trait和Policy

    先看一个Demo:

    累加序列:

    template <typename T> 
    inline 
        T accum (T const* beg, T const* end) 
    { 
        T total = T();  // assume T() actually creates a zero value 
        while (beg != end) { 
            total += *beg; 
            ++beg; 
        } 
        return total; 
    } 
    

    使用示例:

    int main() 
    {
        // create array of 5 integer values 
        int num[]={1,2,3,4,5}; 
    
        // print average value 
        std::cout << "the average value of the integer values is " 
            << accum(&num[0], &num[5]) / 5 
            << '\n'; 
    
        // create array of character values 
        char name[] = "templates"; 
        int length = sizeof(name)-1; 
    
        // (try to) print average character value 
        std::cout << "the average value of the characters in \"" 
            << name << "\" is " 
            << accum(&name[0], &name[length]) / length 
            << '\n'; 
    
        return 1;
    
    }
    

    结果:

    image

    显然char的类型有问题,变量total 应该转化为int

    修改方案则是新加一个模版参数:

    template <typename T,typename V=int> 
    inline 
        V accum (T const* beg, T const* end) 
    { 
        V total = V();  // assume T() actually creates a zero value 
        while (beg != end) { 
            total += *beg; 
            ++beg; 
        } 
        return total; 
    } 
    

    同时添加了使用成本

    accum<char,int>(&name[0], &name[length])
    

    模版的trait力量:将动态模版参数定义到外部结构中

    template<typename T> 
    class AccumulationTraits; 
    
    template<> 
    class AccumulationTraits<char> { 
    public: 
        typedef int AccT; 
    }; 
    
    template<> 
    class AccumulationTraits<short> { 
    public: 
        typedef int AccT; 
    }; 
    
    template<> 
    class AccumulationTraits<int> { 
    public: 
        typedef long AccT; 
    }; 
    
    template<> 
    class AccumulationTraits<unsigned int> { 
    public: 
        typedef unsigned long AccT; 
    }; 
    
    template<> 
    class AccumulationTraits<float> { 
    public: 
        typedef double AccT; 
    }; 
    
    template <typename T> 
    inline 
        typename AccumulationTraits<T>::AccT accum (T const* beg, 
        T const* end) 
    { 
        // return type is traits of the element type 
        typedef typename AccumulationTraits<T>::AccT AccT; 
    
        AccT total = AccT();  // assume T() actually creates a zero value 
        while (beg != end) { 
            total += *beg; 
            ++beg; 
        } 
        return total; 
    } 
    

    现在可以保持调用方式保持不变,通过trait来更改类型参数

    accum(&name[0], &name[length])
    

    现在结果是正确的

    image

    trait的默认值

    trait类型的初始值用构造函数初始化可能会有问题,所以可以再次用trait来定义默认值

    默认值方式:1.静态变量(只能整型数值和枚举),2.静态方法(推荐)

    template<> 
    class AccumulationTraits<char> { 
    public: 
        typedef int AccT; 
        //static AccT const zero = 0; 
        static AccT zero() { 
            return 0; 
        } 
    
    }; 
    

    更改后的初始化方式:

    template <typename T> 
    inline 
        typename AccumulationTraits<T>::AccT accum (T const* beg, 
        T const* end) 
    { 
        // return type is traits of the element type 
        typedef typename AccumulationTraits<T>::AccT AccT; 
    
        AccT total = AccumulationTraits<T>::zero();
        while (beg != end) { 
            total += *beg; 
            ++beg; 
        } 
        return total; 
    } 
    

    This is the key of the traits concept: Traits provide an avenue to configure concrete elements (mostly types) for generic computations.

    trait参数化

    有时候我们想改变通过trait本身的默认模版参数,这样就需要对trait本事做一个参数封装

    封装一个默认的模版参数

    template <typename T, 
        typename AT = AccumulationTraits<T> > 
    class Accum { 
    public: 
        static typename AT::AccT accum (T const* beg, T const* end) { 
            typename AT::AccT total = AT::zero(); 
            while (beg != end) { 
                total += *beg; 
                ++beg; 
            } 
            return total; 
        } 
    }; 
    

    1

    现在之前的方法应该如下示例:

    template <typename T> 
    inline 
        typename AccumulationTraits<T>::AccT accum (T const* beg, 
        T const* end) 
    { 
        return Accum<T>::accum(beg, end); 
    } 
    
    

    trait参数化

    template <typename Traits, typename T> 
    inline 
        typename Traits::AccT accum (T const* beg, T const* end) 
    { 
        return Accum<T, Traits>::accum(beg, end); 
    } 
    

    Policy

    Policy注重算法,如下示例:Policy是一个静态类,通过动态编译来计算

    template <typename T, 
        typename Policy = SumPolicy, 
        typename Traits = AccumulationTraits<T> > 
    class Accum { 
    public: 
        typedef typename Traits::AccT AccT; 
        static AccT accum (T const* beg, T const* end) { 
            AccT total = Traits::zero(); 
            while (beg != end) { 
                Policy::accumulate(total, *beg); 
                ++beg; 
            } 
            return total; 
        } 
    }; 
    

    不同Policy算法

    class SumPolicy { 
    public: 
        template<typename T1, typename T2> 
        static void accumulate (T1& total, T const & value) { 
            total += value; 
        } 
    }; 
    
    class MultPolicy { 
    public: 
        template<typename T1, typename T2> 
        static void accumulate (T1& total, T const& value) { 
            total *= value; 
        } 
    }; 
    

    使用示例:

    int main() 
    { 
        // create array of 5 integer values 
        int num[]={1,2,3,4,5}; 
    
        // print product of all values 
        std::cout << "the product of the integer values is " 
            << Accum<int,MultPolicy>::accum(&num[0], &num[5]) 
            << '\n'; 
    } 
    
  • 相关阅读:
    显示在页面中间的加载gif
    10个超赞的jQuery图片滑块动画
    【Mybatis】mybatis设置指定列为空值
    【Centos】使用confluent将Mysql数据同步到clickhouse
    SpringBoot Mock测试RequestBody参数并包含其他参数接口
    【Linux】linux使用screen部署spring cloud项目
    Docker中部署jenkins
    【Mysql】Docker连接容器中的mysql 8报错 Public Key Retrieval is not allowed
    【MySQL】Windows下mysql的主从配置笔记
    This Gradle plugin requires a newer IDE able to request IDE model level 3. For Android Studio this means version 3.0+
  • 原文地址:https://www.cnblogs.com/Clingingboy/p/2988604.html
Copyright © 2011-2022 走看看