五種迭代器類型
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 源碼