STL 源码剖析重要部分:迭代器与Traits编程技法

五种迭代器类型
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 { };

这里的 xxx_iterator_tag 类型是用来对函数重载起作用的

运用继承的原因在后续代码实例中解释。

为避免写代码时挂一漏万,自行开发的迭代器最好继承下面这个 std::iterator
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;
};
榨汁机 traits
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;
};

针对原生指针而设计的 traits 偏特化版

template <class T>
struct iterator_traits<T*> {
    typedef random_access_iterator_tag iterator_category;
    typedef T value_type;
    typedef ptrdiff_t difference_type;
    typedef T* pointer;
    typedef T& reference;
};

针对原生之 pointer-to-const 而设计的偏特化版

template <class T>
struct iterator_traits<const T*> {
    typedef random_access_iterator_tag iterator_category;
    typedef T value_type;
    typedef ptrdiff_t difference_type;
    typedef const T* pointer;
    typedef const T& reference;
};
三个全局函数

这个函数可以很方便地决定某个迭代器的类型 (category)

template <class Iterator>
inline typename iterator_traits<Iterator>::iterator_category
iterator_category(const Iterator&) {
    typedef typename iterator_traits<Iterator>::iterator_category category;
    return category();
}

这个函数可以很方便地决定某个迭代器的 distance type

template <class Iterator>
inline typename iterator_traits<Iterator>::difference_type*
distance_type(const Iterator&) {
    return static_cast<typename iterator_traits<Iterator>::difference_type* >(0);
}

这个函数可以很方便的决定某个迭代器的 value type

template <class Iterator>
inline typename iterator_traits<Iterator>::value_type*
value_type(const Iterator&) {
    return static_cast<typename iterator_traits<Iterator>::value_type*>(0);
}
以下是整组 distance (一个实例)

作用是求两个迭代器之间的距离。显然,该函数针对迭代器是否有 + n 这个运算分开来写的。 在 lower_bound 等算法中有使用到。

即两种,RandomAccessIterator 和 非 RandomAccessIterator。 而运用继承机制,当我们调用这个函数传入的 BidirectionalIterator 时,它会自动转为 InputIterator,从而有一个合法的函数匹配。其他的,如 ForwardIterator 也是同理。

同时,也可以发现,xxx_iterator_tag 的作用只是帮助形成函数重载。

template <class InputIterator>
inline typename iterator_traits<InputIterator>::difference_type
__distance(InputIterator first, InputIterator last, input_iterator_tag) {
    typename iterator_traits<InputIterator>::difference_type n = 0;
    while(first != last) {
        ++ first; ++ n;
    }
    return n;
}

template <class RandomAccessIterator>
inline typename iterator_traits<RandomAccessIterator>::difference_type
__distance(RandomAccessIterator first, RandomAccessIterator last,
        random_access_iterator_tag) {
    return last - first;
}

template <class InputIterator>
inline typename iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last) {
    typedef typename iterator_traits<InputIterator>::iterator_category category;
    return __distance(first, last, category());
}
以下是整组 advance 函数

该函数的作用是,取得与迭代器 i 距离为 n 处的迭代器。 在 lower_bound 等算法中有使用到。

与 distance() 类似。这里分为了三种,迭代器只有 ++ 操作;迭代器可 ++,可 --,但是不能 + n;迭代器有 ++,–, +n,+=,-= 等运算。

由于继承的关系,当传入 ForwardIterator,在调用时都会自动转换为 InputIterator,即无需再针对 ForwardIterator 编写一个 __advance()

template <class InputIterator, class Distance>
inline void __advance(InputIterator &i, Distance n, input_iterator_tag) {
    while(n --) ++ i;
}

template <class BidirectionalIterator, class Distance>
inline void __advance(BidirectionalIterator &i, Distance n,
                        bidirectional_iterator_tag) {
    if(n >= 0)
        while(n --) ++ i;
    else
        while(n ++) -- i;
}

template <class RandomAccessIterator,class Distance>
inline void __advance(RandomAccessIterator &i, Distance n,
                        random_access_iterator_tag) {
    i += n;
}

template <class InputIterator, class Distance>
inline void advance(InputIterator &i, Distance n) {
    __advance(i, n, iterator_category(i));
}
__type_traits

  __type_traits 与 iterator_traits 很类似,用来萃取其类型是否含有:trivial_default_constructor,trivial_copy_constructor,是否是 POD 类型等。

同样的,为了便于重载,还提供了两个类:

struct __true_type{};
struct __false_type{};

__type_traits 默认将以上类型都设置为 false_type,即:

template <class type>
struct __type_traits {
	typedef __true_type this_dummy_member_must_be_first;
	
	typedef __false_type has_trivial_default_constructor;
	typedef __false_type has_trivial_copy_constructor;
	typedef __false_type has_trivial_assignment_constructor;
	typedef __false_type has_trivial_destructor;
	typedef __false_type is_POD_type;
};

并针对所有的内置类型编写了特例化的版本:

__STL_TEMPLATE_NULL struct __type_traits<char> {
	typedef __true_type has_trivial_default_constructor;
	typedef __true_type has_trivial_copy_constructor;
	typedef __true_type has_trivial_assignment_constructor;
	typedef __true_type has_trivial_destructor;
	typedef __true_type is_POD_type;
};

__STL_TEMPLATE_NULL struct __type_traits<int> {
	typedef __true_type has_trivial_default_constructor;
	typedef __true_type has_trivial_copy_constructor;
	typedef __true_type has_trivial_assignment_constructor;
	typedef __true_type has_trivial_destructor;
	typedef __true_type is_POD_type;
};

// ... 还有 unsigned char, long, short, unsigned short 等许多内置类型

其应用体现在很多地方,见:https://blog.csdn.net/no_O_ac/article/details/105469821 中的 destroy 源码与 uninitialized_copy 源码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值