《Effective C++》再次探索traits技法
来源:互联网 发布:波士顿矩阵分析案例ppt 编辑:程序博客网 时间:2024/05/16 04:46
首先介绍C++标准程序库中的五种迭代器,关于这个可以看我的另一个笔记:http://blog.csdn.net/m0_37316917/article/details/70053513。
对于这五种分类,C++标准程序库分别提供专属的标志结构加以确认:
struct input_iterator_tag{};struct output_iterator_tag{};struct forward_iterator_tag{}:public input_iterator_tag{};struct bidirectional_tag:public forward_iterator_tag{};struct random_access_iterator_tag:public bidirectional_iterator_tag{};
这些struct之间的继承关系是有效的is-a的挂系,所有forward迭代器都是input迭代器,以此类推。
traits并不是C++关键字或者一个预先定义好的构件,它们是一种技术,也是C++程序员共同遵守的协议,这个技术的要求之一是,它对内置类型和用户自定义类型的表现必须一样好,比如下面的advance函数:
template<typename IterT,typename DistT>void advance(IterT&iter,Dist d){ if(iter is a random access iterator) { iter+=d; } else { if(d>=0) {while(d--)++iter;} else {while(d++)--iter;} }}
advance()如果收到的实参是一个指针(例如const char*)和一个int,上述advance仍然必须有效运作,那意味着traits技术也必须能够施行于内置类型比如指针身上。
“traits必须能够施行与内置类型”意味着“类型内的嵌套信息(nesting information)”这种东西出局了,因为我们无法将信息嵌套于原始指针中国,因此类型的traits信息必须位于类型自身之外,标准技术是将它放进一个template及其一个或者多个特化版本中,这样的templates在标准程序库中有多个,其中针对迭代器者被命名为iterator_traits:
template<typename IterT>struct iterator_traits;//迭代器分类的相关信息
如你所限,iterator_traits是个struct,西瓜上traits纵使被实现为struct,但它们却又被成为traits classes。
iterator_traits的运作方式是,针对每一个类型IterT,在struct iterator_traits内一定声明某个typedef名为iterator_category,这个typedef用来确认IterT的迭代器分类。
为了支持内置类型指针迭代器。Iterator_traits特别针对指针类型提供一个偏特化版本,由于指针的行为和random access迭代器累死,所以iterator_traits为指针指定的迭代器类型是:
template<typename IterT>struct iterator_traits<IterT*>{typedef random_access_iterator_tag iterator_category;};
现在我们可以对advance实践之前的伪代码。
template<typename IterT,typename DistT>void advance(IterT&iter,DIstT d){ if(typeid(typename std::iterator_traits<IterT>::iterator_category)==typeif(std::random_access_iterator_tag)) ......;//do something}
但是这种方法将会导致编译问题,IterT的类型在编译期间获得,所以iterator_traits::iterator::category也可在编译期间确定,但if语句是在运行期才会核定,为什么将可在编译期完成的事情延迟到运行期才完成呢?这不仅浪费实践,也造成可执行代码的膨胀。
我们需要一个办法在编译期期间核定类型成功,这个办法就是重载:
template<typename IterT,typename DistT>void doadvance(IterT&iter,DIstT d,std::random_access_iterator_tag)//用于实现random access迭代器{ iter+=d;}template<typename IterT,typename DistT>void doadvance(IterT&iter,DIstT d,std::bidirectional_iterator_tag)//用于实现bidirectional迭代器{ if(d>=0) {while(d--) ++iter;} else{while(d++)--iter;}}template<typename IterT,typename DistT>void doadvance(IterT&iter,DIstT d,std::input_iterator_tag)//用于实现input迭代器{ if(d<0) throw std::out_of_range("Nagetive distance"); while(d--)++iter;}
由于forward_iterator_tag继承自input_iterator_tag,所以上述doadvance的input_iterator_tag版本也能够处理forward迭代器,这是iterator_tag structs继承关系带来的一项红利,实际上这也是public继承带来的部分好处:针对base class编写的代码用于derived class也行得通。
有了这些doadvance重载版本,advance需要做的只是调用它们并且额外传递一个对象,后者必须带有适当的迭代器分类,于是编译期运用重载解析几只调用适当的实现代码:
template<typename IterT,typename DistT>void advance(IterT&iter,DistT d){ doadvance(iter,d,typename std::iterator_traits<IterT>::iterator_category());}
- 《Effective C++》再次探索traits技法
- C++—Traits编程技法
- 【深度探索STL】详解 traits 编程技法
- C++——Traits编程技法
- Traits编程技法一
- STL之traits技法
- traits编程技法感悟
- Traits编程技法
- traits编程技法
- traits编程技法感悟
- 迭代器与traits编程技法
- 《STL源码剖析》traits技法
- STL之traits编程技法
- STL之traits编程技法
- Traits编程技法之type_trait
- Traits编程技法之iterator_traits
- STL中的traits编程技法
- STL中traits编程技法
- Hibernate学习笔记之关联关系
- spring boot开发项目,部署到tomcat,启动报错
- 使用Lock和Condition实现生产者消费者模型
- 拓扑排序模板题-确定比赛名次 HDU
- RHEL 7.2 安装 oracle
- 《Effective C++》再次探索traits技法
- 【bzoj4027】[HEOI2015]兔子与樱花
- JavaWeb-Servlet
- 响应式布局中边框问题
- jstree中文github文档
- apache加载模块的说明
- Matlab 形态学图像处理
- C++ STL/ (13) 常用遍历算法
- bzoj 4199: [Noi2015]品酒大会 后缀数组+并查集