Reputation: 701
I am trying to create a class that can map strings to some arbitrary objects or even primitive types. To clarify, I am not talking of one single generic type, but different types, so the map could look something like this:
["speed": 3, "useNormal": false, "normal": Vec3()]
One approach I have attempted was to create a BaseObject
struct and derive other class like IntObject
and FloatObject
from it. This way I was able to create a std::map<std::string, BaseObject*>
. But this approach feels clunky and getters and setters for the map need a switch case for every single type.
Someone suggested to use bytes. Basically this means to serialize and deserialize the object into bytes arrays and therefore the map would look something like this std::map<std::string, byte*>
. But with this approach the big hurdle to overcome is to somehow generate an object of a certain type from a byte array, which I don't know how to do.
Another suggestion was also to use c++17 variants. But that is too new to be widely supported.
I would appreciate any kind of input!
Upvotes: 1
Views: 4603
Reputation: 51
Using smart pointers instead of raw would fix the memory leaks. Here is a modified version of @Haeri
#include <iostream>
#include <memory>
#include <unordered_map>
struct SuperObject {};
template<class T>
struct BaseObject : SuperObject {
T _value;
BaseObject(T value) : _value(value) {
std::cout << "Constructed" << std::endl;
}
~BaseObject() {
std::cout << "Destroyed" << std::endl;
}
};
std::unordered_map<std::string, std::shared_ptr<SuperObject>> objectMap;
template<typename T>
void setValue(std::string name, T value) {
objectMap[name] = std::make_shared< BaseObject<T>>(value);
}
template <typename T>
T getValue(const std::string& name) {
return ((std::static_pointer_cast<BaseObject<T>>)(objectMap[name]))->_value;
}
int main()
{
setValue<int>("a", 5);
setValue<double>("b", 5.62342423);
std::cout << getValue<int>("a") << std::endl;
std::cout << getValue<double>("b") << std::endl;
}
Upvotes: 0
Reputation: 701
There is a general consent that std::map<std::string, std::any>>
would be the best solution for this. But since I am trying to avoid boost and c++17, here is a pure c++ implementation an object oriented approach to this problem:
struct SuperObject {};
template<class T>
struct BaseObject: SuperObject {
T _value;
BaseObject(T value) : _value(value) {}
};
std::unordered_map<std::string, SuperObject*> objectMap;
template<typename T>
void setValue(std::string name, T value) {
objectMap[name] = new BaseObject<T>(value);
}
template <typename T>
T getValue(const std::string& name) {
return ((BaseObject<T>*)(objectMap[name]))->_value;
}
Please mind the huge memory leak when calling setValue()
Upvotes: 4