日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Typelists

發布時間:2024/4/14 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Typelists 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Typelists是一個用來操作一大群型別的C++工具。就像list對數值提供的各種基本操作一樣,typelists對型別也提供相同的操作。

有些設計模式具體制定并操作一群型別,其中也許有繼承關系,顯著的例子是abstract factory和visitor。如果以傳統編程技術來操作一大群型別,將式全然重復的工作,如此重復將會導致隱微的代碼膨脹。多數人不會想到其實它可以比現在更好。Typelists帶給你一種能力,可以講將經常性的宏工作自動化。Typelists將來自外星球的巨大威力帶到C++中,讓它得以支持新而有趣的一些手法。

?

3.1 Typelists的必要性

有時候你必須針對某些型別重復撰寫相同代碼,而templates無法幫上忙。假如有一個abstract factory,像這樣:

class WidgetFactory { public:virtual Window* CreateWindow() = 0;virtual Button* CreateButton() = 0;virtual ScrollBar* CreateScrollBar() = 0; };

 如果想將abstract factory概念泛化,不止生成window、bottom、scrollbar,而是任意型別。怎么辦?

 如果你不試圖泛化基本概念,就不太會有機會泛化這些概念的具體實體,雖然抽象基類很簡單,但是你會陷入無窮無盡的派生類生成器中。

我們希望能夠這樣去使用一個abstract factory:

template<class T> T* MakedWidget(WidgetFactory& factory) {T* pW=factory.create<T>();pW=SetColor(RED);return pW; }

 實際這是不可能的,如果Create不是虛函數,那么你就陷入了長長的Switch...case...之中,如果它是虛函數,那么虛函數不能是模板。

Typelists將使Abstract Factories泛化成真,并帶來更多其它利益。

?

定義Typelists

template< class T,class U> struct Typelist {typedef T head;typedef T Tail; };

  Typelists 內部沒有任何數值:他的實體是空的。它們存在的理由只是為了攜帶型別信息。因此,對Typelists的任何處理都發生在編譯期。此后我們提到一個typelist,指的是一個型別而非一個對象。雖然typlist只有兩個參數,但我們可以把任意一個替換為另一個typelist,來達到無限延伸的目的。

另外我們需要一個0型別以及一個型別的Typelists,對于0型別,前面提到的NullType就可以,對于一個型別,我們可以這樣定義:

typedef Typelist<int ,NullType> oneTypeOnly;

  

將Typelist生成線性化

像這樣一個Typelist

typedef Typlist<int, Typelist<int, Typelist<int, Typelist<int, int> > > > Int4Type;

它太Lisp了,我們定義一系列的宏來完成它,這樣我們可以忘記尖括號間的空格。

#define TYPELIST_1(T1) Typelist<T1, NullType> #define TYPELIST_2(T1, T2) Typelist<T1, TYPELIST_1(T2) > #define TYPELIST_3(T1, T2, T3) Typelist<T1, TYPELIST_2(T2, T3) > #define TYPELIST_4(T1, T2, T3, T4) Typelist<T1, TYPELIST_3(T2, T3, T4) >//etc #define TYPELIST_50(/* */) //

這樣前面的 Int4Type 就可以這樣定義  

typedef Int4Type TYPELIST_4(int, int, int, int) Int4Type;

這只是包裝手法的一個開端。我們訪問Int4Type的最后一個元素還比較麻煩,需要

Int4Type::Tail::Tail::Tail;

  

計算長度

我們用下面代碼來計算Typelist的長度

template<class TList>struct Length; template<> struct Length<NullType>{enum{value=0}; };template<class T,class U> struct Length<Typelist<T,U>> {enum{value=1+Length<U>::value}; };

由Length<T>::value得到的是一個編譯期常數,我們可以用它來定義數組大小,

std::type_info* intsRtti[Length<SignedIntegrals>::value];

這個模板代碼依靠遞歸來完成,第一個版本是全特化,第二個版本是偏特化。

?

間奏曲

這里有一個問題,在Length的實現中,我們能否用迭代來取代遞歸?答案是否定的。因為我們在編譯期編程中,可以使用到的僅僅是:template、編譯期整數計算、typedef。

1、template:更明確的說是模板特化,提供編譯期的if敘述。

2、整數計算:提供數值計算能力,用以從性別轉為數值,但數值是不可改變的。

3、typedef:可視為用來引進“具名的型別常數”,他們也是定義之后就凍結,你不能將typedef定義的符號重新定義為另一個型別。

?

這些特性決定了我們無法使用迭代,所謂迭代是持有一個迭代器,并改變它,知道某些條件吻合,由于編譯期我們沒有“可資變化的任何東西”,所以無法實現“迭代”。所以編譯期運算只能象那些純粹函數型語言,使用大量的遞歸。

?

索引式訪問

索引式訪問是Typelist訪問線性化,像在static世界中,索引必須是編譯期常數,一個帶有索引的template聲明如下:

template<class TList,unsigned int index> struct TypeAt;

 實現如下:

template<class Head,Class Tail> struct TypeAt<Typelist<Head,Tail>,0> {typedef Head Result; }template<class Head,class Tail,unsigned int> struct TypeAt<Typelist<Head,Tail>,i> {typedef typename TypeAt<Tail,i-1>::Reslut Result; }

  如果你試著越界訪問,會編譯出錯。對Typelist進行索引訪問,花費的時間和typelist大小有關,但這個時間全部花在編譯期。

?

 

 查找Typelist

我們用index0f來查找Typelist中的一個型別,返回其位置,找不到就返回-1。

template <class TList, class T> struct IndexOf; template <class T> struct IndexOf<NullType, T>{enum{value = -1}; };template <class Tail, class T> struct IndexOf<Typelist<T, Tail>, T>{enum{value = 0;} };template <class Head, class Tail, class T> struct IndexOf<Typelist<Head, Tail>, T>{ private:enum{temp = IndexOf<Tail, T>::vale}; public:enum{value = temp == -1 ? -1 : 1+temp}; };

最后一個特化版本是用了問號表達式來實現分支判斷

  

追加元素至Typelist

修改typelist是不可能的,我們以by value方式傳回一個新typelist。

template <class TList, class T> struct Append; template <> struct Append<NullType, NullType>{typedef NullType Result; }; template <class T> struct Append<NullType, T>{typedef TYPELIST_1(T) Result; }; template <class Head, class Tail> struct Append<NullType, Typelist<Head, Tail> >{typedef Typelist<Head, Tail> Result; }; template <class Head, class Tail, class T> struct Append<Typelist<Head, Tail>, T>{typedef Typelist<Head, typename Append<Tail,T>::Result> Result; };

  

這個實現比較復雜,特別是最后一個偏特化版本,他遞歸具現Append,每次遞歸都將tail和待追加型別傳遞進去

?

移除typelist中的某個元素

template <class TList, class T> struct Erase; template <class T> struct Erase<NullType, T>{typedef NullType Result; }; template<class T, calss Tail> struct Erase<Typelist<T, Tail> T>{typedef Tail Result; }; template <class Head, class Tail, class T> struct Erase<Typelist<Head, Tail>, T>{typedef Typelist<Head,typename Erase<Tail, T>::Result>Result; };

  

  

?

轉載于:https://www.cnblogs.com/chillblood/p/4087542.html

總結

以上是生活随笔為你收集整理的Typelists的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。