以構建乙個n緯網格為例,講述模板遞迴。
首先是乙個簡單的一緯網格的實現,這個網格實現了規定長度的網格的例項化,並且能夠在不同大小的網格類中自由的轉型(通過模版巢狀的cast_ctr)
(使用到的技術,非型別引數模版,模版巢狀,類模版特例化,模版友元函式)
#include #includeusing
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 #includetemplate
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...