• STL源码阅读-traits与迭代器


    迭代器模式

    提供一种方法,使之能够依序访问容器的各个元素,而又无需暴露容器的内部表述方式
    STL设计的中心思想在于将数据容器算法分离开,容器和算法分开设计,迭代器则是两者之间的胶着剂,一般迭代器的设计与容器细节相关,所以一般交给容器的设计者

    迭代器相应型别

    如何"获取迭代器的所指对象的型别"? 可以借助参数推导,但函数的返回值是无法推导的,如果声明内嵌型别typedef T value_type,那么对于原始指针就无法定义其内嵌型别,这时候模板偏特化可以做到

    偏特化与traits

    泛型思维对偏特化的定义是"针对template参数更进一步的条件限制所设计的一个特化版本"
    我们可以使用

    template <class I>
    struct iterator_traits {
        typedef typename I::value_type value_type;
    };
    // 针对原始指针的特化版本
    template <class T>
    struct iterator_traits<T*> {
        typedef T value_type;
    };
    // 针对原始常量指针的特化版本
    template <class T>
    struct iterator_traits<const T*> {
        typedef T value_type;
    };
    

    常用迭代器型别

    根据经验常用的迭代器相应型别有5种: value_type,difference_type,pointer,reference,iterator_catagoly

    • value_type 如上,萃取出迭代器所指对象的类型
    • difference_type 表示两个迭代器之间的距离,如STL中的count
    • reference_type 根据是否允许改变“所指对象之内容”分为两种:constant iterator(如const int* p)和mutable iterator(如int* p)
    • pointer 指向迭代器所指之物
    • iterator_category

    根据移动操作和施行操作,迭代器被分为五类

       input iterator             output iterator
            |                           |
            |                           |
            |___________________________|
                          |
                          |
                   forward iterator
                          |
                          |
                bidirectional iterator
                          |
                          |
                random access iterator
    

    上述箭头不是继承的关系,而是concept和refinement的关系
    以advance为例,我们可以在运行时根据不同的类型,调用不同的advance函数,但这样影响效率,选择不同函数版本可以在编译器解决,只要增加tag就行
    五个标记用的型别

    struct input_iterator_tag {};
    struct output_iterator_tag {};
    struct forward_iterator_tag : public input_iterator_tag {};
    struct bidirectional_iterator_tag : public forward_iterator_tag {};
    struct random_access_iterator_tag : public bidirectional_iterator_tag {};
    

    这些classes只作为标记用,所以为空,通过继承,我们可以少写一些重载函数

    每个新设计的iterator应该提供这五个内嵌型别,不然可能无法与STL其他组件搭配,所以STL提供了一个iterator class如下,每个新设计的迭代器都继承自它,就可保证符合STL所需之规范

    template <class Category,
              class T,
              class Distance  = ptrdiff_t,
              class Pointer   = T*,
              class Reference = T&>
    struct iterator {
        typedef Category iterator_category;
        typedef T value_type;
        typedef Distance difference_type;
        typedef Pointer pointer;
        typedef Reference reference;
    };
    template <class Item>
    struct ListIter : public iterator<forward_iterator_tag, Item> { /*...*/ };
    

    参考

    • STL源码剖析第三章:迭代器概念与traits编程技法
  • 相关阅读:
    bzoj3687 简单题
    bzoj3992 [SDOI2015]序列统计
    bzoj4602 [Sdoi2016]齿轮
    bzoj4006 [JLOI2015]管道连接
    szoj461【四校联考0430】挑战
    bzoj4037 [HAOI2015]数字串拆分
    javascript 节点的增,删,改,查
    javascript 节点属性详解
    表单操作部分
    文档对象的操作
  • 原文地址:https://www.cnblogs.com/qbits/p/11609603.html
Copyright © 2020-2023  润新知