Variable id mapping

Started by
2 comments, last by Vanderry 9 years, 2 months ago

Hey guys!

I frequently encounter situations where I want to map variables in C++ with data in scripts or xml-files. It feels most intuitive to associate them with string ids and so far I have done the parsing either by using templates such as:

template <class T>
struct NamedVariable
{
const char* name;
T* variable;
};
And supply functions with one name but different parameter lists (making the compiler figure out which one to use).
Or, I would add a datatype enumerator to the structure and manually specify the type:
struct NamedVariable
{
enum Type { Type_Integer, Type_Float, Type_StlString, etc... };
const char* name;
Type type;
void* variable;
};

Is any of these methods preferable or risky beyond my understanding (I have the most distaste for the void* casting), or might there be another way? I seem to remember one could paste snippets of C-like code on these forums before, hope you'll excuse the crude format. Thank you for your time!

- David

Advertisement

Another suggestion is to store the value as string and perform a lexical cast on demand. In that case, you don't have to determine the type of the data in the parser. For example, is the quoted string "42" supposed to be an integer, a floating point value without a decimal part, or an actual string that just happens to contain numbers? If your parser can always determine that, then that's fine, but maybe it's more useful if the user determines what the type of a certain named variable should be.

struct NamedVariable
{
    std::string name;
    std::string value;
 
    template<typename T>
    T get() {
        std::stringstream ss(value);
        T v;
        ss >> v;
        return v;
    }
};

You can also specialize this for, for example, T=std::string so you just return the value instead of passing it through a string stream object.

The benefit of this approach is that you can read your named variables and query them as many different types. You string "42" will be returned as the integer value 42 if you ask for an integer, the floating point value 42.0 if you ask for a float, and the string "42" if you ask for a string, and so on. Any type that can be read from a text stream can be stored and parsed.

Since this is about a limited number of known types a boost::variant or something similar might be applicable as well.

Thank you both! I had not considered either of the alternatives. I am not overly familiar with Boost, but it seems to have a trick for most problems imaginable. The stringstream solution is super elegant so I think I will explore that first. Again, much obliged :)

This topic is closed to new replies.

Advertisement