(Boolan) C++ STL与泛型编程——算法、仿函数、Adapter

之前已经完成了STL中容器的梳理,那么从语言的层面来看:

  • 容器是class template
  • 算法是function template
  • 迭代器是class template
  • 适配器是class template
  • 分配器是class template

一般STL中的算法都是如下的两种形式(Algorithm代表一种泛指,可以替代其他的函数名称)

template<typename Iterator>
Algorithm (Iterator itr1, Iterator itr2)
{
    ..........
}

template<typename Iterator, typename Cmp>
Algorithm (Iterator itr1, Iterator itr2, Cmp comp)
{
    ..........
}

对于Algorithms来说,是不能直接看到Container的,对他的情况可谓一无所知。那么,他所需要的一切信息就必须要通过他们之间桥梁Iterators来获得了。然而Iterators(是由Container所提供的)必须能够回答Algorithms所提出的一些问题(比如类型等),才能够搭配对应的Algorithm的所有操作。

所谓算法的所提出的问题,其hi就是类型的确认过程,通过确认,来获取他所需要的,例如标记了五种iterator categories的类型

//5种iterator categories
struct input_iterator_tag{};
//

struct output_iterator_tag{};
//

struct forward_iterator_tag : public input_iterator_tag{};
//forward_list是单向链表

struct bidirectional_iterator_tag : public forward_iterator_tag{};
//list,rb_tree为底层的set,multiset、map、multimap是双向链表,iterator不能随机跳跃

struct random_access_iterator_tag : public bidirectional_iterator_tag{};
//对于连续空间的array、vector、deque
(虽然实际上不连续,但是iterator构造了连续的假象)
,这些迭代器可以随便跳跃的类型

iterator categories的UML

这样设计的优势是在于,通过对象的方式就可以调用不同函数的重载,例如:

void _display_category(random_access_iterator_tag){
    cout << "random_access_iterator" << endl;
}

void _display_category(bidirectional_iterator_tag){
    cout << "bidirectional_iterator" << endl;
}

void _display_category(forward_iterator_tag){
    cout << "forward_iterator" << endl;
}

void _display_category(input_iterator_tag){
    cout << "input_iterator" << endl;
}

void _display_category(output_iterator_tag){
    cout << "output_iterator" << endl;
}

template<typename I>
void display_category(I iter){
    typename iterator_traits<I>::iterator_category cagy;
    _display_category(cagy);
    //根据对象类型,可以调用不同的函数重载
}

//.........
{
    //通过iterator的临时对象来作为参数调用
    display_category(set<int>::iterator());
}
  • istream_iterator 的iterator_category
    gnu2.9里面的istream_iterator
template <class T,
                 class Distance = ptrdiff_t>
class istream_iterator{
public:
      typedef input_iterator_tag iterator_category;
//      ............
};

gnu 3.3里面的istream_iterator

template<class _Tp,
         class _CharT = char,
         class _Traits = char_traits<_CharT>,
         class _Dist = ptrdiff_t>
class istream_iterator{
public:
    typedef input_iterator_tag iterator_category;
}

Gnu4.9里面的istream_iterator

template<typename _Category,
         typename _Tp,
         typename _Distance = ptrdiff_t,
         typename _Pointer = _Tp*,
         typename _Reference = _Tp&>
struct iterator{
      typedef _Category iterator_category;
      typedef _Tp       value_type;
      typedef _Distance difference_type;
      typedef _Pointer  pointer;
      typedef _Reference reference;
}

template<typename _Tp,
      typename _CharT = char,
      typename _Traits = char_traits<_CharT>,
      typename _Dist = ptrdiff_t>
class istream_iterator: public iterator<input_iterator_tag, _Tp, _Dist, const _*Tp, const _Tp&>
{...........}
  • ostream_iterator 的iterator_category
    gnu2.9里面的ostream_iterator
template <class T,
                 class Distance = ptrdiff_t>
class ostream_iterator{
public:
      typedef output_iterator_tag iterator_category;
//      ............
};

gnu 3.3里面的ostream_iterator

template<class _Tp,
         class _CharT = char,
         class _Traits = char_traits<_CharT>,
         class _Dist = ptrdiff_t>
class ostream_iterator{
public:
    typedef output_iterator_tag iterator_category;
}

Gnu4.9里面的ostream_iterator

template<typename _Category,
         typename _Tp,
         typename _Distance = ptrdiff_t,
         typename _Pointer = _Tp*,
         typename _Reference = _Tp&>
struct iterator{
      typedef _Category iterator_category;
      typedef _Tp       value_type;
      typedef _Distance difference_type;
      typedef _Pointer  pointer;
      typedef _Reference reference;
}

template<typename _Tp,
      typename _CharT = char,
      typename _Traits = char_traits<_CharT>,
      typename _Dist = ptrdiff_t>
class ostream_iterator: public iterator<output_iterator_tag, void, void, void, void>
{...........}
  • iterator_category对算法的影响
template<class InputIterator>
inline iterator_trais<InputIterator>::diference_type __distance(InputIterator first, InputIterator last, input_iterator_tag){
//input_iterator_tag是forward_iteator_tag和bidirectional_iterator_tag的父类,
//所以遇到了会直接进入input_iterator_tag的重载部分
      iterator_trais<InputIterator>::difference_type n = 0;
      //由于不是RandomAccessIterator,所以迭代器不能直接相减,需要遍历了
      while(first != last){
          ++first;
          ++n;
      }
      return n;
}

template<class RandomAccessIterator>
inline iterator_trais<RandomAccessIterator>::difference_type __distance(RandomAccessIterator first, RandomAccessIterator last, random_access_iterator_tag){
      return last - first;
      //只有连续空间才能迭代器想减
}

template<class InputIterator>
inline iterator_trais<InputIterator>::difference_type distance(InputIterator first, InputIterator last){
      //根据trais获取iterator的category tag,如果编译不通过说明迭代器出问题
      typedef typename iterator_trais<InputIterator>::iterator_category category;
      return __distance(first,
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值