STL中的Traits编程技法
最近在看读《STL源码剖析》,看到Traits编程技法这节时,不禁感慨STL源码作者的创新能力。那么什么是Traits编程技法呢?且听我娓娓道来:
我们知道容器的许多操作都是通过迭代器展开的。其中容器类似于数组,迭代器类似于指针。我们用数组来写个例子:
int arr[] = {,,,,};
int *p;
p = &arr[];
假设,我将第1、2遮挡起来,问你p所指向的对象arr[2]是什么类型,你恐怕无法回答。因为它可以是int,char,float甚至你自己定义的类型。假设我们现在是个容器:
list<int> lit(,);
list<int>::iterator it1,it2;
it1 = lit.begin();
it2 = lit.end();
其中lit是个容器对象,it1和it2都是容器的迭代器。假设现在有个函数,他接受两个迭代器作为参数,并且返回类型是迭代器所指的类型:
template<class iterator>
返回类型
fun(iterator first,iterator last)
{
//函数体
}
问题来了,现在我的返回类型假设是iterator所指向的类型。我们无法进行下去了。。。别怕,我们接着往下看:
如果我们将迭代器定义成一个类:
template<class T>
class My_iterator
{
public:
T* ptr;
typedef T value_type;
My_iterator(T* p = ):ptr(p){}
//...
};
也就是说如果我们的list的迭代器的类型也是上面那种形式,那么我们的fun函数就可以这样写了:
template<class iterator>
typename iterator::value_type //返回类型
fun(iterator first,iterator last)
{
//函数体
}
这样,迭代器所指的容器元素的类型就可以取出来了。怎么样,是不是很cool!但是不是所有的迭代器都是一个类啊,比如我们的原生指针也是迭代器的一种。vector的迭代器就是原生指针。那么用上面的那种方法似乎就不行了。但是STL的编写者创造了一个很好的方法---迭代器类型萃取模板,可以萃取原生指针所指向的元素的类型。对了,什么是原生指针?就是那种真正的是一个指针,我们的许多容器(list,deque)的迭代器是模拟指针但实际上它不是真正意义上的指针,他是一个类里面封装了原生指针。上面的My_iterator是迭代器,My_iterator里面的成员ptr就是原生指针。现在,是Traits编程技法发挥作用的时候了:
如果我们有个迭代器类型萃取模板,如下:
template<clas iterator> //专门用来萃取迭代器iterator指向的元素的类型
class My_iterator_traits
{
typedef typename iterator::value_type value_type;
//...
};
于是,我们的fun()函数就可以写成这样:
template<class iterator>
typename My_iterator_traits<iterator>::value_type //返回类新
fun(iterator first,iterator last)
{
//函数体
}
明眼人一眼就能看出这个代码跟原来的相比除了多一层包装,好像什么实质意义也没有,别急。我们这样写并不是做无用功,是为了应付上面说的原生指针而设计的。这时,我们的偏特化要派上用场了,针对原生指针的迭代器类型萃取偏特化模板如下:
template<clas iterator> //专门用来萃取迭代器iterator指向的类型的
class My_iterator_traits<iterator*>
{
//typedef typename iterator::value_type value_type;
typedef T value_type; //注意与上面的区别
//...
};
怎么样,这样一个迭代器类型萃取模板就这样诞生了。它可以萃取自定义的iterator类型和原生指针类型。但是,请注意了:在萃取自定义的iterator的时候这样写:
typedef typename iterator::value_type value_type;所以我们自定义的迭代器都应该定义时都应该有typedef T value_type.否则,你的迭代器就不能被正确萃取。STL的迭代器在定义的时候也是有类似的限制的!
STL中的Traits编程技法的更多相关文章
- STL——迭代器与traits编程技法
一.迭代器 1. 迭代器设计思维——STL关键所在 在<Design Patterns>一书中对iterator模式定义如下:提供一种方法,使之能够依序巡访某个聚合物(容器)所含的各个元素 ...
- 【STL 源码剖析】浅谈 STL 迭代器与 traits 编程技法
大家好,我是小贺. 点赞再看,养成习惯 文章每周持续更新,可以微信搜索「herongwei」第一时间阅读和催更,本文 GitHub : https://github.com/rongweihe/Mor ...
- [转]Traits 编程技法+模板偏特化+template参数推导+内嵌型别编程技巧
STL中,traits编程技法得到了很大的应用,了解这个,才能一窥STL奥妙所在. 先将自己所理解的记录如下: Traits技术可以用来获得一个 类型 的相关信息的. 首先假如有以下一个泛型的迭代器类 ...
- STL源码--iterator和traits编程技法
第一部分 iterator学习 STL iterators定义: 提供一种方法,使之能够依序巡访某个聚合物(容器)所含的各个元素,而又无需暴露该聚合物的内部表达方式. 任何iteartor都应该提供5 ...
- STL源码分析读书笔记--第三章--迭代器(iterator)概念与traits编程技法
1.准备知识 typename用法 用法1:等效于模板编程中的class 用法2:用于显式地告诉编译器接下来的名称是类型名,对于这个区分,下面的参考链接中说得好,如果编译器不知道 T::bar 是类型 ...
- STL Traits编程技法
traits编程技法大量运用于STL实现中.通过它在一定程度上弥补了C++不是强型别语言的遗憾,增强了C++关于型别认证方面的能力. traits编程技法是利用“内嵌型别”的编程技法和编译器的temp ...
- STL源码之traits编程技法
摘要 主要讨论如何获取迭代器相应型别.使用迭代器时,很可能用到其型别,若需要声明某个迭代器所指对象的型别的变量,该如何解决.方法如下: function template的参数推导机制 例如: tem ...
- STL源码剖析——iterators与trait编程#2 Traits编程技法
在算法中运用迭代器时,很可能用到其相应类型.什么是相应类型?迭代器所指对象的类型便是其中一个.我曾有一个错误的理解,那就是认为相应类型就是迭代器所指对象的类型,其实不然,相应类型是一个大的类别,迭代器 ...
- STL之traits编程技法
traits编程技法利用了“内嵌型别”的编程技巧与编译器的template参数推导功能. 下面主要看看利用traits编程技法实现的迭代器萃取机制. 5种迭代器类型定义: struct input_i ...
随机推荐
- [转] 整理了一份React-Native学习指南
自己在学习React-Native过程中整理的一份学习指南,包含 教程.开源app和资源网站等,还在不断更新中.欢迎pull requests! React-Native学习指南 本指南汇集React ...
- 观察者模式-Observer
观察者模式很好理解,简单来说就是:当一个对象变化时,其它依赖该对象的对象都会收到通知,并且随着变化!对象之间是一种一对多的关系. 1. 自己手工创建Observer模式 首先,创建观察者接口: pub ...
- java格式处理工具类
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOExceptio ...
- Java基础知识强化之集合框架笔记24:ArrayList存储自定义对象并遍历
1. ArrayList存储自定义对象并遍历 2. 代码示例: Student.java,如下: package cn.itcast_01; public class Student { privat ...
- iOS获取健康步数从加速计到healthkit
计步模块接触了一年多,最近又改需求了,所以又换了全新的统计步数的方法,整理一下吧. 在iPhone5s以前机型因为没有陀螺仪的存在,所以需要用加速度传感器来采集加速度值信息,然后根据震动幅度让其加入踩 ...
- List<T>取交集、差集、并集
1. 取交集 (A和B都有) List A : { 1 , 2 , 3 , 5 , 9 }List B : { 4 , 3 , 9 }var intersectedList = list1.Inte ...
- iOS socket编程
// // ViewController.m // socket // // Created by emerys on 16/3/2. // Copyright © 2016年 Emerys. All ...
- VB热点答疑(2016.5.11更新Q4、Q5)
收录助教君在VB习题课上最常被问到的问题,每周更新,希望对大家有所帮助. Q1.如何让新的文本内容接在原来的内容后面/下一行显示? A1.例如,Label1.text原本的内容是"VB程序设 ...
- spring-quartz普通任务与可传参任务
两者区别与作用: 普通任务:总调度(SchedulerFactoryBean)--> 定时调度器(CronTriggerFactoryBean) --> 调度明细自定义执行方法bean(M ...
- Win异常: 除了chrome浏览器外,所有安装的软件都连不上网
经查找资料,是LSP被篡改,恢复后使用正常. 百度百科 LSP: Layered Service Provider, 即分层服务提程序,Winsock 作为应用程序的 Windows 的网络套接字工 ...