Generic configuration module
All,
I'm trying to put together a small generic configuration module that can be used to represent configuration options with various scopes and value types.
I have the organization of scopes, keys, and values, where I'm having trouble is storing the values. The goal is to eventually have something like:
Code:
Configuration &cf = Configuration::getConfig();
cf.registerValue<int>("intkey1", kCSGlobalScope, 0);
cf.registerValue<std::string>("strkey2", kCSAScope, "MyString");
// And to retrieve values semantics such as:
cout << "String Value: " << cf.getValue(kCSAScope, "strkey2") << endl;
cout << "Integer Value: " << cf.getValue(kCSGlobalScope, "intkey1") << endl;
// Or alternatively:
cout << "String Value: " << cf.getValue<std::string>(kCSAScope, "strkey2");
cout << endl;
cout << "Integer Value: " << cf.getValue<int>(kGlobalScope, "intkey1") << endl;
Right now I have something like this for Configuration:
Code:
class Configuration
{
public:
static Configuration& getConfig();
template <typename T>
void registerValue(const std::string& key, ConfigScope scope, const T& value);
template <typename T>
const T& getValue() const;
protected:
static Configuration sInstance;
std::map<std::string, ???> mItems;
};
My issue is I'm not sure how to represent the values in an elegant and extendable manner, while not having to resort to external libraries (i.e. Boost::any).
I would really prefer for each config value to be stored in its expected format (that is, an integer value stored in an integer variable, a string in a string, etc) as opposed to storing everything as a common type and doing conversions each time the data is requested(that is storing values a strings and doing strtol or some such when bool or ints are requested).
I have a ConfigItem class that I'm using to pair the scope with the values that looks something like this:
Code:
template <typename T>
class ConfigItem
{
public:
//ctors & dtor
const T& getValue() const;
void setValue(const T& value);
protected:
T mValue;
ConfigScope mScope;
};
The problem here is that I can't do use ConfigItem as an argument to the map declaration in Configuration:
Code:
std::map<std::string, ConfigItem>
won't work. I tried renaming ConfigItem to ConfigItemValue and making a pure virtual base class with no methods called ConfigItem that ConfigItemValue could inherit from. While I could then use ConfigItem in the map declaration I couldn't call getValue from objects pulled out of the map, and dynamic_cast wasn't seeming to behave.
Am I fighting a lost battle without the help of a invariant type?
I'm out of ideas, and any help is appreciated.
Thanks in advance,
Michael Grubb
P.S. I am a fairly new C++ programmer, so please excuse any discrepancies between references, pointers, local vars, etc. They will be corrected in short order.