I have a class UISceneParams
and I use it to store some parameters that I want to send over to a UIScene. It contains a unordered_map
of shared_ptr
s to DataParam
instances.
The problem is that my DataParam must use a template and feature multiple data types.
Is there any way I can make the unordered_map
use multiple data types of DataParams?
I currently call this like this:
UISceneParams p;
p.AddParam<int>("test_value", 123);
p.AddParam<int>("test_value2", 456);
and in my scene I get the parameters using the GetParam<T>
method, like this:
int value1 = p.GetParam<int>("test_value", 0);
int value2 = p.GetParam<int>("test_value2", 0);
I've been trying many ways to circumvent the errors, but I am a beginner with templates in C++. Can someone get me on the right track?
UISceneParams.h
#pragma once
#include <string>
#include <unordered_map>
#include <memory>
using namespace std;
template <typename T>
class DataParam {
public:
DataParam(string t, T v) {
_tag = t;
_val = v;
}
T Value() const {
return _val;
}
string Tag() const {
return _tag;
}
private:
string _tag;
T _val;
};
class UISceneParams {
public:
bool HasParam(string tag) {
return params.find(tag) != params.end();
}
template <typename T>
void AddParam(string tag, T value) {
if (HasParam(tag)) params.erase(tag);
params.insert({ tag, make_shared<DataParam>(tag, value) });
}
template <typename T>
T GetParam(string tag, T def_value) {
if (!HasParam(tag)) return def_value;
auto p = params.find(tag)->second;
return p->Value;
}
private:
unordered_map<string, shared_ptr<DataParam>> params;
};
Edit: Final code
#pragma once
#include <string>
#include <unordered_map>
#include <memory>
using namespace std;
class IDataParam
{
public:
virtual ~IDataParam() = default;
};
template <typename T>
class DataParam : public IDataParam {
public:
DataParam(string t, T v) {
_tag = t;
_val = v;
}
T Value() const {
return _val;
}
string Tag() const {
return _tag;
}
private:
string _tag;
T _val;
};
class UISceneParams {
public:
bool HasParam(string tag) {
return params.find(tag.data()) != params.end();
}
template <typename T>
void AddParam(string tag, T value) {
if (HasParam(tag)) params.erase(tag);
params.insert({ tag, make_shared<DataParam<T>>(tag, value) });
}
template <typename T>
T GetParam(string tag, T def_value) {
if (!HasParam(tag)) return def_value;
auto p = dynamic_cast<const DataParam<T> &>(*params.find(tag)->second);
return p.Value();
}
private:
unordered_map<string, shared_ptr<IDataParam>> params;
};