Reputation: 1673
I'm making a Configuration class that will hold my user application's configuration, and it reads from a file as strings.
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;
};
So when I start the app, I read the config file line by line and add to my Config class:
//Constructor
Configuration::Configuration()
{
//read from file, examples
AddKey("windowWidth", "1024", false);
AddKey("windowHeight", "768", false);
}
Now I want to retrieve these values somewhere else for use in the app, is there a way I can leave the cast for the Configuration class? Something like this:
//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");
The reason is so I don't have a bunch of stringstreams elsewhere in the code converting the config values before I can use them. I would save the configKey's type as well in the ConfigKey so it can auto-convert itself.
Any advice or suggestions?
Edit for clarification:
I want to retrieve a configKey using this method:
//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
}
So elsewhere in the code I can call:
int myWidth = myConfig.GetKey("windowWidth"); //It's already converted
But I can have multiple configKeys that are either int, float, bool or even something else. I'm looking for a way to have the GetKey(char* keyLabel) to check for the keyType, then convert it, then return it.
Or any advice on a better solution!
Upvotes: 2
Views: 1263
Reputation: 772
Can you use templates? The following code may not be totally correct, but should at least help you evaluate whether this is a solution that will work for you:
//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");
Upvotes: 1
Reputation: 9071
Use boost::variant
for this.
Boost variant allows you to represent multiple types with the condition that each type is copyable.
boost::get
will allow you to get a type out of the variant.
Usage example:
using string_or_int = boost::variant<std::string, int>;
std::vector<string_or_int> data;
std::string& s = boost::get<std::string>(data[0]);
You can make a template using this concept to get whatever configuration information you want:
template<typename T> T get_config_data(const std::string& key) {
return boost::get<T>( some_variant );
}
Usage:
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");
Upvotes: 3
Reputation: 968
You can override the conversion operator for ConfigKey class and return an instance of it.
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
};
You might have to perform the conversion explicitly in case the compiler complains:
//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");
In case of an error in the conversion (e.g. the string does not represent a number) you can throw an exception. Also, would be nice to check if "windowHeight" does not have the value of 0.
Upvotes: 0