2013-07-18 97 views
2

我正在做一個配置類,將保存我的用戶應用程序的配置,並從文件讀取字符串。C++返回一個未知類型

class ConfigKey 
{ 
    public: 
     string KeyLabel; //Will be used to identify this key 
     string KeyValue; //The value 
     bool IsEditable; //For developing uses only, I'm saving a few default and non editable keys for specific apps here 
}; 
class Configuration 
{ 
    public: 
     void AddKey(char* keyLabel, char* keyValue, bool isEditable); 
    private: 
     vector<ConfigKey> configKeys; 
}; 

所以,當我啓動應用程序,我逐行讀取配置文件中的行,並添加到我的配置類:

//Constructor 
Configuration::Configuration() 
{ 
    //read from file, examples 
    AddKey("windowWidth", "1024", false); 
    AddKey("windowHeight", "768", false); 
} 

現在我想在應用程序使用其他地方獲取這些值,有沒有辦法讓我離開配置類的強制轉換? 事情是這樣的:

//In the Configuration class 
void* GetKey(char* keyLabel); 

//And when I call it, I'd like to do something like this: 
int windowAspectRatio = myApp.config.GetKey("windowWidth")/myApp.config.GetKey("windowHeight"); 

的原因是,所以我不有一大堆stringstreams的其他地方的代碼轉換配置值之前,我可以使用它們。 我會在ConfigKey中保存configKey的類型,以便它可以自動轉換它自己。

任何意見或建議?

編輯澄清:

我想用這種方法來檢索configKey:

//In the Configuration Class 
public: 
    int GetKey(char* keyLabel) 
    { 
     //the value I saved in ConfigKey is a "string" type, but I'm converting it to Int before I return it 
     //loop through the vector, find the keyLabel 
     stringstream mySS(foundKey.KeyValue); 
     int returnValue = 0; 
     mySS >> returnValue; //converted the string to int 

     return returnValue; //returned an int 
    } 

所以在代碼的其他地方,我可以打電話:

int myWidth = myConfig.GetKey("windowWidth"); //It's already converted 

但我做不到有多個配置鍵是int,float布爾甚至別的東西。 我正在尋找一種方法來獲取密鑰類型的GetKey(char * keyLabel),然後將其轉換並返回。

或有更好的解決方案的任何意見!

+0

請澄清。你是什​​麼意思「是否有一種方法可以離開配置類的強制轉換」。我不確定你在這裏問什麼。 – Brian

+0

就我個人而言,我會有'int GetIntKey(...)','GetStringKey(...)'等等。 –

回答

3

爲此使用boost::variant

Boost變體允許您使用每種類型都可複製的條件來表示多種類型。

boost::get將允許您從變體中獲取類型。

用例:

template<typename T> T get_config_data(const std::string& key) { 
    return boost::get<T>(some_variant); 
} 

用法:

std::string window_name = config.get_config_data<std::string>("WindowName"); 
int window_width = config.get_config_data<int>("WindowWidth"); 
int window_height = config.get_config_data<int>("WindowHeight"); 
+0

我不認爲我可以使用boost,但使用示例給了我如何解決它的想法,謝謝! – Danicco

0

您可以覆蓋ConfigKey類的轉換運算符並返回它的一個實例。

class ConfigKey 
{ 
    public: 
     string KeyLabel; //Will be used to identify this key 
     string KeyValue; //The value 
     bool IsEditable; //For developing uses only, I'm saving a few default and non editable keys for specific apps here 
     operator int(); //Returns an integer representation of KeyValue 
}; 

您可能需要的情況下,明確地執行轉換的編譯器抱怨:

//In the Configuration class 
void* GetKey(char* keyLabel); 

//And when I call it, I'd like to do something like this: 
int windowAspectRatio = (int)myApp.config.GetKey("windowWidth")/(int)myApp.config.GetKey("windowHeight"); 

在轉換時發生錯誤的情況下(如字符串不表示一個數字),你可以拋出例外。另外,如果「windowHeight」的值不爲0,將很好。

1

你能使用模板

using string_or_int = boost::variant<std::string, int>; 

std::vector<string_or_int> data; 

std::string& s = boost::get<std::string>(data[0]); 

你可以用這個概念來獲得你想要的任何配置信息製作成模板?以下代碼可能不完全正確,但至少應幫助您評估這是否適合您的解決方案:

//In the Configuration Class 
public: 
    template< typename T > 
    T GetKey(char* keyLabel) 
    { 
     stringstream mySS(foundKey.KeyValue); 
     T returnValue; 
     mySS >> returnValue; 
     return returnValue; 
    } 

// elsewhere 
int myWidth = myConfig.GetKey<int>("windowWidth");