Effective C++--条款47: 请使用traits classes表现类型信息

STL五种迭代器类型(卷标):
  struct input_iterator_tag{} ; =>1
  struct output_iterator_tag{} ; =>2
  struct forward_iterator_tag:public input_iterator_tag{} ; =>3
  struct bidirectional_iterator_tag:public forward_iterator_tag{} ; =>4
  struct random_access_iterator_tag:public bidirectional_iterator_tag{} ; =>5
  卷标:每一卷是一个类型,给一个卷标标识一个类别

  =>1:input迭代器 只能向前移动,一次一步,客户只能读取,不能涂写它所指向的东西,而且只能读取一次
      .模仿指向输入文件的阅读指针,如C++程序库中的istream_iterator
  =>2:output迭代器 只能向前移动,一次一步,客户只能涂写,而且只能涂写一次
      .模仿指向输出文件的涂写指针,如C++程序库中的ostream_iterator
  这是威力最小的两个迭代器分类,只能向前移动,而且只能读或写所指物最多一次,只适合”一次性操作算法”


  =>3:单向 可读写一次以上
      .slist的迭代器
  =>4:双向 可读写一次以上
      .set,multiset,map,multimap的迭代器
  =>5:双向 可读写一次以上 可执行迭代器算术运算
      .vector,deque,string的迭代器

Ttrais是一种技术,也是C++程序猿共同遵守的协议,
  对内置类型和用户自定义类型的表现一样好
  那怎么达到这个要求:自定义类型用template,内置
    类型对应多个特化版本
  例如:iterator_traits
    template<typename IterT>
    struct iterator_traits ;

    遵守协议:要求每一个”用户自定义的迭代器类型”
      必须嵌套一个typedef,名为iterator_category,用来确认适当的卷标
    template<...>
    class deque{
    public:
      class iterator {
        typedef random_access_iterator_tag iterator_category ;
        ...

      } ;
      ...
    } ; 
    template<...>
    class list{
    public:
      class iterator {
        typedef bidirectional_iterator_tag iterator_category ;
        ...

      } ;
      ...
    } ; 

    那么接下来可以定义iterator_traits:
    template<typename IterT>
    struct iterator_traits {
      Typedef typename IterT::iterator_category iterator_catory
    }

    为了同样适用指针:偏特化
    template<typename IterT>
    Struct iterator_traits<IterT*>
    {
      typedef random_access_iterator_tag iterator_category ;
      ...
    } ;

advance函数:
  有了iterator_traits,advance函数可如下实现
  // "工头" 调用 "劳工"并传入traits class提供的信息
  template<typename IterT, typename DistT>
  void advance(IterT& iter, DistT d)
  {
    doAdvance( // "劳工"
      iter, d,
      typename
        std::iterator_traits<IterT>::iterator_category() // ()表示对象
    ) ;
  }
  “编译器条件语句”:利用函数函数重载
  所以doAdvance有多个重载形式
  =>1
  template<typename IterT, typename Dist>
  void doAdvance(IterT& iter, Dist d, std::random_access_iterator_tag)
  {
    iter += d ;
  }
  =>2
  template<typename IterT, typename Dist>
  void doAdvance(IterT& iter, Dist d, std::bidirectional_iterator_tag)
  {
    if(d >= 0) {while(d—) ++iter; }
    else { while(d++) --iter ; }
  }
  =>3
  template<typename IterT, typename Dist>
  void doAdvance(IterT& iter, Dist d, std::input_iterator_tag)
  {
    if(d < 0) {
      throw std::out_of_range("Negativ\
      e distance") ;
    }
    while(d--) ++iter ;
  }
  用上面的3中重载形式作为if判断
  =>3 同样会适配std::forward_iterator_tag
    因为它public继承自input_iterator_tag,
    这是public继承的红利:针对base class编写
      代码,用于derived class身上也行得通

traits_class通常以traits结尾
  如std::iterator_traits<T> 给出T的指针类型
  例外:std::numeric_limits<T>表现T的最大z最
        小值
        std::cout << std::number_limits<int>::min() << "\n" ;
        std::cout << std::number_limits <int>::max() << "\n" ;
      std:is_fundamental<T> 判断T是否为内
        置类型
        std::cout << "unsigned is_fundamental:" << std::is_fundamental<unsinged>::value << "\n" ;
        // 输出:true

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值