一: 迭代器辅助函数, 方便的操作迭代器
advance(Iterator, n) : 使迭代器前进或后退n个位置, 直接改动迭代器, 不返回值
distance(Iterator_first,Iterator_last ): 计算两个迭代器的距离
iter_swap(Iterator ,Iterator) 交换两个迭代器所指元素的值, 不是交换两个迭代器
vector<int> v1;
v1={1,2,3};
auto i1=v1.begin();
auto i2=v1.end();
auto i3=v1.end();
assert( i2==i3 );
iter_swap(i1,i2);
assert( i2==i3 ); //交换后还成立
二: 迭代适配器:把一种迭代器转换为另一种迭代器
标准库里有如下几种
逆向迭代器: 反序迭代
转移迭代器: 迭代器返回右值引用
插入迭代器: 赋值操作转换为插入操作
流迭代器: 把IO流转换为迭代器操作
插入迭代器:
vector<int> v1,v2;
//直接创建v1的插入迭代器
auto it=back_inserter(v1);
*it=1;//将1加入到v1中。
*it=2;//将2加入到v1中
//对v2创建插入迭代器, 把v1的元素全部插入到v2
copy(v1.begin(),v1.end(), back_inserter(v2));
流迭代器:
//直接创建cout的流迭代器
auto out=ostream_iterator<int>(cout);
*out=1;//将1加入到 out里(即cout<<1)
*out=2;//将1加入到 out里(即cout<<2)
//*out="b"; error ,上面已经指定了流迭代器类型为int
//输出v1的每个元素, 第二个参数可用于控制分隔标志
copy(v1.begin(),v1.end(), ostream_iterator<int>(cout,"\n"));
三:next()与prev()
上面提到advance无返回值, 且会修改原迭代器
而boost库的next()和prior函数, 标准库里的next()和prev()提供可以获取第n个迭代器但不改变原迭代器的功能
boost库的next函数简要, 其中用了模板元编程
template<typename T>
inline T next(T x)
{return ++x;}
template<typename T,typename Distance>
inline T next(T x,Distance n) //这里传形参不传引用
{
std::advance(x,n); //不改变实参
return ++x;
}
而标准库里的next()则使用了默认参数=1
template<class ForwardIterator>
ForwardIterator next(ForwardIterator x, difference_type n = 1);
四:iterator_traits库
iterator_traits库用来获取迭代器(或指针)的属性
可以获取以下五种类型信息
iterator_category :迭代器的分类
value_type :值的类型
pointer :指针类型
difference_type :距离类型
reference :引用类型
其中iterator_category即迭代器的分类在标准库里有以下几种
输入迭代器: 只读迭代器,只提供operator++, 可以比较相等
输出迭代器: 只写迭代器,只提供operator++,不能比较
前向迭代器:可以读写, 提供operator++, 可以比较相等和赋值
双向迭代器: 在前向迭代器基础上提供operator--
随机访问迭代器: 双向迭代器基础上增加了迭代器的算术运算功能, 提供operator[]和operator+=
对应的标签如下, 可以看到继承包含关系
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_traits对vector<int>的迭代器操作如下
vector<int> v1;
auto it=v1.begin();// 换成int*it;下面断言一样都成立
static_assert(is_same_v<iterator_traits<decltype(it)>::reference , int &>);
static_assert(is_same_v<iterator_traits<decltype(it)>::iterator_category , random_access_iterator_tag>);
static_assert(is_same_v<iterator_traits<decltype(it)>::value_type , int>);
static_assert(is_same_v<iterator_traits<decltype(it)>::pointer , int*>);
static_assert(is_same_v<iterator_traits<decltype(it)>::difference_type , long long>);
可知vector<int>迭代器信息如下:
引用类型: int&
迭代器分类: random_access_iterator_tag(即随机访问)
值类型: int
指针类型: int*
距离类型: long long
boost库的iterator_traits库和标准库的略有差别, 其中把相应的5个元数据分成5个不同的元函数调用
boost::iterator_category //分类
boost::iterator_pointer //指针类型
boost::iterator_reference //引用类型
boost::iterator_value //值类型
boost::iterator_difference //距离类型
五:boost::iterator_facade, 用外观模式提供一个辅助类, 更容易自己创建标准的迭代器
头文件 #include "boost/iterator/iterator_facade.hpp"
核心操作有几个(依据迭代器的类型不必全都实现), 通常声明为private
解引用: dereference(), 实现可读和可写必须
相等比较: equal(), 实现单遍迭代器必须
递增: increment() ,实现可递增迭代器和前向遍历迭代器必须
递减: decrement(), 实现双向遍历迭代器必须
距离计算:advance()和distance_to(), 实现随机访问遍历迭代器必须
iterator_facade有五个模板参数, 对应iterator_traits里的五个迭代器信息
template <
class Derived //迭代器子类
, class Value //值类型
, class CategoryOrTraversal //迭代器分类
, class Reference = Value& //引用类型
, class Difference = std::ptrdiff_t //距离类型
>
class iterator_facade;
后面两个可以用缺省参数, 可以只关心前3个
Derived :子类的名字, 即正在编写的类名称
Value :迭代器值类型
CategoryOrTraversal: 迭代器分类
boost库对迭代器进行了更细致的分类, 除了标准库的五个外 , 还包括
using iterators::incrementable_traversal_tag; using iterators::single_pass_traversal_tag; using iterators::forward_traversal_tag; using iterators::bidirectional_traversal_tag; using iterators::random_access_traversal_tag;
用法示例一
#include<bits/stdc++.h>
#include "boost/iterator/iterator_facade.hpp"
using namespace std;
template<typename T>
class vs_iterator :
public boost::iterator_facade< //基类链继承技术
vs_iterator<T>, T, //子类名和值类型
boost::single_pass_traversal_tag> //单遍迭代器类型
{
private:
vector<T> &v;
int current_pos;
public:
using super_type = boost::iterator_facade<vs_iterator<T>, T, boost::single_pass_traversal_tag>;
using this_type = vs_iterator;
using reference = typename super_type::reference;
vs_iterator(vector<T> &v_, int pos = 0) : v(v_), current_pos(pos) //构造函数
{}
vs_iterator(this_type const &other) : v(other.v), current_pos(other.current_pos) //拷贝构造函数
{}
void operator=(this_type const &other) //赋值函数
{
this->v = other.v;
this->current_pos = other.current_pos;
}
private:
friend class boost::iterator_core_access; //必须的友元声明
reference dereference() const //解引用操作
{
return v[current_pos];
}
void increment() //递增操作
{
++current_pos;
}
bool equal(this_type const &other) const //比较操作
{
return this->current_pos == other.current_pos;
}
};
int main()
{
vector<int> v{1, 2, 3, 4};
vs_iterator vsi(v); //对应v.begin()
vs_iterator vsi_end(v, v.size()); //对应v.end()
//使用operator*操作元素
assert(*vsi == 1);
//注意 vsi_end对应v.end(), *vsi_end!=4
assert(*vsi_end != 4);
//copy算法将元素输出到cout
copy(vsi, vsi_end, ostream_iterator<int>(cout, ","));
return 0;
}
//输出->
1,2,3,4,
从示例可以看出使用时需要的操作
-- public继承boost::iterator_facade, 且指明模板类型: 子类(当前类), 值类型, 迭代器类型
-- 写出接口的实现,这里单边迭代器类型为boost::single_pass_traversal_tag, 需实现
dereference()
increment()
equal
-- 必备的友元声明: friend class boost::iterator_core_access;
示例2: 每次跳跃N步长的迭代器
有漏洞, equal函数貌似无法正确实现
#include<bits/stdc++.h>
#include "boost/iterator/iterator_facade.hpp"
using namespace std;
template<typename T, ptrdiff_t N = 2> //默认步长为2
class step_iterator :
public boost::iterator_facade< //基类链继承技术
step_iterator<T>, typename iterator_traits<T>::value_type const, //子类名和值类型
boost::single_pass_traversal_tag> //单遍迭代器类型
{
private:
T iter;
public:
using super_type = boost::iterator_facade<
step_iterator<T>, typename boost::iterator_value<T>::type const,
boost::single_pass_traversal_tag>;
using this_type = step_iterator;
using reference = typename super_type::reference;
step_iterator(T x) : iter(x)
{}
step_iterator(this_type const &) = default;
this_type &operator=(this_type const &) = default;
private:
friend class boost::iterator_core_access; //必须的友元声明
reference dereference() const //解引用操作
{
return *iter;
}
void increment() //递增操作
{
advance(iter, N);
}
bool equal(this_type const &other) const //比较操作
{
/*这里疑似有漏洞
* 直接 return iter == other.iter; 时, 步数大于1时可能跳过比较最后的迭代器,
* 导致 copy(first, last, ostream_iterator<char>(cout)); 出错
*
* 但用以下的方法又不能正确的比较迭代器是否相等,只是这里copy时没错
*/
int i;
for(i=0 ;i <N; i++)
{
if(next(iter,i)==other.iter)
return true;
}
return false;
}
};
int main()
{
char s[] = "123456789";
step_iterator<char *> first(s), last(s + sizeof(s)); //改不了步长, step_iterator<char *,3>无效, 还是默认步长2,
copy(first, last, ostream_iterator<char>(cout));
return 0;
}
六:iterator_adaptor
派生自iterator_facade, 同样使用了基类链技术, 用法和iterator_facade差不多, 但只需编写少数核心变化的操作函数即可, 用法较简单
有6个模板参数, 通常只用前2个
template <
class Derived
, class Base
, class Value = use_default
, class Traversal = use_default
, class Reference = use_default
, class Difference = use_default
>
class iterator_adaptor;
被适配对象(Adaptee)必须是可拷贝构造和可赋值的, 不一定要有operator++, 也就是说不一定是一个迭代器
用法示例一
#include<bits/stdc++.h>
#include "boost/iterator/iterator_adaptor.hpp"
using namespace std;
template<typename P>
class array_iter:public boost::iterator_adaptor<array_iter<P>,P>
{
static_assert( is_pointer_v<P> ); //保证P是一个指针
public:
using super_type = typename array_iter::iterator_adaptor_; //用iterator_adaptor_ 省去了写出一长串模板参数列表声明父类
array_iter(P x):super_type(x){} //必要的构造函数
};
int main()
{
int a[10]={1,2,3};
array_iter<int*> start(a),finish(a+10);
start+=1;
copy(start,finish,ostream_iterator<int>(cout));
return 0;
}
示例二: 实现访问存储增量数值
每次访问递增迭代器, 就把容器的值加上
值引用类型处须加const, 否则会造成非const引用的问题
大概是这个原因吧?目前不太清楚
#include<bits/stdc++.h>
#include "boost/iterator/iterator_adaptor.hpp"
using namespace std;
template<typename P>
class array_iter : public boost::iterator_adaptor<array_iter<P>, P>
{
static_assert(is_pointer_v<P>); //保证P是一个指针
public:
using super_type = typename array_iter::iterator_adaptor_; //用iterator_adaptor_ 省去了写出一长串模板参数列表声明父类
array_iter(P x) : super_type(x)
{} //必要的构造函数
};
template<typename I>
class delta_iterator : public boost::iterator_adaptor<
delta_iterator<I>, I,
typename iterator_traits<I>::value_type, //值类型
boost::single_pass_traversal_tag, //单向遍历
typename iterator_traits<I>::value_type const> //值引用类型, 只读,不加const会报错
{
friend class boost::iterator_core_access; //必须的友元声明
using this_type = delta_iterator;
using super_type = typename this_type::iterator_adaptor_; //基类定义
typename super_type::value_type m_value; //存储当前的值
public:
delta_iterator(const I &iter) : super_type(iter), m_value(0) //当前值从0开始
{}
private:
using super_type::base;
using super_type::base_reference;
typename super_type::reference dereference() const
{
return m_value + *base(); //返回存储的值+当前的值
}
void increment()
{
m_value += *base(); //存储的值+=当前的值
++base_reference();//迭代器前进
}
};
int main()
{
vector<int> a = {1, 2, 3, 4};
delta_iterator<decltype(a.begin())> start(a.begin()), finish(a.end());
copy(start, finish, ostream_iterator<int>(cout, ","));
return 0;
}
//输出->
1,3,6,10