《STL源码剖析》阅读摘要
第一章
介绍一些STL中特定的组态和设定
第二章 空间配置器(allocator)
第一级、第二级空间配置器
STL设计的空间配置器 std::alloc
三个基本处理工具:uninitialized_copy、uninitialized_fill、uninitialized_fill_n
第三章 迭代器与traits编程技法
迭代器粘合了 算法与容器
这一部分大量使用了偏特化,例如,当调用一个泛型算法时,根据输入类型,使用模板函数+模板类(参数类型推断机制,返回一个临时对象)推断输入的迭代器的类型(这非常重要)。然后以类型(临时对象)为参数去调用被封装的函数,这个时候根据参数的类型的不同,会匹配不同的特化版本,保证最优效率。
3.6节介绍了如何推断输入类型的完整代码,用到了“萃取器”traits(模板类),对迭代器对象、指针、指向const的指针有多个偏特化版本。
举个例子具体怎么做:
假设我们用struct定义了好几种迭代器类型,例如
struct A {}; struct B :public A {}; struct C :public A {}; ` //等等,都是空的,没成员。
定义了
traits
,它将不同迭代器的类型重新统一命名:template <class Iterator> struct iterator_traits { typedef typename Iterator::iterator_category iterator_category; };
然后定义某种迭代器, 例如:
struct __XXX__iterator { typedef C iterator_category; //定义这个迭代器属于C类 };
这样,在某个封装函数种用到迭代器时,先使用traits类去推断(取得)迭代器类型,以类型为参数调用被封装的函数。
template<class Iterator> void fun(Iterator& iter) { typedef typename iterator_traits<Iterator>::iterator_category category; fun_(iter, category()); //A(), B()或者C() } template<class A_iter> void fun_(A_iter& i, A) { //函数多了一个tag,A类的某个对象 std::cout << "I am A" << std::endl; } template<class B_iter> void fun_(B_iter& i, B) { std::cout << "I am B" << std::endl; } template<class C_iter> void fun_(C_iter& i, C) { std::cout << "I am C" << std::endl; } //测试函数 int main() { __XXX__iterator X_iter; fun(X_iter); //输出 "I am C" } //决定迭代器类型的函数 template <class Iterator> inline typename iterator_traits<Iterator>::iterator_category iterator_category(const Iterator&){ typedef typename iterator_traits<Iterator>::iterator_category category; return category();