typeid() Object-Oriented Design Alternative

c++, collections, oop, typeid

Solution

This is a perfect fit for template specialization:

template<>
void MyMaps::addKey<string>(const string& key)
{       
    stringFields.insert(pair<string, string>(key, string()));
}

template<>
void MyMaps::addKey<int>(const int& key)
{   
    intFields.insert(pair<string, int>(key, int()));;
}

template<>
void MyMaps::addKey<float>(const float& key)
{   
    floatFields.insert(pair<string, float>(key, float()));
}

EDIT: For syntax/more info about template specialization read: Template Specialization and Partial Template Specialization

Or better yet, if boost is an option and if the keys are unique for all 3 maps and you have 3 different maps just to be able to store them, then consider using `boost::variant`:

typedef boost::variant<string, int, float> ValueType;

class MyMap
{

public:
    typedef std::map<std::string, ValueType> MapType;
    template<typename T> void addKey(const std::string& key, T &val)
    {
        ValueType varVal= val;
        allFields.insert(MapType::value_type(key, varVal));
    }

private:

    MapType allFields;                              
};

Problem

I have the following class using 3 different maps: keys are always strings, while values may be strings, integers or floats. ``` class MyMaps { public: template<typename T> void addKey(const std::string& key); void addValue(const std::string& key, const std::string& value); void addValue(const std::string& key, int value); void addValue(const std::string& key, float value); private: std::map<std::string, std::string> stringFields; std::map<std::string, int> intFields; std::map<std::string, float> floatFields; }; ``` The `addValue()` functions simply add a new pair to the related map. What I'm working on is the `addKey()` template function: ``` /** Add only a key, the related value is a default one and is specified by template parameter T. */ template<typename T> void MyMaps::addKey(const string& key) { if (typeid(T) == typeid(string)) { stringFields.insert(pair<string, string>(key, string())); } else if (typeid(T) == typeid(int)) { intFields.insert(pair<string, int>(key, int()));; } else if (typeid(T) == typeid(float)) { floatFields.insert(pair<string, float>(key, float())); } } ``` Basically, I'm using `template` and `typeid()` because I don't like this alternative that relies on type-within-function-name: ``` void MyMaps::addStringKey(const string& key) { stringFields.insert(pair<string, string>(key, string())); } void MyMaps::addIntKey(const string& key) { intFields.insert(pair<string, int>(key, int())); } void MyMaps::addFloatKey(const string& key) { floatFields.insert(pair<string, float>(key, float())); } ``` The first `addKey()` version seems working, but I'm wondering if there is a more elegant solution. Maybe I'm missing some Object-Oriented design concept that could be helpful in this case? Thanks in advance.

Original source