我正在尝试创建一个带有字符串标签和值的枚举,我打算用它来读取ini文件中的内容。
例如,在ini文件中,我可能会有一些double
,int
或string
类型值,前面是值的标记/名称:
SomeFloat = 0.5
SomeInteger = 5
FileName = ../Data/xor.csv
当我从文件中读取标记时,它以string
形式出现,所以我只想让std::set
保留所有值...当我读取标记时可以将它与EnumType
进行比较,如果匹配标签,那么我将检查类型并进行正确的转换(atoi或只使用字符串等)
例如:
EnumType<int> someInteger;
someInteger.label = "SomeInteger";
someInteger.type = INT;
std::set<EnumType> myValues;
//
// populate the set
myValues.insert(someInteger);
//
void ProcessTagAndValue(const std::string &tag, const std::string &value)
{
switch(myValues[tag].type)
{
case INT:
myValues[tag].value = atoi(value);
break;
case DOUBLE:
//
break;
case STRING:
myValues[tag].value = value;
break;
default:
break;
}
}
enum ValueType{INT,DOUBLE,STRING];
template <class T>
struct EnumType{
std::string label;
ValueType type;
T value;
bool operator==(const EnumType &other) const {
return this->label == other.label;
}
bool operator==(const T& other ) const
{
return this->value == other;
}
T& operator=(const T& p)
{
value = p;
return value;
}
EnumType& operator=(const EnumType& p)
{
if (this != &p) { // make sure not same object
this->label = p.label;
this->value = p.value;
}
return *this;
}
};
我有几个问题:
你能告诉我更好的解决方案吗?我不确定我是否想要为自己的利益而过于聪明,或者这是否真的是一个可行的解决方案。
如果我的解决方案可以接受,那么任何人都可以告诉我如何声明一组std::set<EnumType<...>>
以便它可以接受任何类型(int,double,string)而我实际上不知道哪种类型enum将用于值?
如果你有任何代码,那就太棒了! :)
答案 0 :(得分:1)
你看过Boost.Any了吗?它应该做你想要的(如果你需要自己动手,你可以查看提示的来源)。
答案 1 :(得分:1)
如果您拥有有限且非常稳定的类型集,则可以使用Boost.Variant。 如果您稍后要添加对新类型的支持,那么最好忘记这个方法。在这种情况下,基于Boost.Any或字符串对的解决方案会更好。
typedef boost::variant<int, double, std::string> ValueType;
struct EnumType {
std::string label;
ValueType value;
};
另一个问题是:“这些价值如何在以后使用?”如果你打算将“SomeInteger”传递给函数,接受int,你仍然需要运行类似于的代码:
acceptInt( get<int>( v.value ) ); // get may throw
当您对固定类型集进行统一处理时,此方法更有效:
class processValue : public boost::static_visitor<>
{
public:
void operator()(int i) const
{
acceptInt( i );
}
void operator()(double d) const
{
acceptDouble( d );
}
void operator()(const std::string & str) const
{
acceptString( str );
}
};
boost::apply_visitor( processValue(), v.value );