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 源碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章