我有一个使用3种不同映射的类:键总是字符串,而值可以是字符串、整数或浮点。
class MyMaps
{
public:
template<typename T> void addKey(const std::string& key);
void addValue(const std::string& key, const std::string& value);
void addValue(const std::string& key, int value);
void addValue(const std::string& key, float value);
private:
std::map<std::string, std::string> stringFields;
std::map<std::string, int> intFields;
std::map<std::string, float> floatFields;
};
addValue()
函数只是向相关映射添加一个新的对。我正在做的是addKey()
模板函数:
/** Add only a key, the related value is a default one and is specified by template parameter T. */
template<typename T>
void MyMaps::addKey(const string& key)
{
if (typeid(T) == typeid(string))
{
stringFields.insert(pair<string, string>(key, string()));
}
else if (typeid(T) == typeid(int))
{
intFields.insert(pair<string, int>(key, int()));;
}
else if (typeid(T) == typeid(float))
{
floatFields.insert(pair<string, float>(key, float()));
}
}
基本上,我使用template
和typeid()
,因为我不喜欢这种依赖于函数名中类型的替代方案:
void MyMaps::addStringKey(const string& key)
{
stringFields.insert(pair<string, string>(key, string()));
}
void MyMaps::addIntKey(const string& key)
{
intFields.insert(pair<string, int>(key, int()));
}
void MyMaps::addFloatKey(const string& key)
{
floatFields.insert(pair<string, float>(key, float()));
}
第一个addKey()
版本似乎正在运行,但我想知道是否有更优雅的解决方案。也许我错过了一些面向对象的设计概念,在这种情况下可能会有所帮助?
提前谢谢。
这非常适合模板专业化:
template<>
void MyMaps::addKey<string>(const string& key)
{
stringFields.insert(pair<string, string>(key, string()));
}
template<>
void MyMaps::addKey<int>(const int& key)
{
intFields.insert(pair<string, int>(key, int()));;
}
template<>
void MyMaps::addKey<float>(const float& key)
{
floatFields.insert(pair<string, float>(key, float()));
}
编辑:有关模板专业化的语法/更多信息,请阅读:模板专业化和部分模板专业化
或者更好的是,如果boost是一个选项,并且所有3个地图的密钥都是唯一的,并且您有3个不同的地图来存储它们,那么可以考虑使用boost::variant
:
typedef boost::variant<string, int, float> ValueType;
class MyMap
{
public:
typedef std::map<std::string, ValueType> MapType;
template<typename T> void addKey(const std::string& key, T &val)
{
ValueType varVal= val;
allFields.insert(MapType::value_type(key, varVal));
}
private:
MapType allFields;
};
您的问题询问两件事:
-
真正的问题是,在同一集合中使用不同类型的值来制作键值映射或字典。
-
还有一个潜在的解决方案,应用"typeid"函数。
更多关于"typeid"的参考:
http://en.cppreference.com/w/cpp/language/typeid
对象(和类)定向是很好的,但是,有时您可能想将其与其他范式混合使用。
"指针"呢?
指针允许将不同的类型视为同一个简单类型。
键值字典集合呢?它存储字符串键和指针值,指针可以是整数、字符串或对象。
或者更具体地说。"Value"可以是一个元组,其中第一个字段(可能是枚举类型)指示值的真实类型。"Value"的第二个字段是指向实字段的指针或变量。
第一个建议使用"联合"(也称为"变体"),无指针:
#include <string>
#include <typeinfo>
union ValueUnion
{
int AsInt,
float AsFloat,
std::string& AsStr
};
struct ValueType
{
std::type_info Id,
ValueUnion Value
};
class MyMaps
{
public:
template<typename T> void addKey(const std::string& key);
void addValue(const std::string& key, const std::string& value);
void addValue(const std::string& key, int value);
void addValue(const std::string& key, float value);
private:
std::map<std::string, ValueType> Fields;
};
或者,带指针:
#include <string>
#include <typeinfo>
struct ValueType
{
std::type_info Id,
void* Value
};
class MyMaps
{
public:
template<typename T> void addKey(const std::string& key);
void addValue(const std::string& key, const std::string& value);
void addValue(const std::string& key, int value);
void addValue(const std::string& key, float value);
private:
std::map<std::string, ValueType> Fields;
};
这种"模式"我见过好几次了,我称之为"键值类型"集合。
注意:STL的经验不多,你确定"std::map"吗,这是正确的收藏品吗?
只有我的2美分。
可能不是您想要的,因为这是一种不同的方法,但您可以使用变体映射。您可以定义一个boost::变量来只保存string、int或float。
eladidan打败了我,我不知道如何删除答案。