Hey guys, I'm attempting to learn C++ coming from more of a PHP/Java/C# world and was hoping to get some feedback from some more experienced programmers on this Config class I've come up with. It seems to work exactly as I intend, but I can't shake this feeling that I'm not following some C++ best practices, or that it's somehow unsafe.
Basically what I'm doing is using boost::any to wrap a boost::shared_ptr to create a heterogeneous map of config objects. These are designed to be mostly simple types such as int, float, bool, but I would also like to support dynamic arrays (vector) and maybe simple structures such as Vector3D or Matrix values.
Cvar is supposed to operate as a read only pointer to a value so that I can modify config values at runtime, yet not change config values through the Cvar interface.
Any feedback on this, or things I might have missed would be greatly appreciated. I don't know if I'm just overthinking it, but the class seems like it's too small to be done safely and correctly.
A little syntax of how it's supposed to work.
ConfigMap config;
config.Set<int>("runningSpeed", 10);
Cvar<int> speed = config.Get<int>("runningSpeed", 1);
cout << speed; //Outputs 10
config.Set<int>("runningSpeed", 20);
cout << speed; //Outputs 20
int playerXPos = 5;
playerXPos += speed;
cout << playerXPos; //Outputs 25
And finally the code
template <class TYPE>
class Cvar {
public:
Cvar() : value(NULL) {}
Cvar(boost::shared_ptr<TYPE> t) : value(t) {}
inline friend std::ostream& operator<<(std::ostream& os, const Cvar& dt) {
os << *dt.value;
return os;
}
inline friend std::istream& operator>>(std::istream& is, const Cvar& dt) {
*dt.value >> is;
return is;
}
inline operator TYPE() { return *value; }
private:
boost::shared_ptr<TYPE> value;
};
class ConfigMap {
typedef std::unordered_map<std::string, boost::any> ConfigStore;
public:
template <class TYPE>
void Set(std::string key, TYPE val) {
if(configStore.find(key) == configStore.end()) {
configStore.insert(std::make_pair(key, boost::shared_ptr<TYPE>(new TYPE(val))));
} else {
boost::shared_ptr<TYPE> value = boost::any_cast<boost::shared_ptr<TYPE>>(configStore[key]);
*value = val;
}
}
template <class TYPE>
const Cvar<TYPE> Get(std::string key, TYPE defaultValue) {
if(configStore.find(key) == configStore.end()) {
Set(key, defaultValue);
}
boost::shared_ptr<TYPE> value = boost::any_cast<boost::shared_ptr<TYPE>>(configStore[key]);
return Cvar<TYPE>(value);
}
private:
ConfigStore configStore;
};