浅谈 uninitialized_copy() 的参数类型

template <class InputIterator, class ForwardIterator>
inline ForwardIterator
uninitialized_copy(InputIterator first, InputIterator last,
                   ForwardIterator result);

该函数位于 SGI stl_uninitialized.h 中。作用于未初始化的空间,具体作用是将 [first,last) 内的元素拷贝到 [result,result+(lastfirst))

其中,形参 first,last 和 result 的类型如下:

parameter iterator category
first,last InputIterator
result ForwardIterator

那么为什么形参类型是这样的呢?

因为按照 STL 算法命名的规则,以算法所能接收的最初级 iterator 类型来为参数命名。在 stl_iterator_base.h 中定义了几种 iterator categories 间的关系:

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 {};

按照定义的话,实际上 Forward Iterator 应当支持 Input Iterator 和 Output Iterator 的所有操作,所以 forward_iterator_tag 应该同时继承 input_iterator_tag 和 output_iterator_tag,但是却不是这样。

实际上 iterator_tag 的继承体系的设计主要是为了 iterator_traits 服务的。Forward Iterator 的内嵌类型并不和 Output Iterator 存在继承和被继承关系。

struct output_iterator {
  typedef output_iterator_tag iterator_category;
  typedef void                value_type;
  typedef void                difference_type;
  typedef void                pointer;
  typedef void                reference;
};

template <class _Tp, class _Distance> struct forward_iterator {
  typedef forward_iterator_tag iterator_category;
  typedef _Tp                  value_type;
  typedef _Distance            difference_type;
  typedef _Tp*                 pointer;
  typedef _Tp&                 reference;
};

Output Iterator 并不是结构体模板,它的所有内嵌类型都是确定的,属于 结构体模板的 Forward Iterator 并不能以多变的参数继承不变的固定的 Output Iterator.

按照 STL 算法的命名规则,再综合该函数的作用:用一个范围内的值初始化另一个范围内的值。对于迭代器的话,必然要求输入参数 [first, last)能够进行 ①递增运算,能够判断是否初始化完毕(②比较 first 和 last 是否相等),初始化时能够通过迭代器获得它代表的值(②解引用),从这些要求来看,Input Iterator 符合要求的最低级迭代器。

那么对于目标参数又有哪些要求呢?
首先,①递增的要求是必要的;二是能够②调用迭代器所对应的 value_type 的构造函数或者能够被赋值

如果单单是 递增 + 能够被赋值,那么 Output Iterator 是符合要求的,但是另一个要求是能够调用构造函数。构造函数的调用累和对于范围内所有元素是昂贵的。对于 non-POD 类型是需要调用构造函数的,对于 POD 类型,有 trivial constructor 和 trivial assignment ,显然更快。

但是如何区分迭代器所代表的数据元素是 POD 类型还是 non-POD 类型呢?
采用 type_traits,萃取出迭代器的 value_type,然后把它跟 true_type 及 false_type 比较,是 true_type,表明是 POD 类型,否则为 non-POD 类型。但是这招对于 Output Iterator 显然不行,因为它的 value_type 为 void,那么就应该兼有 Output Iterator 操作且 value_type 不为 void 的最低类型,那就是 Forward Iterator 了。

你可能感兴趣的:(stl,函数,算法,C++,stl,泛型编程,算法)