Stack Overflow Asked by nintendoeats on December 15, 2020
I am refactoring a "profiles" system with the goal of reducing the amount of repeated code required to save, load, and access settings. However, I am finding that I am just shuffling the repeated code around (decreasing it in one place increases it in another). I feel like I am missing something.
Note, in this scheme there is a concept of the "default" profile, which is selectively masked by the "loaded" profile. The user can configure all settings in the default profile, then just change specific settings for other profiles. For example, the user might want to use the same port number for all profiles (defined in the default profile), but specify a different IP address for connecting to different computers (defined in the loaded profile).
This functionality is not actually implemented yet, it is part of the reason I am refactoring.
Each setting has to be associated with the following information:
Initially, I defined all of these as member variables of a struct. This is very easy to use for accessing settings. I can just pass the profile struct to any function that needs the settings, then access a particular setting using profile.thingy
.
Unfortunately, saving and loading settings in this scheme requires adding separate save/load code for each setting. Similarly, to generate a "merged" settings profile that combines the default and current profiles will require manually coding merging for each setting. I also needed to add separate "useDefault" and "xmlName" variables for each setting. It was all a bit silly.
To start with, I implemented a class template SerfSetting
which contains the 3 pieces of data mentioned earlier.
template <class T>
class SerfSetting {
public:
T value;
string xmlName;
bool useDefault = false;
This is a little bit more annoying to access, since now I need to write profile.setting.value
everywhere, but that’s not so bad. I also overloaded =
and ==
to operate on value
instead of the object itself, so sometimes this is transparent.
The real problem is when I try to turn this into something iterable, to save myself from having to repeat S/L/M (saving/loading/merging) code for every new setting.
What I’m looking at right now is using std::any
, or a separate std::vector
or std::map
for each type of data. For S/L/M these would be perfect, very simple to iterate over. However, accessing a setting then becomes profile.listOfSettings[SETTING_INDEX_CONSTANT].value
(or similar), which is pretty absurd for a common task and adds a potential for runtime bugs that might be difficult to catch (since I need to manually maintain the setting index constants, and manually ensure that the correct setting is being accessed).
Ideally I would be able to just iterate over the member variables of the profile struct, but the internet is quite clear that "C++ does not support reflection" and the alternatives I have seen are just as contrived and ugly as what I described above.
Is there a sensible solution to this problem, or am I resigned to having something ugly somewhere?
Thanks!
I appreciate your comments, and am happy to now be aware of those tools (though I'm not sure std::optional
applies in this case, since all values are expected to be non-null when they are accessed).
As often happens, taking the time to clearly state the problem in words helped me to solve it. I realized after posting, I was making the false assumption that I needed to access and iterate over the settings using the same object.
I believe that the simple solution is this:
struct SerfProfile {
vector<SerfSetting<string>*> stringPtrList;
SerfSetting<string> IPaddress = SerfSetting<string>();
SerfProfile() {
stringPtrList.push_back(&IPaddress);
}
};
I can access the setting using IPaddress.value
and iterate over the settings using stringPtrList
. This also makes it easy to make profile settings that are not S/L/M, if I ever need to do that for some reason.
I appreciate you taking the time to look over this problem.
Answered by nintendoeats on December 15, 2020
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP