Iterators有不同的类型,每种类型都代表着不同的能力,它在重载某个行为时,是有用的,甚至有必要。通过iterators tags和iterator traits 重载可以实现。对于么一个iterator类型STL都提供一个 terator
tag ,这个 terator
tag 能被做一个 ’table”.
namespace std {
struct output_iterator_tag {
};
struct input_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 category ,例如你可能需要迭代器引用的类型,所以STL提供了一个特殊的面板结构体来定义iterator traits ,这个结构体包含了所有关于an iterator 的信息。它被用于定义一个iterator类型的正常的接口。
namespace std {
template <class T>
struct iterator_traits {
typedef typename T::value_type value_type;
typedef typename T::difference_type difference_type;
typedef typename T::iterator_category iterator_category;
typedef typename T::pointer pointer;
typedef typename T::reference reference;
};
}
这个结构体的模板参数是iterator.
这个结构体有两个有点:
1. 它保证一个iterator 提供了所有的类型定义。
2. 它能被特殊的迭代器特化或部分特化。
例如
namespace std {
template <class T>
struct iterator_traits<T*> {
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef random_access_iterator_tag iterator_category;
typedef T* pointer;
typedef T& reference;
};
}
因此对于任何指向T 的指针类型,它都是random
access iterator 种类。
怎么写一个泛型函数。
如果你写泛型函数没有用到iterator_traits ,它的实现很简单。例如:
template <class OutPutIterator>
void display(OutPutIterator start,OutPutIterator end)
{
while(start!=end)
{
cout<<*start<<" ";
++start;
}
cout<<endl;
}
这个使用于任何顺序容器。
但有的时候能用到,为了不同iterator 种类,你一定要有以下两步:
Step 1. 让你的模板函数调用另一个函数,该函数增加了一个iterator
category参数。
例如:
template <class Iterator>
inline void foo (Iterator beg, Iterator end)
{
foo (beg, end,std::iterator_traits<Iterator>::iterator_category());
}
Step2 :
为每一个iterator 种类实现一个函数实现:
template <class BiIterator>
void foo (BiIterator beg, BiIterator end,
std::bidirectional_iterator_tag)
{
...
}
// foo() for
random access iterators
template <class RaIterator>
void foo (RaIterator beg, RaIterator end,
std::random_access_iterator_tag)
{
}
看下advance() 函数的实现过程。
template <class Iterator>
typename std::iterator_traits<Iterator>::difference_type
distance (Iterator pos1, Iterator pos2)
{
return distance (pos1, pos2,std::iterator_traits<Iterator>::iterator_category());
}
//distance() for random access iterators
template <class RaIterator>
typename std::iterator_traits<RaIterator>::difference_type
distance (RaIterator pos1, RaIterator pos2,
std::random_access_iterator_tag)
{
return pos2 - pos1;
}
//distance() for input, forward, and bidirectional iterators
template <class InIterator>
typename std::iterator_traits<lnIterator>::difference_type
distance (Inlterator pos1, InIterator pos2,
std::input_iterator_tag)
{
typename std::iterator_traits<lnIterator>::difference_type d;
for (d=0; pos1 != pos2; ++pos1, ++d) {
;
}
return d;
}
如何定义一个iterator
在定义自己的iterator 时,你需要提供iterator
traits。
有两种方法;
1. 提供必要的iterator_traits 的五种类型。
2. 提供iterator_traits 结构体的特化。
对于第一种方法,STL 提供了一个基类iteratoe<>, 它用于类型的定义。你可以这样:
class MyIterator
: public std::iterator <std::bidirectional_iterator_tag,
type, ptrdiff_t, type*,
type &> {
...
};
第一个参数是the iterator category, 第二个参数是元素类型type,第三个是差值类型(difference type),第四个是指针类型(pointer type),第五个是引用类型(reference type),最后三个是可选的,它们默认的类型:ptrdif_f_t, type *, and type & 。
namespace std {
struct output_iterator_tag {
};
struct input_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 category ,例如你可能需要迭代器引用的类型,所以STL提供了一个特殊的面板结构体来定义iterator traits ,这个结构体包含了所有关于an iterator 的信息。它被用于定义一个iterator类型的正常的接口。
namespace std {
template <class T>
struct iterator_traits {
typedef typename T::value_type value_type;
typedef typename T::difference_type difference_type;
typedef typename T::iterator_category iterator_category;
typedef typename T::pointer pointer;
typedef typename T::reference reference;
};
}
这个结构体的模板参数是iterator.
这个结构体有两个有点:
1.
2.
例如
namespace std {
template <class T>
struct iterator_traits<T*> {
typedef T value_type;
typedef ptrdiff_t difference_type;
typedef random_access_iterator_tag iterator_category;
typedef T* pointer;
typedef T& reference;
};
}
因此对于任何指向T
怎么写一个泛型函数。
如果你写泛型函数没有用到iterator_traits
template <class OutPutIterator>
void display(OutPutIterator start,OutPutIterator end)
{
while(start!=end)
{
cout<<*start<<" ";
++start;
}
cout<<endl;
}
这个使用于任何顺序容器。
但有的时候能用到,为了不同iterator
Step 1.
例如:
template <class Iterator>
inline void foo (Iterator beg, Iterator end)
{
foo (beg, end,std::iterator_traits<Iterator>::iterator_category());
}
Step2
为每一个iterator
template <class BiIterator>
void foo (BiIterator beg, BiIterator end,
std::bidirectional_iterator_tag)
{
...
}
template <class RaIterator>
void foo (RaIterator beg, RaIterator end,
std::random_access_iterator_tag)
{
}
看下advance()
template <class Iterator>
typename std::iterator_traits<Iterator>::difference_type
distance (Iterator pos1, Iterator pos2)
{
return distance (pos1, pos2,std::iterator_traits<Iterator>::iterator_category());
}
//distance() for random access iterators
template <class RaIterator>
typename std::iterator_traits<RaIterator>::difference_type
distance (RaIterator pos1, RaIterator pos2,
std::random_access_iterator_tag)
{
return pos2 - pos1;
}
//distance() for input, forward, and bidirectional iterators
template <class InIterator>
typename std::iterator_traits<lnIterator>::difference_type
distance (Inlterator pos1, InIterator pos2,
std::input_iterator_tag)
{
typename std::iterator_traits<lnIterator>::difference_type d;
for (d=0; pos1 != pos2; ++pos1, ++d) {
;
}
return d;
}
如何定义一个iterator
在定义自己的iterator
有两种方法;
1. 提供必要的iterator_traits
2. 提供iterator_traits
对于第一种方法,STL
class MyIterator
: public std::iterator <std::bidirectional_iterator_tag,
...
};
第一个参数是the iterator category, 第二个参数是元素类型type,第三个是差值类型(difference type),第四个是指针类型(pointer type),第五个是引用类型(reference type),最后三个是可选的,它们默认的类型:ptrdif_f_t,
本文深入探讨了C++中迭代器的概念,包括不同类型的迭代器及其特性和用途,通过实例展示了如何利用迭代器特性进行泛型编程,并详细解释了如何定义和使用迭代器特性结构体。此外,文章还介绍了如何根据迭代器类型定义泛型函数及实现代理函数的方法。
1142

被折叠的 条评论
为什么被折叠?



