有什么好的方法可以合并或简化这些STL贴图吗?
Is there a good way to combine or simplify these STL maps?
我正在写一个 class 需要存储一堆不同的基元和 classes。我决定为每种不同的数据类型创建一个映射,其中映射中的键是变量的名称,映射中的值是变量的值。我的地图定义如下:
std::unordered_map<std::string, int> myInts;
std::unordered_map<std::string, float> myFloats;
std::unordered_map<std::string, Something> mySomethings;
对于每张地图,我必须编写两种方法,一种获取某个变量的值,另一种设置某个变量的值,如下所示:
void setMyInt(const std::string &varName, int newVal) {
myInts[varName] = newVal;
}
int getMyInt(const std::string &varName) {
return myInts[varName];
}
一切都很好,也很简单,但是,我最终得到了 8 个不同的地图,其中 16 个 get set 方法。这对我来说似乎不是很有效或干净,更不用说每次我需要存储新数据类型时我都必须定义一个新映射并编写 2 个新的 get-set 方法。
我考虑摆脱 get set 方法,而是编写 2 个模板方法,这些方法将接受用户需要获取或设置的变量类型,然后访问适当的集合来执行操作,比如所以:
template<class Type>
void getVariable<Type>(const std::string &varName) {
// if Type == int -> return myInts[varName];
// else if Type == float -> return myFloats[varName];
}
这似乎是一个非常糟糕的方法,因为用户可以传入 class 不支持的类型,并且该方法打破了 C++ 不是真正通用的规则。
我的另一个想法是编写一些变量 class,它将包含此 class 应该存储的所有字段,以及一些定义 class 是什么变量的枚举实际上被用于,然后制作这个变量的地图 class 像这样:
enum Type {
TYPE_INT,
TYPE_FLOAT,
TYPE_SOMETHING
class Variable {
Type type;
int myInt;
float myFloat;
Something mySomething;
}
std::unordered_map<std::string, Variable> myVariables;
但这似乎也是一个非常糟糕的解决方案,或者至少是一个难以理解的解决方案。有什么聪明的方法可以让这个 class 存储不同的类型吗?
模板如何 class 如下所示:
template<typename ValueType>
class UnorderedStringMap : public std::unordered_map<std::string, ValueType> {
public:
...
void setValue(const std::string &varName, ValueType newVal) {
std::unordered_map::operator[](varName) = newVal;
}
const ValueType& getValue(const std::string &varName) {
return std::unordered_map::operator[](varName);
}
...
}
UnorderedStringMap<int> myInts;
UnorderedStringMap<float> myFloats;
然后您也可以将其用作普通 std::unordered_map。
我正在写一个 class 需要存储一堆不同的基元和 classes。我决定为每种不同的数据类型创建一个映射,其中映射中的键是变量的名称,映射中的值是变量的值。我的地图定义如下:
std::unordered_map<std::string, int> myInts;
std::unordered_map<std::string, float> myFloats;
std::unordered_map<std::string, Something> mySomethings;
对于每张地图,我必须编写两种方法,一种获取某个变量的值,另一种设置某个变量的值,如下所示:
void setMyInt(const std::string &varName, int newVal) {
myInts[varName] = newVal;
}
int getMyInt(const std::string &varName) {
return myInts[varName];
}
一切都很好,也很简单,但是,我最终得到了 8 个不同的地图,其中 16 个 get set 方法。这对我来说似乎不是很有效或干净,更不用说每次我需要存储新数据类型时我都必须定义一个新映射并编写 2 个新的 get-set 方法。
我考虑摆脱 get set 方法,而是编写 2 个模板方法,这些方法将接受用户需要获取或设置的变量类型,然后访问适当的集合来执行操作,比如所以:
template<class Type>
void getVariable<Type>(const std::string &varName) {
// if Type == int -> return myInts[varName];
// else if Type == float -> return myFloats[varName];
}
这似乎是一个非常糟糕的方法,因为用户可以传入 class 不支持的类型,并且该方法打破了 C++ 不是真正通用的规则。
我的另一个想法是编写一些变量 class,它将包含此 class 应该存储的所有字段,以及一些定义 class 是什么变量的枚举实际上被用于,然后制作这个变量的地图 class 像这样:
enum Type {
TYPE_INT,
TYPE_FLOAT,
TYPE_SOMETHING
class Variable {
Type type;
int myInt;
float myFloat;
Something mySomething;
}
std::unordered_map<std::string, Variable> myVariables;
但这似乎也是一个非常糟糕的解决方案,或者至少是一个难以理解的解决方案。有什么聪明的方法可以让这个 class 存储不同的类型吗?
模板如何 class 如下所示:
template<typename ValueType>
class UnorderedStringMap : public std::unordered_map<std::string, ValueType> {
public:
...
void setValue(const std::string &varName, ValueType newVal) {
std::unordered_map::operator[](varName) = newVal;
}
const ValueType& getValue(const std::string &varName) {
return std::unordered_map::operator[](varName);
}
...
}
UnorderedStringMap<int> myInts;
UnorderedStringMap<float> myFloats;
然后您也可以将其用作普通 std::unordered_map。