迭代器所指之物的型別便是其一。最常用的相應(yīng)型別有5種,有的時候可以利用template參數(shù)推導(dǎo)機制來取得,而并非所有,所以需要更全面的解法。
Traits編程技法
迭代器所指對象的型別,就是迭代器的value type。參數(shù)推導(dǎo)機制雖然可用于value type;卻非全面可用,如果value type必須要求用于函數(shù)的返回值,就不成立。Template參數(shù)推導(dǎo)機制推而導(dǎo)之的只是參數(shù),無法推導(dǎo)函數(shù)的返回值型別。
聲明內(nèi)嵌型別可以解決返回值型別的問題。
func()的返回型別必須加上typename,T是template的一個參數(shù),在被編譯器據(jù)西安華之前,編譯器對T一無所知,編譯器并不知道MyIter<T>::value_type代表的是什么,typename告訴編譯器這是一個型別,才能通過編譯。
新的問題出現(xiàn):并不是所有的迭代器都是class type(只有它能夠定義內(nèi)嵌型別,如果無法定義內(nèi)嵌型別,還是無法解決函數(shù)返回值型別的問題);原生指針就不是,所以引出新的解決方案。
TemplatePartial Specialization(偏特化)
Class template 如果有一個以上的template參數(shù),,可以對其中的某個或者數(shù)個進行特化處理,可以再泛型設(shè)計中提供一個特化版本,將泛型化版本中某些template參數(shù)賦予明確的指定。
模板特化是通過"給模板中的所有模板參數(shù)一個具體的類"的方式來實現(xiàn)的.而模板偏特化則是通過"給模板中的部分模板參數(shù)以具體的類,而留下剩余的模板參數(shù)仍然使用原來的泛化定義"的方式來實現(xiàn)的.
模板的偏特化能力很強大.當(dāng)你實例化一個模板時,編譯器會把目前存在的偏特化模板和全特化模板做比較,并找出其中最合適、最匹配的實現(xiàn).
這樣,靈活性就很大.
模板的偏特化機制不能用在函數(shù)身上,不論成員函數(shù)還是非成員函數(shù).
我們便可以很快找到原生指針的偏特化版本:
template<typename T>
classC<T*>{….}
進入關(guān)鍵部分:
class template專門用來萃取迭代器的特性,而value type正是迭代器的特性之一。
這里所謂的traits就是如果I有自己定義的value type,那么通過這個traits作用,萃取出來的value_type就是I::value_type,換句話說,如果I有自己定義的value type,先前的func函數(shù)可以寫成這樣:
template<class I>
typenameiterator_traits<I>::value_type func(I ite){return *ite;}
中間多了一層間接性,traits可以擁有自己的偏特化版本。令iterator_traits擁有一個偏特化版本:
原生指針int*雖然不是一種class type,也可以通過traits特性取其value type。這就解決了之前的問題。
但是,針對指向常數(shù)對象的指針,下面這個式子得到的結(jié)果:
iterator_traits<constint *>::value_type;
獲得的是const int而非int,不是期望的(本來希望利用這種機制,聲明一個暫時的變量,使其型別與迭代器的的value type相同,而聲明一個無法賦值的暫時變量,沒多大用處),所以應(yīng)該設(shè)計一個特化版本:
特性萃取機traits能夠有效運作,每一個迭代器都必須遵循約定,自行以內(nèi)嵌型別定義的方式定義出相應(yīng)的型別,這個是stl的一個約定。
iterators_traits必須對傳入型別為pointer以及pointer—to-const設(shè)計特化版本。
differencetype表示兩個迭代器之間的距離。如果一個泛型算法提供技術(shù)功能,例如count(),其傳回值就必須使用迭代器的difference type:
類似于value type,difference type也設(shè)計了兩個版本的偏特化版本,pointer和pointer-to-const版本。
referencetype pointer type
聯(lián)系客服