Reference Type 和 Pointer Type
所谓左值(lValue):是用来代表某个对象的一个东西。如果p是指向类型为T的某个对象,那么表达式*p不能只是返回类型为T的对象,而必须是返回一个lValue(左值)。
平时总是拿起*p就直接赋值(对于简单基本类型,例如int *p = &I ; *p=3),没想什么*p返回左值那么多。但是当在自定义类中重栽*运算符的时候,我们就要特别小心,要注意到这点,返回为T& 才对。
言规正传
iterator_traits的某些机制所蕴涵的意义十分微妙而深远,不过它的实现却不是很复杂,不过这些东西看起来比较容易看懂,真正能够灵活使用就需要花时间领悟了,为什么会采取这种方法解决问题,和其它的方法对比有什么好处和提高?这种明白这些问题才算掌握了trait的实质。
template< class Iterator>
struct iterator_traits
{
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::difference_type difference_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference ;
};
template< class T>
struct iterator_traits
{
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference ;
};
template< class T>
struct iterator_traits
{
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef T& reference ;
};
当你定义一个自己的算法,你需要关注这个机制,下面两个理由就是你可能要用到iterator_traits:
① 你必须返回某值,或者是申明临时变量,而其它型别与iterator的value type 或者different type或者reference type 或者pointer type一致。
② 你的算法类似与advance,必须根据iterator的分类来决定不同的实现方法(提高效率,在编译时候进行判断而不是在运行的时候进行判断),没有traits机制,你只好在‘一般化但是没效率’或者‘有效率但是过度狭隘’中进行抉择。
当定义一个Iterator 类,就得在改类中定义五个嵌套的类型,如上面的五个所示。要不然就得针对你的Iterator类,明白的令iterator_traits为Iterator特化,就像iterator_traits要明白的针对指针而特化一样。第一种做法总是比较简单,尤其是STL的一个辅助类,base class iterator,让事情变得更简单了。
template< class Category,
class Value,
class Distance =ptrdiff_t,
class Pointer = Value*,
class Reference = Value &
>
struct iterator
{
typedef Category iterator_category;
typedef Value value_type;
typedef Distance difference_type;
typedef Pointer pointer;
typedef Reference reference;
};
为了确保iterator_traits能够对新的iterator class有适当的定义,最简单的方法就是从iterator类派生自己的iterator。基类iterator不含任何成员函数和成员变量,所以继承不存在额外的开销。