第三章 迭代器(iterator)概念与traits编程技法
设计模式中,iterator模式的定义:
提供一种方法,使之能偶依序巡访聚合物(容器)的所含各个元素,而又无需暴露该聚合物的内部表达式。
每一种STL容器都提供有专属迭代器。
1、如何获取 迭代器相应型别(五种) 如:迭代器所指对象的型别(可用 模板函数的参数推导机制获取),而更加全面的解法 Traits编程技法
2、迭代器是一种smart pointer。
Traits编程技法——STL源代码门匙
1、模板的偏特化:
偏特化定义:针对任何template参数更进一步的条件限制所设计出来的一个特化版本。
如:
template<typenameT>
Calss c{ }; //泛化版本 T接受任何类型的参数
偏特化,进一步限制参数:
template<typenameT>
Calss c<T*> { };//偏特化后,只能接受指针类型的参数
或者
有多个模板参数时,对其中的一个或几个(不能全部)予明确指定。
taites就像一台特性萃取机,榨取各个迭代器的特性(相应型别):
value_type:表示迭代器所封装的元素类型
difference_type:用来表示两个迭代器之间的距离。
reference :指的是迭代器封装对象的类型的引用。这个类型的出现主要是为了解决对指针进行解引用的时候,返回什么样的对象的问题。
pointer:如果我们想返回迭代器封装的对象的地址,就需要用到这里的pointer_type,主要用在迭代器中对->运算符重载的问题。
iterator_category:这个类型的作用是按照迭代器的移动特性和能够在该迭代器上实施的操作对迭代器进行分类,之所以这样做,完全是为了效率的考量。
迭代器类型萃取:
//iterator_traits<typenameT> 一个专门萃取迭代器相应型别的模板类,模板参数为迭代器类型 萃取所得的是一种类型。如:
iterator_traits<vector<int>::iterator>::difference_typed; d=iv.end()-iv.begin()
类型相应型别萃取:
SGI特有的类型萃取_type_traits:\用于萃取类型的特性:是否为POD类型
SGI中定义了用于萃取类型相应型别的模板类
_type_traits<typenameT> ,模板参数为类型,主要用于萃取该类型是否为POD类型
VC标准库中利用模板类
std::is_pod<typename T>::value 返回bool值,以判断是否为POD
如:
boolpod=std::is_pod<vector<int,JJ::allocator<int>>>::value;
注:C++的内置标量类型都定义自己的_type_traits特化版本,其中每一个typedef的值都为_true_type。 对于自定义的类型,一般来说编译器是不能自己识别其_type_traits的,因此需要在自定义类型中自定义_type_traits的typedef。一般原则是,如果一个class中有指针成员,并且有动态内存配置,那么该类型就应该实现出自己的non_trival_xxx.
在STL中,共有以下5种迭代器类型:
l 单向移动只读迭代器 Input Iterator
l 单向移动只写迭代器 Output Iterator
l 单向移动读写迭代器 Forward Iterator
l 双向移动读写迭代器 Bidirectional Iterator
以上4种属于单步向前挪型的迭代器,还有一种双向移动读写迭代器属于一步跨到位型:
l 随机访问迭代器 Random Access Iterator
2、taites就像一台特性萃取机,榨取各个迭代器的特性(相应型别)
具体用模板偏特化 对不同的迭代器采取不同策略:
( STL容器的迭代器,都必须提供自己的相应型别,即 value type
对于原生指针则有偏特化处理)
__type_traits:用于萃取类型型别:是否为non_tivial_xxx
3、什么时候自定义的calss应该为POD类型:
如果Claa内含指针成员,并且对他们进行动态内存配置,那么这个类即需要实现出自己的non-trivial-xxx.。即为non-POD.
4、对于内置标量类型<type_traits>中都typedef 了__true_type , 即为POD类型。
萃取出特性,算法操作时采取不同的实现策略,为每种情况都实现最大的效率策略。