C++ INI 文件读取器的自定义枚举结构

发布于 2024-07-19 09:00:09 字数 1946 浏览 9 评论 0 原文

我正在尝试创建一个具有字符串标签和值的枚举,我计划使用它从 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> 以便它可以接受任何类型( int、double、string),而我实际上不知道枚举将用于该值的类型?

如果您有任何代码,那就太好了! :)

I'm trying to create an Enum that has a string label and a value and I plan to use this to read stuff from an ini file.

For example in the ini file I might have some double, int or string type values preceded by the tag/name of the value:

SomeFloat = 0.5
SomeInteger = 5
FileName = ../Data/xor.csv

When I read the tag from a file it comes in as a string, so I'd just like to have std::set that keeps all of my values... when I read the tag I can just compare it against the EnumType and if matches the label then I will check the type and do the proper conversion (atoi or just use the string, etc.)

For example:

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

I have several questions:

  1. Can you guys tell me any better solutions? I'm not sure if I'm trying to be too clever for my own good, or if this is really a viable solution.

  2. If my solution is acceptable, then can anybody tell me how I can declare a set of std::set<EnumType<...>> so that it can accept any type (int, double, string) without me actually knowing which type the enum is going to be using for the value?

If you have any code, then it would be GREAT! :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

冷…雨湿花 2024-07-26 09:00:10

如果您的类型集有限且非常稳定,那么 Boost。可以使用变体
如果您稍后要添加对新类型的支持,那么最好忘记此方法。 在这种情况下,解决方案基于 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 );

If you have limited and very stable set of types, then Boost.Variant may be used.
If you going to add support for new types later, then better forget about this method. In this situation solution, based on Boost.Any, or pair of strings will be better.

typedef boost::variant<int, double, std::string> ValueType;
struct EnumType {
std::string label;
ValueType value;
};

Another question is: "How these values will be used later?" If you are going to pass "SomeInteger" to function, accepting int, you still have to run code similar to:

acceptInt( get<int>( v.value ) ); // get may throw

This approach works better when you have uniform processing of fixed set of types:

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 );
定格我的天空 2024-07-26 09:00:10

您看过 Boost.Any 吗? 它应该做你想做的事(如果你需要自己动手,你可以查看源代码以获取提示)。

Have you looked at Boost.Any? It should do what you want (and if you need to roll your own, you can peek at the source for hints).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文