STL五种迭代器类型(卷标):
struct input_iterator_tag{} ; =>1
struct output_iterator_tag{} ; =>2
struct forward_iterator_tag:public input_iterator_tag{} ; =>3
struct bidirectional_iterator_tag:public forward_iterator_tag{} ; =>4
struct random_access_iterator_tag:public bidirectional_iterator_tag{} ; =>5
卷标:每一卷是一个类型,给一个卷标标识一个类别
=>1:input迭代器 只能向前移动,一次一步,客户只能读取,不能涂写它所指向的东西,而且只能读取一次
.模仿指向输入文件的阅读指针,如C++程序库中的istream_iterator
=>2:output迭代器 只能向前移动,一次一步,客户只能涂写,而且只能涂写一次
.模仿指向输出文件的涂写指针,如C++程序库中的ostream_iterator
这是威力最小的两个迭代器分类,只能向前移动,而且只能读或写所指物最多一次,只适合”一次性操作算法”
=>3:单向 可读写一次以上
.slist的迭代器
=>4:双向 可读写一次以上
.set,multiset,map,multimap的迭代器
=>5:双向 可读写一次以上 可执行迭代器算术运算
.vector,deque,string的迭代器
Ttrais是一种技术,也是C++程序猿共同遵守的协议,
对内置类型和用户自定义类型的表现一样好
那怎么达到这个要求:自定义类型用template,内置
类型对应多个特化版本
例如:iterator_traits
template<typename IterT>
struct iterator_traits ;
遵守协议:要求每一个”用户自定义的迭代器类型”
必须嵌套一个typedef,名为iterator_category,用来确认适当的卷标
template<...>
class deque{
public:
class iterator {
typedef random_access_iterator_tag iterator_category ;
...
} ;
...
} ;
template<...>
class list{
public:
class iterator {
typedef bidirectional_iterator_tag iterator_category ;
...
} ;
...
} ;
那么接下来可以定义iterator_traits:
template<typename IterT>
struct iterator_traits {
Typedef typename IterT::iterator_category iterator_catory
}
为了同样适用指针:偏特化
template<typename IterT>
Struct iterator_traits<IterT*>
{
typedef random_access_iterator_tag iterator_category ;
...
} ;
advance函数:
有了iterator_traits,advance函数可如下实现
// "工头" 调用 "劳工"并传入traits class提供的信息
template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d)
{
doAdvance( // "劳工"
iter, d,
typename
std::iterator_traits<IterT>::iterator_category() // ()表示对象
) ;
}
“编译器条件语句”:利用函数函数重载
所以doAdvance有多个重载形式
=>1
template<typename IterT, typename Dist>
void doAdvance(IterT& iter, Dist d, std::random_access_iterator_tag)
{
iter += d ;
}
=>2
template<typename IterT, typename Dist>
void doAdvance(IterT& iter, Dist d, std::bidirectional_iterator_tag)
{
if(d >= 0) {while(d—) ++iter; }
else { while(d++) --iter ; }
}
=>3
template<typename IterT, typename Dist>
void doAdvance(IterT& iter, Dist d, std::input_iterator_tag)
{
if(d < 0) {
throw std::out_of_range("Negativ\
e distance") ;
}
while(d--) ++iter ;
}
用上面的3中重载形式作为if判断
=>3 同样会适配std::forward_iterator_tag
因为它public继承自input_iterator_tag,
这是public继承的红利:针对base class编写
代码,用于derived class身上也行得通
traits_class通常以traits结尾
如std::iterator_traits<T> 给出T的指针类型
例外:std::numeric_limits<T>表现T的最大z最
小值
std::cout << std::number_limits<int>::min() << "\n" ;
std::cout << std::number_limits <int>::max() << "\n" ;
std:is_fundamental<T> 判断T是否为内
置类型
std::cout << "unsigned is_fundamental:" << std::is_fundamental<unsinged>::value << "\n" ;
// 输出:true