最近的專案常常需要更新 INI 設定檔,而最麻煩的事情莫過於太多零散的設定,你必須要記住 INI 檔設定的 key,再把在某個 object 的 member function 把值抓出來,最後再丟給 WritePrivateProfileString 之類的 function 把值更新進檔案。
所以常常就會寫出一堆噁心的 code 像是。
obj.iniKey = "INI_SERVER"; obj.iniValue = info.GetServer(); UpdateByObj(obj);
這樣的話,有幾個設定就要寫幾次,所有的 Key 跟 Value 的相關性都顯得零散,未來要加上新的設定,也非得要再加上類似的 code 才行……。
忽然我就靈機一動,也許可以用 tr1::function 跟 tr1::bind 來做這樣的事情。
struct proxyConfig { std::string iniKey; std::tr1::function<std::string()> func; }; const proxyConfig configArray [] = { { "INI_SERVER", std::tr1::bind(&proxyInfo::GetServer, &info) }, { "INI_PORT", std::tr1::bind(&proxyInfo::GetPort, &info) }, { "INI_USER", std::tr1::bind(&proxyInfo::GetUser, &info) }, { "INI_PASS", std::tr1::bind(&proxyInfo::GetPass, &info) }, }; for (size_t i = 0; i < sizeof(configArray)/sizeof(configArray[0]); ++i) { obj.iniKey = configArray[i].iniKey; obj.iniValue = configArray[i].func(); UpdateByObj(obj); }
靠著把 INI 的 key 跟 member function 建表就顯得簡單一點,並把更新的程式碼簡化成一份,未來如果要新增不同的設定,也只要更動表中的 INI key 跟所綁定的 function 就好。
不過後來仔細想想,其實只要在建表的時候寫成 info.GetServer() 就可以滿足我的需求了。
而 tr1::function 與 tr1::bind 絕對不是只有這點小技倆而已,真正使用的巧妙應該是 C++ Function Objects in TR1 所提及那種彈性而優雅地將 function 包裹成物件,能有改變的彈性,也能應時應地做出適合的調整。
如果你的編譯器還不支援 tr1,除了換一個之外,你還可以考慮一下 boost,也許更瞭解一點,會讓你的生活變得更好歐。