STL中的Traits编程技法

  最近在看读《STL源码剖析》,看到Traits编程技法这节时,不禁感慨STL源码作者的创新能力。那么什么是Traits编程技法呢?且听我娓娓道来:

  我们知道容器的许多操作都是通过迭代器展开的。其中容器类似于数组,迭代器类似于指针。我们用数组来写个例子:


1 int arr[5] = {1,2,3,4,5};
2 int *p;
3 p = &arr[2];

  假设,我将第1、2遮挡起来,问你p所指向的对象arr[2]是什么类型,你恐怕无法回答。因为它可以是int,char,float甚至你自己定义的类型。假设我们现在是个容器:


1 list<int> lit(5,3);
2 list<int>::iterator it1,it2;
3 it1 = lit.begin();
4 it2 = lit.end();

  其中lit是个容器对象,it1和it2都是容器的迭代器。假设现在有个函数,他接受两个迭代器作为参数,并且返回类型是迭代器所指的类型:


1 template<class iterator>
2 返回类型
3 fun(iterator first,iterator last)
4 {
5 //函数体
6 }

  问题来了,现在我的返回类型假设是iterator所指向的类型。我们无法进行下去了。。。别怕,我们接着往下看:

  如果我们将迭代器定义成一个类:


template<class T>
class My_iterator
{
public:
T* ptr;
typedef T value_type;
My_iterator(T* p = 0):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编程技法,布布扣,bubuko.com

时间: 2024-10-26 20:12:44

STL中的Traits编程技法的相关文章

STL iterator和traits编程技法

今天终于看完了<STL源码分析>,最近忙于两个比赛的各种文档,没时间写东西,趁着看完的劲,把欠下的补上来. <Design patterns>中对于iterator模式描述如下:提供一种方法,使之能够依序寻访某个聚合物所含的各个元素,而又无需暴露该聚合物的内部结构.在STL中,iterator扮演着连接container和algorithms的作用,下面以STL find()函数展现一下iterator在container和algorithm之间的连接作用. template &l

stl源码剖析学习笔记(二)traits编程技法简明例程

解释说明 traits侯捷老师的翻译是萃取.其目的就是在编译期进行模板调用的类型识别,从而做一些事情. 最突出的例子,我觉得不是<STL源码剖析>中"迭代器概念与traits编程技法"这一章的说明,而是stl算法中copy的实现.代码在stl源码的stl_algobase.h中. copy的最终实现,大致分为两类,一类是直接整块内存的memmove操作,另一类是一个个对象赋值.其中涉及has_trivial_assignment_operator的类型推断. 如果has_t

STL Traits编程技法

traits编程技法大量运用于STL实现中.通过它在一定程度上弥补了C++不是强型别语言的遗憾,增强了C++关于型别认证方面的能力. traits编程技法是利用"内嵌型别"的编程技法和编译器的template参数推导功能实现的. iterator_traits 1.对于class type要求其"内嵌型别" 要求与STL兼容的容器,其迭代器必须定义一下五种型别: iterator_category 迭代器类型 value_type 迭代器所指对象类型 differe

STL之traits编程技法

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

[转载]《STL源码剖析》阅读笔记之 迭代器及traits编程技法

本文从三方面总结迭代器   迭代器的思想   迭代器相应型别及traits思想   __type_traits思想 一 迭代器思想 迭代器的主要思想源于迭代器模式,其定义如下:提供一种方法,使之能够依序巡防某个聚合物(容 器)所含的元素,而又无需暴露该聚合物的内部表达式.可见她的主要作用便是能够降低耦合,提高代码的 模块性. STL的的中心思想在于:将数据容器和算法分开,彼此独立设计,最后再以一贴胶着剂将它们撮合 在一起,这贴胶着剂便是迭代器.迭代器的行为类似智能指针(例如标准库的auto_pt

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

在算法中运用迭代器时,很可能用到其相应类型.什么是相应类型?迭代器所指对象的类型便是其中一个.我曾有一个错误的理解,那就是认为相应类型就是迭代器所指对象的类型,其实不然,相应类型是一个大的类别,迭代器所指对象的类型只是里面的其中一个.后面会讨论到相应类型的另外几种. 假设算法需要声明一个变量,以“迭代器所指对象的类型”为类型,该怎么做?或许我们可能会想到RTTI性质中的typeid(),但获得的只是类型名称,并不能拿来声明变量. 其中一个解决方法是:利用模版函数中的参数推导(argument d

traits编程技法

看了<stl源码剖析>中关于traits的部分,由于对模板还不是很熟悉,就看了一下还未完工的C++ Template 进阶指南 ,感觉收获很大,推荐一下. 在使用迭代器时,为了知道它的相应类型,可以使用模板的参数推导,代码如下 template <class T> struct MyIter typedef T value_type; T* ptr; MyIter(T* p=0) : ptr(p) { } T& operator*() const { return *ptr

STL源码剖析—迭代器与traits编程方法

STL的中心思想就是将算法和容器分开,彼此独立设计,最后再以粘合在一起,算法和容器的泛型化,并不是很难,C++的class templates和function templates可以达成目标,但是粘合在一起就是迭代器的事情. 这么一说迭代器就是为了粘合算法和容器的,如果单独设计迭代器,那么这个迭代器就必须知道某个特定容器的内部数据,会暴露太多的信息,这样就规定每一种STL容器都提供有专属迭代器. 迭代器所指对象的型别,称为该迭代器的value_type.所谓value_type,是指迭代器所指

《STL源码剖析》学习之traits编程

侯捷老师在<STL源码剖析>中说到:了解traits编程技术,就像获得“芝麻开门”的口诀一样,从此得以一窥STL源码的奥秘.如此一说,其重要性就不言而喻了.      之前已经介绍过迭代器,知道了不同的数据结构都有自己专属的迭代器,不同的迭代器也有不同的特性,由于算法的接口是统一的,通过迭代器的不同属性,算法自动选择正确的执行流程,在完全任务的同时,也尽可能提高算法的执行效率.那算法如何获知迭代器的属性呢?这一光荣的任务就是traits完成的.在STL实现中,traits编程技术得到大量的运用