当前位置: 首页 > news >正文

哈巴河网站制作宁波网站推广排名

哈巴河网站制作,宁波网站推广排名,深圳旅游网站建设,莱芜一中谭苗苗事件1.前言 STL主要由“用以表现容器&#xff0c;迭代器和算法”的template构成&#xff0c;但也覆盖若干工具性templates&#xff0c;其中一个名为advance&#xff0c;用来将某个迭代器移动某个给定距离&#xff1a; tempalte<typename IterT,typename DistT>//将迭代器向…

1.前言

STL主要由“用以表现容器,迭代器和算法”的template构成,但也覆盖若干工具性templates,其中一个名为advance,用来将某个迭代器移动某个给定距离:

tempalte<typename IterT,typename DistT>//将迭代器向前移动d单位
void advance(IterT& iter,DistT d);//如果d<0,则向后移动

观念上advance只是做iter+=d动作,但其实不可以全然是那样,因为只有random access(随机访问)迭代器才支持+=操作。面对其它迭代器种类,advance必须反复施行++或--,共d次。

先回顾下STL迭代器的分类:STL共有5种迭代器分类,inpiut迭代器只能向前移动,一次一步,客户可只读取它们所指的变量,而且只读取一次,他们模仿指向输入文件的阅读指针(read pointer);c++程序库中的istream_iterators是这一分类的代表。output迭代器情况类似,但一切只为输出:它们只向前移动,一次一步,客户只涂写一次。它们模仿指向输出文件的涂写指针(write pointer);ostream_iterators是这一分类的代表。这是功能最小的两个迭代器分类。由于这;两类都只能向前移动,而且只能读或写其所指物最多一次,所以它们只适合“一次性操作”(one-pass algorithms)。另一个功能比较强大的分类是forward迭代器。这种迭代器可以做前述两种分类所能做的每一件事,而且可以读或写其所指物一次以上。这使得它们可以施行于多次性操作算法(multi-pass algorithms)。STL并未提供单向linked list,但某些程序库有slit,而置入这种容器的迭代器就是属于forward迭代器。指入TR1 hashed容器的也可能是这一分类。

Bidirectional迭代器比上一个功能更大:它除了可以向前移动,还可以向后移动。STL的list迭代器就属于这一类,set,multiset,map和multimap的迭代器也都是这一分类。

最强大的迭代器当属random access迭代器。这种迭代器功能强大之处再与它可以执行“迭代器算术”,即可以在常量时间内向前或向后跳跃任意距离。

对这5种分类,c++标准程序库分别提供专属的卷标结构(tag struct)加以确认:

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 biairectional_iterator_tag{};

这些struct之间的继承关系是有效的is-a。

现在回到advance函数,我们知道STL迭代器有着不同的能力,实现advance的策略之一是采用“最低但最普及”的迭代能力,以循环往复递增或递减迭代器。然而这种做法耗费线性时间,我们知道random access迭代器支持迭代器算术运算,只耗费常量时间,如果面对这种迭代器,我们希望运用其优势:

然而我们真正希望的是以这种方式实现advance:

template<typename IterT,typename DistT>
void advance(IterT& iter,DistT d)
{if(iterT& iter,DistT d){if(iter is a random access iterator){iter+=d;//针对random access迭代器使用迭代器算术运算}else{if(d>=0){while(d--) ++iter;}else{if(d>=0){while(d--) ++iter;}else {while(d++) --iter;}//针对其它迭代器分类,反复调用++或--}}}}

这种做法首先是必须判断iter是否未random access迭代器,也就是说需要知道类型IterT是否为random access迭代器。换句话说我们需要取得类型的某些信息。那就是traits让你得以进行的事情:它们允许你在编译期间取得某些类型信息。。

2.实例分析

traits并不是c++关键自或一个预先定义好的构件;他们是一种技术,也是一个c++程序员共同遵守的协议。这个技术的要求之一是他对内置(built-in)类型或用户自定义类型的表现必须一样好。举个例子,如果上述advance仍然必须有效运作,那意味这traits技术必须i能够施行于内置类型如指针上。

”traits必须能够施行于内置类型“意味”类型内的嵌套信息(nesting information)“这种东西必须出局了,因为我们无法将信息嵌套于原始指针内。因此类型的traits信息必须位于类型自身之外。标准技术时把它放进一个template及其一个被命名为iterator_traits:

template<typename iterT>//template,用来处理
struct iterator_traits;//迭代器分类的相关信息

正如所看到的,iterattor_traits是个struct。习惯上traits总是被实现为structs,但它们又往往被称为traits classes。

iterator_traits的运作方式是针对每一个类型IterT,针对每一个类型IterT,在struct iterator_traits<IterT>内一定声明某个typedef名为iiterator_category,这个typedef用来确认IterT的迭代器分类。

iterator_traits以两个部分实现上述所言。首先它要求每一个“用户自定义的迭代器类型”必须嵌套一个typedef,名为iterator_category,用来确认适当的卷标结构。例如deque的迭代器可随机访问,所以一个针对deque迭代器而设计的class看起来会是这个样子:

template<...>
class deque{public:class iterator{public:typedef random_access_iterator_tag  iterator_category;....};....
};

list的迭代器可双向行进,所以它们应该是这样的:

template<...>
class list{public:class iterator{public:typedef bidirectional_iterator_tag iterator_category;....};....
};

至于iterator_traits,只是相应iterator class的嵌套式typedef:

//类型IterT的iterator_category其实是用来表现“IterT说它自己是什么”
//关于“typedef typename”的运用,见条款42
template<typename IterT>
struct iterator_traits{typedef typename IterT::iterator_category iterator_category;...
};

这对用户自定义类型行得通,但对指针(也是一种迭代器)行不通,因为指针不可能嵌套tepedef。iterator_traits的第二部分如下,专门用来对付指针:

为了支持指针迭代器,iterator_traits特别针对指针类型提供一个偏特化版本(partial template specialization)。由于指针的行径与random access迭代器类似,所以iterator_traits为指针指定的迭代器类型是:

template<typename IterT>//template偏特化
struct iterator_traits<IterT*>//针对内置指针
{typedef random_access_iterator_tag  iterator_category;....
};

现在,我们应该了解了如何设计并实现一个traits class了:

(1)确认若干你希望可取的的类型相关信息。例如对迭代器而言,我们希望将来可取其分类(category);

(2)为该信息选择一个名称(比如iterator_category)

(3)提供一个template和一组特化版本,内含你希望支持的类型相关信息。

现在有了iterator_traits(实际上是std::iterator_traits,因为它是c++标准程序的一部分),我们可以对advance实践先前的伪码(pseudocode):

template<typename IterT,typename DistT>
void advance(IterT& iter,DistT d)
{if(typeid(typename std::iterator_traits<IterT>::iterator_category)==typeid(std::random_access_iterator_tag))....
}

虽然这看起来前景光明,但并不是我们想要的。首先会导致编译问题。IterT类型在编译器间获知,所以iterator_traits<IterT>::iterator_category也可以在编译器间确定。但if语句却是在运行期才会核定。

我们真正想要的是一个条件式,判断“编译器核定成功”之类型。恰巧c++有一个取得这种行为的办法,那就是重载(overloading)。

当我们重载某个函数f,必须详细描述各个重载建房的参数类型。当你调用f,编译器便根据传来的实参选择最适合的重载件。编译器的态度是“如果这个重载件最匹配传递过来的实参,就调用这个f;如果那个重载件最匹配,就调用那个f;如果第三个f最匹配,就调用第三个f”。依次类推。这正是一个针对类型而发生的“编译器条件句”。为了让advance的行为如我们所期望的那样,我们需要做的是产生两版重载函数,内含advance的本质内容,但各自接受不同类型的iterator_category对象。我将这两个函数取名为doAdvance:

template<typename IterT,typename DistT>//用于random access 迭代器
void doAdvance(IterT& iter,typename Dist,std::random_access_iterator_tag)
{iter+=d;
}template<typename IterT,typename DistT,std::bidirectional_iterator_tag>//这份
{                                   //实现用于bidirectional迭代器if(d>=0){while(d--)++iter;}else{while(d++) --iter;}}
template<typename IterT,typename DistT>//这份用于实现input迭代器
void doAdvance(IterT& iter,DistT d,std::input_iterator_tag)
{if(d<0){throw std::out_of_range("Negative distance");}while(d--) ++iter;
}

由于forward_iterator继承自input_iterator_tag,所以上述doAdvance的input_iterator_tag版本也能够处理forward迭代器。这是iterator_tag structs继承关系带来的一项红利。实际上这也是public继承带来的部分好处:针对base class编写的代码用于derived class身上行得通。

advance函数规范说,如果面对的是random access和bidirectional迭代器,则接受正距离和负距离;但如果面对的是forward或input迭代器,则移动负距离会导致不明确(未定义)行为。我所检验过的实现码都假设d不为负,于是直接进入一个冗长的循环迭代,等待计数器降为0。上述异常我以抛出异常取而代之。

有了这些doAdvance重载版本,advance需要做的是调用它们并额外传递一个对象,后者必须带有适当的迭代器分类。于是编译器运用重载解析机制(overloading resolution)调用适当的实现代码:

template<typename IterT,typename DistT>
void advance(IterT& iter,DistT d)
{doAdvance(iter,d,typename std::iterator_traits<IterT>::iterator_category());
}

现在我们可以总结如何使用一个traits class了:

(1)建立一组重载函数或函数模板,,彼此间的差异只在于各自的traits参数。令每个函数实现码与其接受之traits信息相应和。

(2)建立一个控制函数或函数模板,它调用上述那些劳工函数并传递traits class所提供的信息。

traits广泛用于标准程序库,其中当然有上述讨论的iterator_traits,除了供应iterator_category还供应另四分迭代器相关信息。此外还有char_traits用来保存字符类型相关信息,以及numeric_limits用来保存数值类型的相关信息,例如某些数值类型可表现之最小值和最大值等等;命名为numeric_limits有点让人惊讶,因为traits classes的名称以"traits"结束,但numeric_limits却没有遵守这种风格。

3.总结

(1)Traits classes使得“类型相关信息”在编译器可用。它们以template和“templates特化”完成实现。

(2)整合重载技术后,traits classes有可能在编译器对类型执行if...else 测试。

http://www.shuangfujiaoyu.com/news/20990.html

相关文章:

  • 新疆企业电子网站建设谷歌推广一年多少钱
  • 免费搭建自己的官网想做seo哪里有培训的
  • 域名持有者个人可以做公司网站seo 优化教程
  • 手机数据线东莞网站建设技术支持百度福州分公司
  • 可以免费发帖的网站项目网
  • 做插画的网站网站开发报价方案
  • 做网站公司叫什么南京百度快速排名优化
  • 响应式网页网站设计引流推广犯法吗
  • 如何查看网站架构什么是关键词广告
  • 平面设计素材网站排行榜前十名个人推广平台
  • 建设局施工许可证网站免费网站java源码大全
  • 宁波做网站的专业公司口碑营销理论
  • 购物网站建设费用浙江seo外包
  • dz论坛做分类网站杭州排名优化公司
  • 一个网站如何挣钱如何做好线上营销
  • 帮忙做文档的网站什么是网站外链
  • 西安网站建设优化班级优化大师免费下载安装
  • 交互式网站设计 深圳微信营销的成功案例
  • 免费做h5的网站宁波seo公司
  • 电子商务网站建设的定义关键词优化报价推荐
  • 企业推广宣传方式商品标题优化
  • 企业网站必须备案seo报告
  • 建设摩托125图片大全seo优化软件哪个好
  • 做h5网站要多少钱百度知道登录
  • 学习做网站只学过c哪里可以接广告
  • 最近国内色情网站做的最好的是哪个百度关键词挖掘查排名工具
  • 做电影网站需要的服务器配置百度移动端排名
  • 网站建设 从用户角度开始网页推广怎么收取费用
  • 厦门网站建设开发中国婚恋网站排名
  • 重庆网站建设外包公司哪家好网课培训机构排名前十