STL是C++標準庫的重要組成部分之一,它不僅是一個可複用的組件庫,更是一個包含算法與數據結構的軟件框架,同時也是C++泛型編程的很好例子。STL中運用了許多C++的高級技術。本文介紹模板特化技術的運用。主要參考了《C++ Primer》和《STL源碼剖析》。
STL中大量運用了模塊,可以說模板是創建類或函數的公式。但是,我們並不總能寫出對所有可能被實例化的類型都最合適的模板。舉個函數模板特化的例子。
- template <typename T>
- int Compare(const T &x, const T &y)
- {
- if(x < y)
- return -1;
- else if(x > y)
- return 1;
- else
- return 0;
- }
模板特化(template specialization)的定義爲指定一個或多個模板形參的實際類型或實際值。例如可以爲Compare模板函數定義一個特化版本。
- template <> //template關鍵字後面接空括號
- int Compare(const char * const &x, const char * const &y) //形參爲指向常量的常指針的引用
- {
- return strcmp(x, y);
- }
迭代器是STL的關鍵所在,它將原本分開的數據容器和算法很好的膠合在一起。比如下面這個STL中的函數(摘自源碼),命名上做了修改,同時略去了一些代碼,但是足以說明問題。這個函數通過迭代器交換容器的數據,迭代器是數據容器和算法的橋樑,算法通過數據容器的迭代器訪問容器中的數據,而不需關心容器的具體構造。
- //真正的交換函數,內部調用
- template <class Iter1, class Iter2, class T>
- inline void _iter_swap(Iter1 a, Iter2 b, T) {
- T tmp = *a;
- *a = *b;
- *b = tmp;
- }
- //交換兩個迭代器所指的元素,外部接口
- template <class Iter1, class Iter2>
- inline void iter_swap(Iter1 a, Iter2 b) {
- _iter_swap(a, b, VALUE_TYPE(Iter1)); //VALUE_TYPE返回迭代器的值類型
- }
問一個問題,iter_swap這個函數的形參是迭代器,我們需要在函數內部定義一個臨時變量,變量的數據類型爲迭代器所指的數據類型。那麼我們如何知道迭代器所指的數據類型呢?有人說,可以利用模板實參推斷機制,解決這個問題。代碼如下所示:
- //真正的交換函數
- template <class Iter1, class Iter2, class T>
- inline void _iter_swap(Iter1 a, Iter2 b, T) {
- T tmp = *a;
- *a = *b;
- *b = tmp;
- }
- //交換兩個迭代器所指的元素
- template <class Iter1, class Iter2>
- inline void iter_swap(Iter1 a, Iter2 b) {
- _iter_swap(a, b, *a); //模板實參推斷
- }
- class MyAlloc{
- };
- template<class T>
- struct List_iterator{
- typedef T value_type; //list 迭代器的內嵌型別
- ...
- };
- template <class T, class Alloc = MyAlloc>
- class list{
- public:
- typedef List_iterator<T> iterator; //list迭代器
- ...
- };
- template<class I>
- struct Iterator_traits{ //萃取劑定義
- typedef typename I::value_type value_type;
- };
- Iterator_traits<list<int>::iterator>::value_type x = 1;
- class MyAlloc{
- };
- template <class T, class Alloc = MyAlloc>
- class vector :
- {
- public:
- typedef T value_type; //內嵌型別
- typedef value_type* pointer;
- typedef const value_type* const_pointer;
- typedef value_type* iterator; //vector 迭代器,是原生指針
- typedef const value_type* const_iterator;
- typedef value_type& reference;
- typedef const value_type& const_reference;
- ...
- };
- template<class I>
- struct Iterator_traits{
- typedef typename I::value_type value_type;
- };
- //特化 原生指針
- template<class T>
- struct Iterator_traits<T*>{
- typedef T value_type;
- };
- //特化 原生常指針
- template<class T>
- struct Iterator_traits<const T*>{
- typedef T value_type;
- };
- #include <iostream>
- #include <vector>
- #include <list>
- using namespace std;
- //萃取劑
- template<class I>
- struct Iterator_traits{
- typedef typename I::value_type value_type;
- };
- //特化 原生指針
- template<class T>
- struct Iterator_traits<T*>{
- typedef T value_type;
- };
- //特化 原生常指針
- template<class T>
- struct Iterator_traits<const T*>{
- typedef T value_type;
- };
- #define VALUE_TYPE(I) Iterator_traits<I>::value_type()
- //交換兩個迭代器所指的元素
- template <class Iter1, class Iter2>
- inline void iter_swap(Iter1 a, Iter2 b) {
- _iter_swap(a, b, VALUE_TYPE(Iter1)); //VALUE_TYPE返回迭代器的值類型
- }
- //真正的交換函數
- template <class Iter1, class Iter2, class T>
- inline void _iter_swap(Iter1 a, Iter2 b, T) {
- T tmp = *a;
- *a = *b;
- *b = tmp;
- }
- //測試函數
- int main()
- {
- int a = 1, b = 2;
- iter_swap(&a,&b);
- cout<<a<<' '<<b<<endl; //2 1
- list<int> l;
- l.push_back(3);
- l.push_back(4);
- iter_swap(l.begin(),++l.begin());
- cout<<*(l.begin())<<' '<<*(++l.begin())<<endl; //4 3
- Iterator_traits<int *>::value_type w = 5; //特化
- Iterator_traits<const int*>::value_type x = 6; //特化
- Iterator_traits<vector<int>::iterator>::value_type y = 7; //vector 容器
- Iterator_traits<list<int>::iterator>::value_type z = 8; //list 容器
- cout<<w<<' '<<x<<' '<<y<<' '<<z<<endl; //5 6 7 8
- return 0;
- }