最近在看读《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编程技法的更多相关文章

  1. STL——迭代器与traits编程技法

    一.迭代器 1. 迭代器设计思维——STL关键所在 在<Design Patterns>一书中对iterator模式定义如下:提供一种方法,使之能够依序巡访某个聚合物(容器)所含的各个元素 ...

  2. 【STL 源码剖析】浅谈 STL 迭代器与 traits 编程技法

    大家好,我是小贺. 点赞再看,养成习惯 文章每周持续更新,可以微信搜索「herongwei」第一时间阅读和催更,本文 GitHub : https://github.com/rongweihe/Mor ...

  3. [转]Traits 编程技法+模板偏特化+template参数推导+内嵌型别编程技巧

    STL中,traits编程技法得到了很大的应用,了解这个,才能一窥STL奥妙所在. 先将自己所理解的记录如下: Traits技术可以用来获得一个 类型 的相关信息的. 首先假如有以下一个泛型的迭代器类 ...

  4. STL源码--iterator和traits编程技法

    第一部分 iterator学习 STL iterators定义: 提供一种方法,使之能够依序巡访某个聚合物(容器)所含的各个元素,而又无需暴露该聚合物的内部表达方式. 任何iteartor都应该提供5 ...

  5. STL源码分析读书笔记--第三章--迭代器(iterator)概念与traits编程技法

    1.准备知识 typename用法 用法1:等效于模板编程中的class 用法2:用于显式地告诉编译器接下来的名称是类型名,对于这个区分,下面的参考链接中说得好,如果编译器不知道 T::bar 是类型 ...

  6. STL Traits编程技法

    traits编程技法大量运用于STL实现中.通过它在一定程度上弥补了C++不是强型别语言的遗憾,增强了C++关于型别认证方面的能力. traits编程技法是利用“内嵌型别”的编程技法和编译器的temp ...

  7. STL源码之traits编程技法

    摘要 主要讨论如何获取迭代器相应型别.使用迭代器时,很可能用到其型别,若需要声明某个迭代器所指对象的型别的变量,该如何解决.方法如下: function template的参数推导机制 例如: tem ...

  8. STL源码剖析——iterators与trait编程#2 Traits编程技法

    在算法中运用迭代器时,很可能用到其相应类型.什么是相应类型?迭代器所指对象的类型便是其中一个.我曾有一个错误的理解,那就是认为相应类型就是迭代器所指对象的类型,其实不然,相应类型是一个大的类别,迭代器 ...

  9. STL之traits编程技法

    traits编程技法利用了“内嵌型别”的编程技巧与编译器的template参数推导功能. 下面主要看看利用traits编程技法实现的迭代器萃取机制. 5种迭代器类型定义: struct input_i ...

随机推荐

  1. JDK5-增强for循环

    下面的程序演示了增强for循环在数组及集合中的应用: import java.util.ArrayList; import java.util.HashMap; import java.util.Ha ...

  2. jQuery日期联动插件

    此版本为网上的日期联动插件修改版,加入了修改后事件 /* * jQuery Date Selector Plugin * 日期联动选择插件 * * Demo: $("#calendar&qu ...

  3. CentOS 6.7 编译安装Nginx 1.8.0

    1.配置编译环境 yum update && yum upgrade yum groupinstall "Development Tools" 或者 yum ins ...

  4. struts_ognl详解

  5. Css3渐变(Gradients)-径向渐变

    CSS3径向渐变-radial-gradient()/repeating-radial-gradient() 径向渐变由它的中心定义. 创建径向渐变,至少定义两种颜色节点,呈现平稳过度的颜色.同时,你 ...

  6. 点击文字可以选中相应的checkbox

    <html><head><title>中国站长天空-网页特效-表单特效-点击文字选中的复选框</title><meta http-equiv=&q ...

  7. oracle服务器端-登陆

    由于的的操作系统是windows server版本,所以想装服务器端的server版本,一般的oracle都有'scott'用户,但是貌似服务器端的没有该用户,我用以下方式登陆: sqlplus / ...

  8. (转载)loadrunner简单使用——HTTP,WebService,Socket压力测试脚本编写

    原文出处:http://ajita.iteye.com/blog/1728243/ 先说明一下,本人是开发,对测试不是特别熟悉,但因工作的需要,也做过一些性能测试方面的东西.比较久之前很简单的用过,最 ...

  9. 【转】 iOS KVO KVC

    原文: http://www.cocoachina.com/industry/20140224/7866.html Key Value Coding Key Value Coding是cocoa的一个 ...

  10. [转]Mysql导入导出工具Mysqldump和Source命令用法详解

    Mysql本身提供了命令行导出工具Mysqldump和Mysql Source导入命令进行SQL数据导入导出工作,通过Mysql命令行导出工具Mysqldump命令能够将Mysql数据导出为文本格式( ...