2016-05-16 49 views
0

所以爲了get_as (),以獲得更多的進元編程我試圖用一個 ConfigParser使用SFINAE實現

template<typename T> T get_as(std::string key) 

一樣的界面,編寫一個配置文件解析器可以返回解析值作爲一個特定的類型。由於我在內部將解析的配置文件存儲爲字符串映射,因此我仍然需要在轉換大部分數據之前將其返回。所以我使用type_traits頭來根據請求的類型來轉換數據。我做了以下假設:

  • 所有非平凡類型都必須提供一個構造函數,它需要一個std :: string來構造它們自己。當且僅當它們拼寫錯誤,否則,我們拋出一個異常

實現是頭只,可以在我的github page找到

  • 字符串是真的當且僅當他們拼出真(公正,以降低/上/混合詞),假。

    /// INTEGRAL TYPES 
    template<class T, typename std::enable_if<std::is_integral<T>::value && !std::is_same<bool, T>::value>::type* = nullptr> 
    T get_as(std::string key) 
    { 
        // Implementation 
    } 
    
    /// FLOATING TYPES 
    template<class T, typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr> 
    T get_as(std::string key) 
    { 
        // Implementation 
    } 
    
    /// BOOL 
    template<class T, typename std::enable_if<std::is_same<bool, T>::value>::type* = nullptr> 
    T get_as(std::string key) 
    { 
        // Implementation 
    } 
    
    /// COMPLEX TYPE 
    template<class T, typename std::enable_if<std::is_class<T>::value>::type* = nullptr> 
    T get_as(std::string key) 
    { 
        // Implementation 
    } 
    

    我有的問題是,這是否是一個好的設計來拆分我這樣執行取決於請求的類型。或者是否有更好的方法來實現類型相關的get_as接口?

  • +3

    僱傭失敗不是錯誤...原子? – Yakk

    +1

    這可能更適合於[Code-Review](// codereview.stackexchange.com)Stack Exchange站點。 –

    +0

    @TobySpeight謝謝 - 我不知道有這樣的事情。這就是爲什麼我試圖相應標記它。下次將使用其他網站:) – datosh

    回答

    1

    例外情況應該是例外。

    您應該審覈配置文件,並確保不會發生任何異常:保存和可能的版本,以便您可以檢測舊版本。那麼配置文件無效的故障現在是例外。

    也可能不是加載字符串字符串映射,而是在加載時加載配置數據,而不是在使用位置。

    將配置數據的佈局和序列化連接起來。一個檔案系統,如:

    struct config { 
        int x; 
        std::string bar; 
        bool b; 
    
        template<class A, class Config, 
        std::enable_if_t<std::is_same<std::decay_t<Config>, config>>::value, int>* =nullptr 
        > 
        friend void Archive(A& a, std::string name, Config& config) { 
        auto tag = Archive(a, name, ArchiveTag); 
        Archive(a, "x", config.x); 
        Archive(a, "bar", config.bar); 
        Archive(a, "b", config.b); // etc 
        } 
    }; 
    

    現在我們有一個檔案系統,以類型安全的方式保存和加載。類型錯誤被提前發現。錯誤可能是例外情況,或者說存儲在Archive類型中,並且可能處理的是整體。

    如果您正在閱讀的文件缺少一個字段,那麼可能存在從中讀取的默認存檔。

    +0

    這似乎是一個很好的方法來避免按要求鑄造/轉換數據,但我不能再請求不同類型的值,不是嗎?我必須在配置文件的每一行中的實現(配置中的存儲空間和另一個存檔行)中添加兩行。這個實現如何擴展一個配置文件數百行? – datosh

    +0

    @dat請求作爲錯誤類型的東西是類型錯誤,不是嗎?有一個固定的字段是一個布爾值或一個整數的有效原因很少。基本上,我將所需的類型知識從*每個使用點的代碼中移除,其中錯誤導致任何代碼想要配置數據*的異常,*一個點,其中可以集中處理錯誤處理*。除了讀取配置數據的例外情況,意味着要麼是一個不穩定的/不可預知的程序,要麼是每一個配置訪問周圍的一噸的異常處理和單元測試! – Yakk

    +0

    是的,我明白這一點。我的想法是,我可以將它用於複雜類型,將T類從類Foo交換到類Bar,構造函數處理剩餘的類型。但是我的另一個問題呢?你的方法看起來不太好,是嗎? – datosh