I'm trying to implement a configuration manager class in c++11 that would load settings from *.xml files. The first implementation (I used structs instead of classes only for easy testing):
struct ConfigManager
{
ConfigManager(){}
void initialize()
{
add<CoreSettings>(std::make_unique<CoreSettings>("WhatEver.xml"));
}
template <typename T>
void add(std::unique_ptr<T> settings)
{
settings_.insert(std::make_pair(std::type_index(typeid(T)), std::move(settings)));
}
template <typename T>
T& get() const
{
auto it = settings_.find(std::type_index(typeid(T)));
return dynamic_cast<T&>(*it->second);
}
void load()
{
for (auto& s : settings_)
s.second->load();
}
void save()
{
for (auto& s : settings_)
s.second->save();
}
std::map<std::type_index, std::unique_ptr<ISettings>> settings_;
};
It would allow me to write code like below to use this class:
ConfigManager confManager;
confManager.initialize();
confManager.load();
auto& coreSettings = confManager.get<CoreSettings>();
coreSettings.windowOptions_.height_ = 800;
confManager.save();
A more simple implementation would be:
struct ConfigManager : public IConfigManager
{
ConfigManager()
{
set_.insert(&coreSettings_);
}
virtual void load() final
{
for (auto& s : set_)
s->load();
}
virtual void save() final
{
for (auto& s : set_)
s->save();
}
virtual CoreSettings& getCoreSettings() final
{
return coreSettings_;
}
CoreSettings coreSettings_;
std::set<ISettings*> set_;
};
But this way I have to write a lot of getters for all kind of settings I will create.
Which one do you think it's better and why? Maybe this is not at all how it should be done; your opinion is appreciated.
I'd prefer option #1, precisely because it doesn't need to know of all setting types in advance. However, you should add some error checking into get()
to react to a situation when the appropriate setting is not found (and thus it == settings_.end()
).