Re: [問題] 相似的功能但不知如何合併

看板C_and_CPP (C/C++)作者 (眠月)時間13年前 (2012/06/29 01:45), 編輯推噓8(804)
留言12則, 8人參與, 最新討論串2/2 (看更多)
我舉實際一點的例子,比方說取得 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)

06/29 01:56, , 1F
full source code http://ideone.com/qLKXX
06/29 01:56, 1F

06/29 02:27, , 2F
workship !!
06/29 02:27, 2F

06/29 02:35, , 3F
^ worship ? XD
06/29 02:35, 3F

06/29 02:53, , 4F
orz , worship is right.
06/29 02:53, 4F

06/29 03:23, , 5F
actually i thought of "workshop" at first glance...
06/29 03:23, 5F

06/29 08:35, , 6F
worship!!!!!
06/29 08:35, 6F

06/29 08:48, , 7F
看來看去還是比較喜歡 specialized 的做法XD
06/29 08:48, 7F

06/29 10:39, , 8F
可是pointer-to-member好像比較好閱讀
06/29 10:39, 8F

06/29 11:14, , 9F
workshop
06/29 11:14, 9F

06/29 12:44, , 10F
http://ideone.com/HAuSk 供比較喜歡特化但沒有C++11又覺得
06/29 12:44, 10F

06/29 12:44, , 11F
數字不好閱讀的人參考
06/29 12:44, 11F

06/30 01:30, , 12F
worship~~
06/30 01:30, 12F
文章代碼(AID): #1Fx9WjHe (C_and_CPP)
文章代碼(AID): #1Fx9WjHe (C_and_CPP)