C ++ Custom Enum Struct for reading INI files

I am trying to create an Enum that has a string label and value and I am planning on using that to read files from an ini file.

For example, in an ini file, I can have values ​​of type double

, int

or string

, preceded by a tag / value name:

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

      

When I read a tag from a file, it comes as string

, so I just want to have std::set

that stores all my values ​​... when I read the tag, I can just compare it against EnumType

, and if it matches the tag, I check the type and do the correct conversion ( atoi or just use a string, etc.).

For instance:

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:

  • Can you guys tell me the best solutions? I'm not sure if I'm trying to be too smart for myself, or if this is a really viable solution.

  • If my solution is acceptable, then someone will tell me how can I declare a set std::set<EnumType<...>>

    so that it can take on any type (int, double, string) without me actually knowing what type the enumeration will be for the value?

If you have the code then it will be GREAT! :)

0


a source to share


2 answers


If you have a limited and very stable set of types, then you can use Boost.Variant . If you add support for new types later, you better forget about this method. In this situation, a solution based on Boost.Any or a couple of lines would be better.

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

      

Another question: "How will these values ​​be used later?" If you are going to pass "SomeInteger" to work while accepting an int, you still need to run code similar to:



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

      

This approach works best if you have a consistent handling of a 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 );

      

+1


a source


Have you looked at Boost.Any ? It should do what you want (and if you need to roll yourself, you can look at the source for clues).



+1


a source







All Articles