初探 TR1 function object

最近的專案常常需要更新 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,也許更瞭解一點,會讓你的生活變得更好歐。

Leave a Reply

Your email address will not be published. Required fields are marked *