泛型程式設計深入探索之二,模板遞迴與可變引數模版

2022-05-09 09:03:09 字數 4126 閱讀 3288

以構建乙個n緯網格為例,講述模板遞迴。

首先是乙個簡單的一緯網格的實現,這個網格實現了規定長度的網格的例項化,並且能夠在不同大小的網格類中自由的轉型(通過模版巢狀的cast_ctr)

(使用到的技術,非型別引數模版,模版巢狀,類模版特例化,模版友元函式)

#include #include 

using

namespace

std;

template

int length>

class

grid;

template

int length>ostream& operator

<< (ostream& os, const grid&gd)

os<1]<<"]"

os;}

template

int length>

class

grid;

grid(

const grid& gd):mcells(new

t[length]),size(gd.size)

}//足夠,任何修改了t或者length的都會被這個巢狀模板handle

templateint newlength>

//required e->t naturally

grid(const grid& gd):mcells(new t[length]),size(0

) size=newsize;

}grid

& operator=(const grid&gd)

}template

int newlength>

//required e->t naturally

grid& operator=(const grid&gd)

size=newsize;

}inline

int getsize()const

virtual ~grid();

t& operator(int

index)

return *(mcells+index);

}const t& operator (int index)const

void resize(int newsize,const t& def=t())

else

size=newsize;}}

friend ostream& operator

<< (ostream& os, const grid&gd);

private

: t*mcells;

intsize;

};

測試**如下:

#define     _test_grid_      1

#if _test_grid_#include

"grid.h

"#include

#include

#include

using

namespace

std;

intmain()

//不同大小,不同型別的網格互相拷貝

gridb(a);

grid

c(a);

cout

//利用一緯網格,由呼叫方實現模版遞迴(實際是例項遞迴)

gridonegrid;

grid

int, 40>, 40>twogrid;

unsigned

long lct=time(null);

for(int k=0;k<40;k++)

}cout

<}#endif

例項遞迴的好處是語義上簡單,容易理解,缺點卻很多:

1)  使用hadrcode的初始化列表才能對每乙個網格進行初始化。

2)    所有子網格的大小型別必須保持一致。

另外一種遞迴是由類的設計方所實現的,借助巢狀和遞迴設計技術,設計方可以設計出簡潔明瞭的任意緯度的網格類(而不是由使用者來實現),且不需要對每一緯度單獨進行特例化。

#include #include 

template

int length, int n>

class

multigrid;

virtual ~multigrid()

multigrid(

const multigrid& gd):size(0),mcells(new multigrid1>[length])

//基礎,同一緯度下的拷貝

template int newlength>multigrid(

const multigrid& gd):size(0),mcells(new multigrid1>[length])

size=newsize;

}int getsize()const

multigrid

1>& operator(int

index)

return

mcells[index];

}const multigrid1>& operator(int index) const

void resize(int newsize,const multigrid1>& def=multigrid1>())

size=newsize;}}

multigrid

& operator=(const multigrid&gd)

return (*this

); }

template

int newlength>multigrid

& operator=(const multigrid&gd)

size=newsize;

return (*this

); }

private

: multigrid

1>*mcells;

intsize;

};//

利用偏特化技術構造乙個遞迴基

template int length>

class multigrid 1>;

virtual ~multigrid();

multigrid(

const multigrid1>& gd):size(0),mcells(new

t[length])

size=gd.size;

}int getsize()const

template

int newlength>multigrid(

const multigrid1>&gd)

size=newsize;

}t& operator(int

index)

return

mcells[index];

}const t& operator (int index) const

void resize(int newsize,const t& def=t())

size=newsize;}}

multigrid

1>& operator=(const multigrid1>&gd)

return (*this

); }

template

int newlength>multigrid

1>& operator=(const multigrid1>&gd)

size=newsize;

return (*this

); }

private

: t*mcells;

intsize;

};

通過模版遞迴和偏特化遞迴基,我們可以實現任意緯的網格。

特別值得注意的是,無論是在靜態時刻遞迴產生多維網路,還是動態時刻遞迴產生多維網路,效率是一樣的,因為他們都是一種迭代產生所有例項物件的過程,但由於這些例項物件全部是使用者所需要的,並沒有產生大量重複,因此,這種效率是可以接受的。

總而言之,與inline不同,模版遞迴並不是一種犧牲空間換時間的策略!!!他造成的是確確實實的**膨脹。

事實上,按照上述方法,經筆者測試,製作乙個6維矩陣長度為40的六維矩陣的時間為26s,也就說,製作乙個10維則需要440小時...

模板與泛型程式設計

模板是泛型變成的基礎。泛型程式設計 編譯與型別無關的 是一種復用的方式,模板分為模板函式和模板類。模板函式是乙個通用的函式模板,而不是為每一種型別定義乙個新函式,乙個函式模板就像乙個公式,針對不同型別函式生成不同的函式版本。關鍵字 template 以 template 開始,後面跟乙個模板引數列表...

模板與泛型程式設計

泛型程式設計 編寫與型別無關的通用 是 復用的一種手段。模板是泛型程式設計的基礎。函式模板代表了乙個函式家族,該函式模板與型別無關,在使用時被引數化,根據實參型別產生函式的特定型別版本。模板的格式 template 返回值型別 函式名 引數列表 模板分為類模板和函式模板 模板它本身並不是函式,是編譯...

模板與泛型程式設計

一 函式模板 模板定義以關鍵字template開始,後跟乙個模板引數列表,在模板定義中,模板引數列表不能為空。模板型別引數 型別引數前必須使用class或typename關鍵字。非型別模板引數 表示乙個值而不是乙個型別 陣列引用形參 arr兩端的括號必不可少 void print int arr 1...