Re: [問題] 樣版設計 - 只接受特定幾種類別該怎設計?
看板C_and_CPP (C/C++)作者littleshan (我要加入劍道社!)時間16年前 (2009/05/20 11:25)推噓1(1推 0噓 9→)留言10則, 4人參與討論串2/3 (看更多)
話說,大家怎麼都把討論集中在「char 合不合理」
其實在我看來
template function 對「某些 type」無法作用
還算是滿常見的事
當然就這個 case 來說,是見人見智啦...
※ 引述《windincloud (雲淡風輕)》之銘言:
: 今天我遇到一個樣版設計的問題~
: 問看看大家有沒有啥好想法?
: 問題是這樣的~
: 我今天需要設計一個類別來計算數學問題(矩陣運算)
: 當我寫
: template< class T >
: void add(T** a,T** b,int X, int Y);
^ 多打了
: {
: //matrix adding;
: }
: 但問題來了~
: T 可以是int float double
: 但是char就應該不要吧~
: 那這樣要怎解決
template <class T>
void add(T** a, T** b, int X, int Y)
{
// matrix adding
}
void add(char** a, char** b, int X, int Y);
// No definition to produce link error
這方法就是 legnaleurc 提出的做法
當既存的 function 與引數的型別吻合時
C++ 會優先採用 function 而不會使用 function template
但我們只給宣告不給定義
所以會產生 link error
這作法有個缺點,就是 error message 會讓 user 搞不清楚狀況
yoco 有提出一個產生 compile time error 的方法
template <>
void add(char** a, char** b, int X, int Y)
{
int matrix_element_should_not_be_char[0];
}
當使用者試圖以 char 作為 matrix element 的型別時
會產生如下的錯誤訊息:
xxx.cc:13: error: ISO C++ forbids zero-size array ‘matrix_element_type_
should_not_be_char’
注意這邊必須使用 function template specialization
若你像上面那樣直接定義一個一般的 function
那不管這個 char 版本的 add() 有沒有被使用者呼叫
都必須通過 compiler 的語法檢查,因此 compile 時會直接產生錯誤
但使用 function template 的情況下
只有在使用者呼叫 char 版本的 add() 時,compiler 才會試圖具現化這段程式
也只會在這時候產生 compile error
另外,gcc 的擴充語法支援大小為零的陣列,所以上述的人為錯誤並不會被測出
因此 compile 時要加上 -pedantic 這個參數才能正確處理這個技巧
: 且要是我想讓 vector< vector< T > >,list< list< T > >......等stl容器放入
: 那我該如何寫?
: 總不會是一種寫一個吧~
: 那這樣就會失去template的意義的說~
傳 iterator 即可
template <typename T, typename U>
void add(T src, T src_end, U dst)
{
typedef typename iterator_traits<T>::value_type src_container;
typedef typename iterator_traits<U>::value_type dst_container;
while(src != src_end)
{
typename src_container::const_iterator si = src->begin();
typename dst_container::iterator di = dst->begin();
while(si != src->end()){
*di += *si;
++si;
++di;
}
++src;
++dst;
}
}
int main()
{
vector<vector<int> > a;
list<list<int> > b;
...
add(a.begin(), a.end(), b.begin());
}
但很不幸的,這樣一來 add 就不能用在 int** 或 double** 之類的型別
這邊有一個重點:操作 vector<vector<int> > 和操作 int** 的方法是不一樣的
vector<vector<int> > 是個容器,每個元素又是另一個 (有大小資訊的) 容器
但 int** 是個指標,指向另一個 (沒有大小資訊的) 指標
所以你很難寫一個 template 就兩者通吃
比較好的方法是你自己寫一個二維陣列的 class
而不要用 vector<vector<int> > 或 list<list<int> >
畢竟容器內再塞容器 效率上可能不太理想
另一個方法是寫兩個 template
一個給 int**、double** 這類型別使用
另一個則給 vector<vector<T> > 和 list<list<T> > 使用
雖然多寫了一個 template 但可以多處理許多「容器的容器」
: 我是有想過要typeinfo去處理~
typeinfo 是用在 run-time 取得型別資訊
template 則用在 compile-time 取得型別資訊
兩者是不同的角色
: 不過應該還有其他更聰明的方式處理~
: 有沒有那位大師有經驗的~
: 可以分享一下嘛?
: 感謝~
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 219.87.151.2
推
05/20 11:47, , 1F
05/20 11:47, 1F
→
05/20 11:50, , 2F
05/20 11:50, 2F
→
05/20 11:51, , 3F
05/20 11:51, 3F
→
05/20 11:51, , 4F
05/20 11:51, 4F
→
05/20 11:51, , 5F
05/20 11:51, 5F
→
05/20 11:52, , 6F
05/20 11:52, 6F
→
05/20 11:53, , 7F
05/20 11:53, 7F
→
05/20 11:53, , 8F
05/20 11:53, 8F
→
05/20 12:00, , 9F
05/20 12:00, 9F
→
05/20 22:32, , 10F
05/20 22:32, 10F
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 2 之 3 篇):
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章