2013-10-22 81 views
0

我使用的是其具有具有 不同的功能,這樣的JSON解析類第三方C++庫函數的名稱:模板替代

GetInt 
GetBool 
GetString 
GetDouble 

我想編寫一個可以訪問的效用函數這個班。我想的是這樣的:

class <template T> 
class MyClass { 
static T getValue(ThirdPartyClass someObj, const string &key) { 
    if(someObj[key].IsDouble()) 
     return someObj[key].GetDouble(); 
    else if (someObj[key].IsString()) 
     return someObj[key].GetString(); 
    // ... (for other types) 

} 
} 

這個類的調用者將持有正確的返回類型。

然而這很難看。有什麼辦法(例如使用宏替代)我可以避免if條件?第三方類具有IsXXTypeXX和相應的GetXXTypeXX函數(其中XXTypeXX是Int,Double,String或Bool)。

我知道的返回類型,當我調用函數如:

int i = getValue(someObj, "intKey"); 
string s = getValue(someObj, "strKey"); 

所以我不需要了,如果條件都沒有。理想我想看看有沒有東西,所以我 將能夠做到這一點:

int i = MyClass<int>::getValue(someObj, "intKey"); 

string s = MyClass<string>::getValue(someObj, "strKey"); 

回答

1

爲什麼不只是寫一堆的靜態Get功能(GetInt/GetDouble ...),用於驗證輸入,返回相應的鍵入結果並拋出一個異常,如果它不是那種類型?

1

從技術上講,你可以實現你在那裏概述的公共接口,但會涉及非常難看的模板專業化。 它可能會更好,如果你只是有一堆靜態功能。以下是模板專業化的樣子:

template <typename T> class MyClass { 
    static T getValue(ThirdPartyClass someObj, const string &key) { 
     // handle types that you didn't specialize for 
    } 
}; 
template <> class MyClass <string> { 
    static string getValue(ThirdPartyClass someObj, const string &key) { 
     return someObj[key].GetString(); 
    } 
}; 
template <> class MyClass <int> { 
    static int getValue(ThirdPartyClass someObj, const string &key) { 
     return someObj[key].GetInt(); 
    } 
}; 
//.. 
+0

模板專門化是一個很好的解決方案,因爲它提供了編譯時類型解析機制,而不是運行時類型檢查和分支。 – holtavolt

+0

謝謝。我以前沒有使用過模板專業化。我會用這個。 – Nura

0

您顯示的代碼不會編譯。您不能在同一個函數中返回doublestringint。什麼你必須做專門爲每個返回類型,然後調用只該類型的函數:

template <> 
class MyClass<int> getValue(ThirdPartyClass someObj, const string& key) { 
    if(someOjb[key].IsInt()) return someObj[key].GetInt(); 
    else { /* Maybe throw an exception */ } 
}; 

和重複每個類型。

現在,你可能會想:「這很愚蠢,我爲什麼要專門化每種類型?」這是因爲你的JSON庫正在使用類型擦除,所以你必須在運行時檢查類型。如果圖書館提供了模板get,那麼保存作品的唯一方法就是保存作品。

如果你願意,你可以創建一個宏來標記這些實例。它將利用預處理器的#stringification)和##concatenation)功能。將它們寫出來可能會更清楚。

+0

是的,我給出的代碼只是我想的一個例子,而不是實際的代碼。感謝您指出錯誤:)並感謝您的串聯建議(不熟悉) – Nura

1

軟件工程的骨架鍵:添加一箇中間層。

#include <string> 
#include <cassert> 
using std::string; 

class Proxy { 
public: 
    enum Type { 
    Int, 
    Bool, 
    String, 
    Double 
    }; 
    Type type; 
    int i; 
    bool b; 
    string s; 
    double d; 
    operator int() const { 
    assert(type == Int); 
    return i; 
    } 
    operator bool() const { 
    assert(type == Bool); 
    return b; 
    } 
    operator string() const { 
    assert(type == String); 
    return s; 
    } 
    operator double() const { 
    assert(type == Double); 
    return d; 
    } 
    Proxy(int i) : type(Int), i(i) {} 
    Proxy(bool b) : type(Bool), b(b) {} 
    Proxy(string s) : type(String), s(s) {} 
    Proxy(double d) : type(Double), d(d) {} 
}; // class Proxy 

Proxy getValue(ThirdPartyClass someObj, const string &key) { 
    if (someObj[key].IsDouble()) 
    return someObj[key].GetDouble(); 
    else if (someObj[key].IsString()) 
    return someObj[key].GetString(); 
    //... (for other types) 
} 

int main() { 
    int i = getValue(someObj, "intKey"); // if type does not match, a exception will be thrown. 
    string s = getValue(someObj, "strKey"); 
}