iterator是容器和算法之间的粘合剂,为算法提供对于容器的操作,以下是关系图(继承):
我们拿到一个类型,先判断是不是原生指针(const和非const),如果是原生指针,那我们就进行萃取,将其型别萃取成random型别;
template <class T>
struct iterator_traits<T*>
{
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef ptrdiff_t difference_type;
};
如果不是原生指针,那我们就要进行判断,看萃取出来的类类型是否具有iterator_category;
template <class T>
struct has_iterator_cat
{
private:
struct two { char a; char b; };
template <class U> static two test(...); // 存在两个字符的结构体还是说只是一个
template <class U> static char test(typename U::iterator_category* = 0);
// 运用了SFINAE技巧,若有iterator_category属性,则会优先匹配到
public:
static const bool value = sizeof(test<T>(0)) == sizeof(char); // 看参数是不是true--这就是有iterator_category
};
// 这个类是一个判断模板类中是否含有typename U::iterator_category*,设计非常巧妙
如果具有iterator_category,那就看看是不是Input和output_iterator的子类;
template <class Iterator>
struct iterator_traits_helper<Iterator, true>
: public iterator_traits_impl<Iterator,
std::is_convertible<typename Iterator::iterator_category, input_iterator_tag>::value ||
std::is_convertible<typename Iterator::iterator_category, output_iterator_tag>::value> // 分类是input类或者output类
{
};
iterator_traits_impl<Iterator, true> 是萃取出迭代器的特性,也就是说在 struct iterator_traits_helper<Iterator, true>中,如果迭代器型别是Input和output_iterator的子类,那我就进行萃取并且进行typedef;
template <class Iterator>
struct iterator_traits_impl<Iterator, true> // 如果说有iterator_categort的特性就去萃取;
{
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
typedef typename Iterator::difference_type difference_type;
};
所以萃取机继承struct iterator_traits_helper即可,完美闭环~
template <class Iterator> // 继承关系
struct iterator_traits
: public iterator_traits_helper<Iterator, has_iterator_cat<Iterator>::value> {};
逻辑图如下:
这样看起来萃取机源码的逻辑就比较简洁了;
那问题来了,我们要先去萃取出五种型别,并且要对型别之间的关系进行判断,那么五种型别和之间的关系如下:
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 {}; // 最高效率的进行元素操作;
有了上面的铺垫,我们能够很容易的萃取出一个类类型的型别;
template <class Iterator>
typename iterator_traits<Iterator>::iterator_category
iterator_category(const Iterator&)
{
typedef typename iterator_traits<Iterator>::iterator_category Category;
return Category();
}
剩下的反转迭代器这些就不讲了,问题又来了,我们使用迭代器的时候一般是 iterator<vector>::iter = vec.begin(); 我们可以通过*iter来提取iter处的值,以及++iter来使得迭代器向前移动,这些迭代器的具体运算符重载其实是在具体的容器中实现的,因为不同容器++所实现的才做其实是可能不一样,例如list和vector的++;
具体迭代器thin_stl的源码如下:
#pragma once
#ifndef MYTINYSTL_ITERATOR_H_
#define MYTINYSTL_ITERATOR_H_
// 这个头文件用于迭代器设计,包含了一些模板结构体与全局函数,
#include <cstddef>
namespace mystl
{
// 五种迭代器类型
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 {}; // 最高效率的进行元素操作;
// 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 Pointer pointer;
typedef Reference reference;
typedef Distance difference_type;
};
// iterator traits
template <class T>
struct has_iterator_cat
{
private:
struct two { char a; char b; };
template <class U> static two test(...); // 存在两个字符的结构体还是说只是一个
template <class U> static char test(typename U::iterator_category* = 0);
// 运用了SFINAE技巧,若有iterator_category属性,则会优先匹配到
public:
static const bool value = sizeof(test<T>(0)) == sizeof(char); // 看参数是不是true--这就是有iterator_category
};
// 这个类是一个判断模板类中是否含有typename U::iterator_category*,设计非常巧妙
template <class Iterator, bool>
struct iterator_traits_impl {};
template <class Iterator>
struct iterator_traits_impl<Iterator, true> // 如果说有iterator_categort的特性就去萃取;
{
typedef typename Iterator::iterator_category iterator_category;
typedef typename Iterator::value_type value_type;
typedef typename Iterator::pointer pointer;
typedef typename Iterator::reference reference;
typedef typename Iterator::difference_type difference_type;
};
template <class Iterator, bool>
struct iterator_traits_helper {};
template <class Iterator>
struct iterator_traits_helper<Iterator, true>
: public iterator_traits_impl<Iterator,
std::is_convertible<typename Iterator::iterator_category, input_iterator_tag>::value ||
std::is_convertible<typename Iterator::iterator_category, output_iterator_tag>::value> // 分类是input类或者output类
{
};
// 萃取迭代器的特性
template <class Iterator> // 继承关系
struct iterator_traits
: public iterator_traits_helper<Iterator, has_iterator_cat<Iterator>::value> {};
// 针对原生指针的偏特化版本
template <class T>
struct iterator_traits<T*>
{
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef ptrdiff_t difference_type;
};
template <class T>
struct iterator_traits<const T*>
{
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef const T* pointer;
typedef const T& reference;
typedef ptrdiff_t difference_type;
};
template <class T, class U, bool = has_iterator_cat<iterator_traits<T>>::value>
struct has_iterator_cat_of
: public m_bool_constant<std::is_convertible<
typename iterator_traits<T>::iterator_category, U>::value>
{
};
// 萃取某个迭代器的 category
template <class Iterator>
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>
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>
typename iterator_traits<Iterator>::value_type*
value_type(const Iterator&)
{
return static_cast<typename iterator_traits<Iterator>::value_type*>(0);
}
// 以下函数用于计算迭代器间的距离
// distance 的 input_iterator_tag 的版本
template <class InputIterator>
typename iterator_traits<InputIterator>::difference_type
distance_dispatch(InputIterator first, InputIterator last, input_iterator_tag)
{
typename iterator_traits<InputIterator>::difference_type n = 0;
while (first != last)
{
++first;
++n;
}
return n;
}
// distance 的 random_access_iterator_tag 的版本
template <class RandomIter>
typename iterator_traits<RandomIter>::difference_type
distance_dispatch(RandomIter first, RandomIter last,
random_access_iterator_tag)
{
return last - first;
}
template <class InputIterator>
typename iterator_traits<InputIterator>::difference_type
distance(InputIterator first, InputIterator last)
{
return distance_dispatch(first, last, iterator_category(first));
}
// 以下函数用于让迭代器前进 n 个距离
// advance 的 input_iterator_tag 的版本
template <class InputIterator, class Distance>
void advance_dispatch(InputIterator& i, Distance n, input_iterator_tag)
{
while (n--)
++i;
}
// advance 的 bidirectional_iterator_tag 的版本
template <class BidirectionalIterator, class Distance>
void advance_dispatch(BidirectionalIterator& i, Distance n, bidirectional_iterator_tag)
{
if (n >= 0)
while (n--) ++i;
else
while (n++) --i;
}
// advance 的 random_access_iterator_tag 的版本
template <class RandomIter, class Distance>
void advance_dispatch(RandomIter& i, Distance n, random_access_iterator_tag)
{
i += n;
}
template <class InputIterator, class Distance>
void advance(InputIterator& i, Distance n)
{
advance_dispatch(i, n, iterator_category(i));
}
/*****************************************************************************************/
// 模板类 : reverse_iterator
// 代表反向迭代器,使前进为后退,后退为前进
template <class Iterator>
class reverse_iterator
{
private:
Iterator current; // 记录对应的正向迭代器
public:
// 反向迭代器的五种相应型别
typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
typedef typename iterator_traits<Iterator>::value_type value_type;
typedef typename iterator_traits<Iterator>::difference_type difference_type;
typedef typename iterator_traits<Iterator>::pointer pointer;
typedef typename iterator_traits<Iterator>::reference reference;
typedef Iterator iterator_type;
typedef reverse_iterator<Iterator> self;
public:
// 构造函数
reverse_iterator() {}
explicit reverse_iterator(iterator_type i) :current(i) {}
reverse_iterator(const self& rhs) :current(rhs.current) {}
public:
// 取出对应的正向迭代器
iterator_type base() const
{
return current;
}
// 重载操作符
reference operator*() const
{ // 实际对应正向迭代器的前一个位置
auto tmp = current;
return *--tmp;
}
pointer operator->() const
{
return &(operator*());
}
// 前进(++)变为后退(--)
self& operator++()
{
--current;
return *this;
}
self operator++(int)
{
self tmp = *this;
--current;
return tmp;
}
// 后退(--)变为前进(++)
self& operator--()
{
++current;
return *this;
}
self operator--(int)
{
self tmp = *this;
++current;
return tmp;
}
self& operator+=(difference_type n)
{
current -= n;
return *this;
}
self operator+(difference_type n) const
{
return self(current - n);
}
self& operator-=(difference_type n)
{
current += n;
return *this;
}
self operator-(difference_type n) const
{
return self(current + n);
}
reference operator[](difference_type n) const
{
return *(*this + n);
}
};
// 重载 operator-
template <class Iterator>
typename reverse_iterator<Iterator>::difference_type
operator-(const reverse_iterator<Iterator>& lhs,
const reverse_iterator<Iterator>& rhs)
{
return rhs.base() - lhs.base();
}
// 重载比较操作符
template <class Iterator>
bool operator==(const reverse_iterator<Iterator>& lhs,
const reverse_iterator<Iterator>& rhs)
{
return lhs.base() == rhs.base();
}
template <class Iterator>
bool operator<(const reverse_iterator<Iterator>& lhs,
const reverse_iterator<Iterator>& rhs)
{
return rhs.base() < lhs.base();
}
template <class Iterator>
bool operator!=(const reverse_iterator<Iterator>& lhs,
const reverse_iterator<Iterator>& rhs)
{
return !(lhs == rhs);
}
template <class Iterator>
bool operator>(const reverse_iterator<Iterator>& lhs,
const reverse_iterator<Iterator>& rhs)
{
return rhs < lhs;
}
template <class Iterator>
bool operator<=(const reverse_iterator<Iterator>& lhs,
const reverse_iterator<Iterator>& rhs)
{
return !(rhs < lhs);
}
template <class Iterator>
bool operator>=(const reverse_iterator<Iterator>& lhs,
const reverse_iterator<Iterator>& rhs)
{
return !(lhs < rhs);
}
} // namespace mystl
#endif // !MYTINYSTL_ITERATOR_H_
参考资料:侯捷老师《stl源码剖析》
thin_stl项目
@深度学习可好玩了 C++:STL中的萃取器traits