作者yoco315 (眠月)
看板C_and_CPP
標題Re: [問題] 相似的功能但不知如何合併
時間Fri Jun 29 01:45:15 2012
我舉實際一點的例子,比方說取得 max。
我先用爛方法寫出兩個實作品:
struct point {
int x ;
int y ;
} ;
int max_
x ( std::vector<point>& v ) {
int result = v[0].
x ;
for ( std::vector<point>::size_type i = 1; i != v.size(); ++i )
if(v[i].
x > result)
result = v[i].
x ;
return result ;
}
int max_
y ( std::vector<point>& v ) {
int result = v[0].
y ;
for ( std::vector<point>::size_type i = 1; i != v.size(); ++i )
if(v[i].
y > result)
result = v[i].
y ;
return result ;
}
std::cout << max_
x(v) << std::endl ;
std::cout << max_
y(v) << std::endl ;
我現在要寫一個通吃兩者的函數,我有兩種作法。
一種是使用「access idiom」
就是我存取 point 的 x 或是 y 的時候,不直接使用 p.x 這種形式,
而是透過一個 access 函數去存取:
int& access(point& p,
const int index) {
return index == 0 ? p.x : p.y ;
}
int max ( std::vector<point>& v,
const int index) {
int result =
access(v[0], index) ;
for ( std::vector<point>::size_type i = 1; i != v.size(); ++i )
if(
access(v[i], index) > result)
result =
access(v[i], index) ;
return result ;
}
std::cout << max(v,
0) << std::endl ;
std::cout << max(v, 1) << std::endl ;
更進一步,
為了省去這個 access function 當中 if 的成本,
我們把他改寫成 template 的版本……
template < int N > int& access(point& p) ;
template <> int& access<0>(point& p) { return p.x ; }
template <> int& access<1>(point& p) { return p.y ; }
template
< int N >
int max ( std::vector<point>& v) {
int result =
access<N>(v[0]) ;
for ( std::vector<point>::size_type i = 1; i != v.size(); ++i )
if(
access<N>(v[i]) > result)
result =
access<N>(v[i]) ;
return result ;
}
std::cout << max
<0>(v) << std::endl ;
std::cout << max<1>(v) << std::endl ;
另外一個方法,如果不喜歡 specialized 一堆 access 的版本,
我們還有一個 pointer-to-member 的方法可以用,在這邊剛好!
int max ( std::vector<point>& v,
int point::*m )
{
int result = v[0].
*m ;
for ( std::vector<point>::size_type i = 1; i != v.size(); ++i )
if(v[i].
*m > result)
result = v[i].
*m ;
return result ;
}
std::cout << max(v,
&point::x) << std::endl ;
std::cout << max(v, &point::y) << std::endl ;
效能的話……
specialized access<>() 最快。
跟手工寫兩個版本的程式碼一樣快,
為了彌補呼叫時候 max<0>(v) 其意含不直覺的缺點,
可以使用 C++11 const_expr int X = 0;
或是其他你喜歡的手法避開這個問題。
希望對你的問題有幫助。
--
To iterate is human, to recurse, divine.
遞迴只應天上有, 凡人該當用迴圈. L. Peter Deutsch
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 111.185.67.169
※ 編輯: yoco315 來自: 111.185.67.169 (06/29 01:46)
推 EdisonX:workship !! 06/29 02:27
→ purincess:^ worship ? XD 06/29 02:35
推 EdisonX:orz , worship is right. 06/29 02:53
→ purincess:actually i thought of "workshop" at first glance... 06/29 03:23
推 shininglion:worship!!!!! 06/29 08:35
推 shininglion:看來看去還是比較喜歡 specialized 的做法XD 06/29 08:48
推 azureblaze:可是pointer-to-member好像比較好閱讀 06/29 10:39
推 ericinttu:workshop 06/29 11:14
→ Chikei:數字不好閱讀的人參考 06/29 12:44
推 VictorTom:worship~~ 06/30 01:30