天天看點

STL源碼剖析 3、疊代器概念與traits程式設計技法疊代器Traits程式設計技法——STL源代碼門鑰iterator源代碼完整重列SGI STL的私房菜 __type_traits

疊代器

設計思維

設計模式:提供一種方法,使之能夠依序巡訪某個聚合物(容器)所含的各個元素,而又無需暴露該聚合物的内部表述方式。

疊代器作用:STL的中心思想是将容器和算法分開,彼此獨立設計,最後再用膠着劑将它們撮合在一起,疊代器扮演膠着劑

疊代器是一種是智能指針

疊代器行為類似于指針,最重要的作用是内容提領(deference)和成員通路(member access),是以,疊代器最重要的程式設計工作就是對operator*和operator->進行重載工作,可以參考auto_ptr(過時了)。

為什麼每種STL容器有專屬疊代器?

疊代器的實作需要容器細節:

 要完成一個容器如List的疊代器,需要暴露很多List實作細節,如1.為了制作begin和end兩個疊代器,疊代器内部需要連結清單節點的指針,暴露了連結清單節點。2.為了打成++,需要暴露next屬性。

暴露細節無法避免,幹脆讓容器設計者開發專屬疊代器

疊代器相應型别

概念:疊代器所指之物的型别等

問題:C++隻支援sizeof(),不支援typeof(),不能識别疊代器所指之物的型别

解決:

方法1.利用function template的參數推導機制

局限性:

 ●五種類型不能全推出

 ●不能用于函數的傳回值,template參數推導的隻是參數

STL源碼剖析 3、疊代器概念與traits程式設計技法疊代器Traits程式設計技法——STL源代碼門鑰iterator源代碼完整重列SGI STL的私房菜 __type_traits

Traits程式設計技法——STL源代碼門鑰

traits大量運用于STL中,利用“内嵌型别”的程式設計技巧與編譯器的template參數推導功能,增強了C++未能提供的關于型别認證方面的能力

方法2.聲明内嵌型别

可以傳回疊代器所指類型

局限性:并不是所有的疊代器都是類,如原生指針。不是類就無法定義内嵌型别。

STL源碼剖析 3、疊代器概念與traits程式設計技法疊代器Traits程式設計技法——STL源代碼門鑰iterator源代碼完整重列SGI STL的私房菜 __type_traits

方法3.traits(traits意為特性)

偏特化:針對template參數更進一步的條件限制所設計出來的一個特化版本,不一定要指定template部分參數。

//這也是一種偏特化,這個特化版本适用于“T為原生指針”的情況
//“T為原生指針”是對“T為任何型别”的限制,隻要限制了就是特化
template<typename T>
class C<T*>{}
           

traits萃取疊代器特性

//1.如果I(疊代器)定義了自己的value type,那麼萃取出的value_type就是I::value_type
template<class I>
struct iterator_traits{		
	typedef typename I::value_type value_type;
};
//2.原生指針特化版,如int*不是類,沒有定義value type,也可以萃取出所指的類型
template<class T>
struct iterator_traits<T*>{
	typedef T value_type;
};
//3.原生const指針特化版,我們不需要const特性
template<class T>
struct iterator_traits<const T*>{
	typedef T value_type;
};
           

應用

可以用

typename iterator_traits<I>::value_type

來得到任何疊代器I的value_type

疊代器的五種型别

為了所開發的容器與STL相容,一定定義五種相應型别

STL源碼剖析 3、疊代器概念與traits程式設計技法疊代器Traits程式設計技法——STL源代碼門鑰iterator源代碼完整重列SGI STL的私房菜 __type_traits

1.value type

概念:疊代器所指對象的型别

具體見上面

2.difference type

概念:兩個疊代器之間的距離(元素個數)

traits:

//1.普通版本,針對類内定義了difference_type
template<class I>
struct iterator_traits{
	typedef typename I::difference_type difference_type;
};
//2.原生非const指針版本
template<class T>
struct iterator_traits<T*>{
	typedef ptrdiff_t difference_type;	//ptrdiff_t為兩個指針的差,定義于<cstddef>
};
//3.原生const指針 略
template<class T>
struct iterator_traits<const T*>{
	typedef ptrdiff_t difference_type;	//ptrdiff_t為兩個指針的差,定義于<cstddef>
};
           

應用:STL的計數函數count(),傳回值必須使用疊代器的difference type

STL源碼剖析 3、疊代器概念與traits程式設計技法疊代器Traits程式設計技法——STL源代碼門鑰iterator源代碼完整重列SGI STL的私房菜 __type_traits

3.reference type

4.pointer type

區分:reference type和pointer type

Item& operator*() const{return *ptr;}		//Item&是reference type
Item* operator->() const{return ptr;}		//Item*是pointer type
           

traits:

//1.普通版本,針對class type
template<class I>
struct iterator_traits{
	typedef typename I::pointer pointer;
	typedef typename I::reference reference;
};
//2.針對非const原生指針
template<class I>
struct iterator_traits<T*>{
	typedef T* pointer;
	typedef T& reference;
};
//2.針對非const原生指針
template<class I>
struct iterator_traits<const T*>{
	typedef const T* pointer;
	typedef const T& reference;
};
           

5.iterator_category

●五類疊代器:

STL源碼剖析 3、疊代器概念與traits程式設計技法疊代器Traits程式設計技法——STL源代碼門鑰iterator源代碼完整重列SGI STL的私房菜 __type_traits

●關系:

STL源碼剖析 3、疊代器概念與traits程式設計技法疊代器Traits程式設計技法——STL源代碼門鑰iterator源代碼完整重列SGI STL的私房菜 __type_traits

●考慮效率:如果對Random類一個個移動效率太低,是以要根據類别調用不同的函數

 方法1:缺乏效率

STL源碼剖析 3、疊代器概念與traits程式設計技法疊代器Traits程式設計技法——STL源代碼門鑰iterator源代碼完整重列SGI STL的私房菜 __type_traits

 方法2:函數重載

STL源碼剖析 3、疊代器概念與traits程式設計技法疊代器Traits程式設計技法——STL源代碼門鑰iterator源代碼完整重列SGI STL的私房菜 __type_traits
STL源碼剖析 3、疊代器概念與traits程式設計技法疊代器Traits程式設計技法——STL源代碼門鑰iterator源代碼完整重列SGI STL的私房菜 __type_traits

●traits實作

//這個traits比前面四種難了解一點
//如value type萃取的是iter所指的類型,iterator_categoty萃取的就是屬于五類疊代器中的哪一類
//萃取的是疊代器的最強類型

//1.普通版本,類内自行指定
template<class I>
struct iterator_traits{
	typedef typename I::iterator_category iterator_category;
};
//2.原生指針版本,原生指針是一種Random 
template<class I>
struct iterator_traits<T*>{
	typedef random_access_iterator_tag iterator_category;
};
//3.原生const指針版本,原生cosnt指針是一種Random 
template<class I>
struct iterator_traits<const T*>{
	typedef random_access_iterator_tag iterator_category;
};
           

std::iterator的保證

STL源碼剖析 3、疊代器概念與traits程式設計技法疊代器Traits程式設計技法——STL源代碼門鑰iterator源代碼完整重列SGI STL的私房菜 __type_traits
STL源碼剖析 3、疊代器概念與traits程式設計技法疊代器Traits程式設計技法——STL源代碼門鑰iterator源代碼完整重列SGI STL的私房菜 __type_traits

iterator源代碼完整重列

見p101

注意:

STL源碼剖析 3、疊代器概念與traits程式設計技法疊代器Traits程式設計技法——STL源代碼門鑰iterator源代碼完整重列SGI STL的私房菜 __type_traits

SGI STL的私房菜 __type_traits

萃取什麼:型别的特性,即這個型别是否有預設構造,預設析構,預設拷貝構造/操作符

差別:iterator_traits負責萃取疊代器的特性,__type_traits則負責萃取型别的特性。

SGI STL一般化:

STL源碼剖析 3、疊代器概念與traits程式設計技法疊代器Traits程式設計技法——STL源代碼門鑰iterator源代碼完整重列SGI STL的私房菜 __type_traits
STL源碼剖析 3、疊代器概念與traits程式設計技法疊代器Traits程式設計技法——STL源代碼門鑰iterator源代碼完整重列SGI STL的私房菜 __type_traits

偏特化:

STL源碼剖析 3、疊代器概念與traits程式設計技法疊代器Traits程式設計技法——STL源代碼門鑰iterator源代碼完整重列SGI STL的私房菜 __type_traits

應用:和疊代器型别差不多,擷取五個屬性中的一個,然後true和false臨時變量調用不同的重載函數

繼續閱讀