用于INI文件阅读器的C ++ Custom Enum Struct

时间:2009-05-12 22:07:35

标签: c++ templates enums switch-statement ini

我正在尝试创建一个带有字符串标签和值的枚举,我打算用它来读取ini文件中的内容。

例如,在ini文件中,我可能会有一些doubleintstring类型值,前面是值的标记/名称:

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;
    }
};

我有几个问题:

  1. 你能告诉我更好的解决方案吗?我不确定我是否想要为自己的利益而过于聪明,或者这是否真的是一个可行的解决方案。

  2. 如果我的解决方案可以接受,那么任何人都可以告诉我如何声明一组std::set<EnumType<...>>以便它可以接受任何类型(int,double,string)而我实际上不知道哪种类型enum将用于值?

  3. 如果你有任何代码,那就太棒了! :)

2 个答案:

答案 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 );