Re: [語法] STL sort 在一個 Class 裡面含很多priv …

看板C_and_CPP (C/C++)作者 (ばかちーは俺の嫁)時間16年前 (2009/10/05 17:34), 編輯推噓13(13058)
留言71則, 4人參與, 最新討論串4/6 (看更多)
※ 引述《minazukimaya (水無月真夜)》之銘言: : 加上getXXX()的做法也是每加一次要改一次model啊.. : 同樣都是汙染原本的class : 為什麼你為認為加十個getter比加一個template function汙染得少呢? : 要提取class其中的private成員 本來就勢必要在class裡面加東西 : 兩者的差別只在你加的是member function還是template member function而已 : : → adrianshum:根本和寫十個 compare_by_Xxx() compare_by_Yyy() 無異 10/05 16:53 : class LessThanByXXX { : public: : bool operator() (GNF& lhs,GNF& rhs) { return lhs.getXXX()<rhs.getXXX();} : }; : 這樣寫十個 和 : template <GNF::SortBy T> : class LessThanBy { : public: : bool operator() (GNF& lhs,GNF& rhs) { return lhs.getAttr<T>() < rhs.getAttr<T> ();} : } : 寫十個前者到底哪裡比較好.. : 除了增加code的長度和降低維護性之外.. : 寫十個functor然後每個functor只差9個字元 這樣真的比較好嗎 但是你沒有必要用enum做這件事 template<typename T, T (GNF::*getter)() const> class LessThanBy { public: bool operator() (const GNF& a, const GNF& b) { return (a.*getter)() < (b.*getter)(); } }; 這樣就好了 enum根本是多此一舉 -- -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 220.133.186.66

10/05 17:36, , 1F
template function call 和function pointer call
10/05 17:36, 1F

10/05 17:36, , 2F
效率不一樣
10/05 17:36, 2F

10/05 17:36, , 3F
當然compiler optimization也許可以解決這個問題
10/05 17:36, 3F

10/05 17:37, , 4F
但是這兩者不過是「效率」和「彈性」的trade-off
10/05 17:37, 4F

10/05 17:37, , 5F
如果要在意幾個cycle的效率差那隨便你...
10/05 17:37, 5F

10/05 17:38, , 6F
可是這個comparator是用來sort的耶= =
10/05 17:38, 6F

10/05 17:38, , 7F
用來sort表示它會不斷的被call,也就是它的效率
10/05 17:38, 7F

10/05 17:38, , 8F
絕對影響整個sort的效率 而且是正比..
10/05 17:38, 8F

10/05 17:39, , 9F
而且重點是 std和boost都有函式配接器幫你做這件事
10/05 17:39, 9F

10/05 17:39, , 10F
所以如果是要寫這種functor,根本不用親自動手
10/05 17:39, 10F

10/05 17:43, , 11F
效率上我不認為在 getter 都 inline 的情況下會是個問題
10/05 17:43, 11F

10/05 17:43, , 12F
透過pointer的函式呼叫本來就比較慢 這也是為什麼
10/05 17:43, 12F

10/05 17:43, , 13F
C的qsort會比std::sort慢的主要原因啊
10/05 17:43, 13F

10/05 17:43, , 14F
(getter 不 inline...你這 getter 還要做什麼事情啊 XD)
10/05 17:43, 14F

10/05 17:44, , 15F
當然如果優秀的compiler是有可能把pointer call
10/05 17:44, 15F

10/05 17:44, , 16F
轉成一般呼叫的
10/05 17:44, 16F

10/05 17:44, , 17F
std::sort 的 functor 的 operator () 呼叫和這裡的其實沒差
10/05 17:44, 17F

10/05 17:44, , 18F
多少的說...
10/05 17:44, 18F

10/05 17:45, , 19F
重點是你有沒有對某個函式進行取址的動作
10/05 17:45, 19F

10/05 17:45, , 20F
可是進 functor 之後位址是固定的...
10/05 17:45, 20F

10/05 17:45, , 21F
如果你要取址 inline就失效了 inline本身只是給
10/05 17:45, 21F

10/05 17:45, , 22F
不管是 functor 的 operator () 還是這裡的 fp
10/05 17:45, 22F

10/05 17:45, , 23F
compiler的「建議」
10/05 17:45, 23F

10/05 17:46, , 24F
compiler不一定真的幫你inline,特別是你會用到他的
10/05 17:46, 24F

10/05 17:46, , 25F
位址的時侯..
10/05 17:46, 25F

10/05 17:47, , 26F
functor 的 operator () 對 compiler 來說還是一樣要取址啊
10/05 17:47, 26F

10/05 17:47, , 27F
不用 甚至有可能連函式呼叫都不用
10/05 17:47, 27F

10/05 17:50, , 28F
唔...所以即使這兩個位址都是 compile-time 已知仍然會有差?
10/05 17:50, 28F

10/05 17:51, , 29F
Inside the C++ Objective model有提到這個
10/05 17:51, 29F

10/05 17:51, , 30F
(我是指 functor 的 operator () 和這裡的 fp 位址)
10/05 17:51, 30F

10/05 17:52, , 31F
functor的operator()有可能用inline做掉啊 因為
10/05 17:52, 31F

10/05 17:52, , 32F
又沒有實際對它取址@@
10/05 17:52, 32F

10/05 17:53, , 33F
那同樣是已知 function 為何 template 的寫法不會知道所呼叫
10/05 17:53, 33F

10/05 17:53, , 34F
的函式為何?
10/05 17:53, 34F

10/05 17:53, , 35F
我覺得 F 大的做法更合理. 那丁點的 performance loss
10/05 17:53, 35F

10/05 17:53, , 36F
(我的觀念裡 template specialize 後那些tmpl. arg是固定的)
10/05 17:53, 36F

10/05 17:54, , 37F
相比起維護性來說簡直不值一哂, code 看起來也更清楚
10/05 17:54, 37F

10/05 17:59, , 38F
你下面那篇才說用template寫functor不合理耶
10/05 17:59, 38F

10/05 18:00, , 39F
Fenikso和我的code差別只在於getter function要不要
10/05 18:00, 39F

10/05 18:00, , 40F
寫成template而已
10/05 18:00, 40F

10/05 18:01, , 41F
TO:LPH66 對 但是你一旦對某個getter function取址
10/05 18:01, 41F

10/05 18:01, , 42F
compiler勢必要生個位址出來 這樣它就不能inline了
10/05 18:01, 42F

10/05 18:01, , 43F
所以boost::function才要做個wrapper包起來
10/05 18:01, 43F

10/05 18:02, , 44F
以確保你在這樣用的時侯不會造成效能上的衝擊
10/05 18:02, 44F

10/05 18:08, , 45F
所以就是 high-level 的函式資訊有沒有被帶過去的關係了...
10/05 18:08, 45F

10/05 18:11, , 46F
(雖然我覺得就算包一層好像還是差不多的狀況...)
10/05 18:11, 46F

10/05 18:11, , 47F
包一層的話 帶過去實際的資訊是Type
10/05 18:11, 47F

10/05 18:12, , 48F
所以呼叫這個Type裡面的operator()的時侯 其實並
10/05 18:12, 48F

10/05 18:12, , 49F
沒有像傳function pointer進去一樣要經過一個取址
10/05 18:12, 49F

10/05 18:13, , 50F
這樣的話operator()就很可能被inline處理掉
10/05 18:13, 50F

10/05 18:15, , 51F
也就是說像這個 getter 的狀況包一層都不一定會比較好就是了
10/05 18:15, 51F

10/05 18:18, , 52F
在getter被傳進去之前就包起來
10/05 18:18, 52F

10/05 18:19, , 53F
就可以避免對getter()取址
10/05 18:19, 53F

10/05 18:24, , 54F
我下一面對你做法最大的問題也在於 intrusive. 但 F大
10/05 18:24, 54F

10/05 18:25, , 55F
的做法就能夠避免, 寫起來的分別可不能同日而語哦...
10/05 18:25, 55F

10/05 18:25, , 56F
等等 原本的class是沒有getter的 為什你會一直假
10/05 18:25, 56F

10/05 18:25, , 57F
設他有呢?
10/05 18:25, 57F

10/05 18:27, , 58F
如果原本的class有getter,那用std的函式配接器
10/05 18:27, 58F

10/05 18:27, , 59F
就可以解決sorting的問題 不需要另外再寫個functor
10/05 18:27, 59F

10/05 18:28, , 60F
std的functino adaptor事實上就是個template functor
10/05 18:28, 60F

10/05 18:31, , 61F
如果你需要更強大的功能 也有boost::bind
10/05 18:31, 61F

10/05 18:31, , 62F
和boost::function可以用
10/05 18:31, 62F

10/05 19:39, , 63F
TO LPH66: 剛剛我把你的問題再想了一遍 的確
10/05 19:39, 63F

10/05 19:40, , 64F
在compile time時template參數的位址是已知 所以
10/05 19:40, 64F

10/05 19:40, , 65F
好的compiler應該要把語法的indirect call 轉成
10/05 19:40, 65F

10/05 19:40, , 66F
direct call
10/05 19:40, 66F

10/05 19:41, , 67F
但是進一步來說能不能轉變成inline call,要由整個
10/05 19:41, 67F

10/05 19:42, , 68F
程式中究竟有沒有地方確實在run-time需要知道該
10/05 19:42, 68F

10/05 19:42, , 69F
function的位址來決定(ex.在runtime把該function取
10/05 19:42, 69F

10/05 19:42, , 70F
址,assign給某個變數之類)
10/05 19:42, 70F

10/05 19:44, , 71F
我想應該前幾大的compiler都會有這種優化能力(大概
10/05 19:44, 71F
文章代碼(AID): #1AoRsjjo (C_and_CPP)
討論串 (同標題文章)
文章代碼(AID): #1AoRsjjo (C_and_CPP)