zoukankan      html  css  js  c++  java
  • 【C++】traits classes

    程序开发时,经常遇到根据变量获取其类型信息的需求.

    例如,某一个函数针对不同的类型参取了不同的优化策略,因而要获取相应的类型信息调用对应的函数.

    template<typename IterT,typename DistT> //将迭代器向前移动d单位
    void advance(IterT& iter,DistT d);        //如果d < 0则向后移动

    观念上advance只是做iter += d动作,但其实不可以全然那么实践.因为只有random access迭代器才支持+=操作,面对其他威力不那么强大迭代器种,advance必须反复施行++或--,共d次.因而希望其实现方式如下:

    template<typename IterT,typename DistT>
    void advance(IterT& iter,DistT d)
    {
        if(iter is a random access iterator) {
            iter += d;        //针对random access 迭代器使用迭代器算术运算
        }
        else{        //针对其他迭代器分类,反复调用++或--
            if(d >= 0) {while(d--) ++iter;}    
            else {while(d++) --iter;}    
        }
    }

    其中,关键是如何判断类型为IterT的iter是否为random access迭代器

    初步想法,可以在类型中定义相应的类型信息属性,标识该类型所包含的类型信息,然后通过获取该类型的这些信息属性,进行判断.

    这种想法,可以解决自定义类型的问题,但无法解决内置类型的问题,因为我们无法将信息嵌套于原始指针内.

    因此,上述想法行不通,我们需要把类型的类型信息放于类型自身之外.

    traits classes就是一种技术,也是个C++程序员共同遵守的协底色,它要求对内置类型和用户自定义类型表现一样.

    这种技术可以允许我们在编译期间取得某些类型信息.一个traits class设计与实现的一般步骤如下:

    1.确认若干你希望将来可取得的类型相关信息.

    2.为该信息选择一个名称

    3.提供一个template和一组特化版本,内含你希望支持的类型相关信息.

    有了相关的trait class,我们可以用trait class提供的信息类型,取代if语句中的条件判断.

    这样实现,将会存在一个问题,编译期完成的事被延到运行期了.

    这是因为traits class可以在编译期间获知IterT的类型,但if语句却是在运行期才会判断.

    这里就需要一种方法,可以在编译期完成类型的判断,取代if语句的判断.

    该方法就是重载,根据编译期间确定的类型信息,选择最合适的重载函数,相当根据if语句判断后,再选择具体的实现.

    template<typename IterT,typename DistT>
    void doAdvance(IterT& iter,DistT d,std::random_access_iterator_tag)
    {
        iter += d;
    }
    template<typename IterT,typename DistT>
    void doAdvance(IterT& iter,DistT d,std::bidirectional_iterator_tag)
    {
        if(d >= 0) {while(d--) ++iter;}    
        else {while(d++) --iter;}    
    }
    template<typename IterT,typename DistT>
    void doAdvance(IterT& iter,DistT d,std::input_iterator_tag)
    {
        if(d < 0){
            throw std::out_of_range("Negative distance");
        }
        while(d--) ++iter;
    }
    
    template<typename IterT,typename DistT>
    void advance(IterT& iter,DistT d)
    {
        doAdvance(iter,d,typename std::iterator_traits<IterT>::iterator_category());
    }

    trait class具体的使用方法,如上述代所述.

    1.建立一组重载函数或函数模板,彼此间的差异只在于各自的traits参数.令每个函数实现码与其接受的traits信息相匹配.

    2.建立一个控制函数或函数模板,它调用上述的那些重载函数并传递traits class所提供的信息.

    启发:解决问题时,思路的逐步深入,遇到问题,可以先想个初步思路,然后分析初步思路不足,并改进初步思路,提供合理的解决方案.

    参考资料:Effective C++

  • 相关阅读:
    高级程序设计语言学习2
    程序设计语言学习
    基于Android,对硬件、框架、API、操作系统、应用程序的理解
    Python_code_使用OpenCV库对图片实现数据增强
    Python_code_使用ImageFilter库对图片实现数据增强
    Python_code_实现贴图功能
    Python_code_使用OpenCV库实现对图像的_平移_旋转_缩放
    Python_code_七段数码管绘制实现_happy-new-year
    3_一幅图像,经过傅里叶变换后,将高频部分删除,再进行反变换,设想一下将会得到什么结果?
    2_图像处理中正交变换的目的是什么?图像变换主要用于那些方面?
  • 原文地址:https://www.cnblogs.com/dwdxdy/p/2593100.html
Copyright © 2011-2022 走看看