Search code examples
c++stlgeneric-programmingtypeidtypeinfo

how to create a container that takes one object of each kind?


I tried to create a container for posible metadata that can be attached to my objects. I can guarantee that there will be at most one object af each kind attached to my class but there is no limit for object of different type to attach. for example I can't attach two instances of wordInfo to an object but instances of wordInfo and phraseInfo classes can be attached to an object at a same time. here is what I did so far to get it done.

class object
{
    std::map <std::type_info, object*> mMetaData;
    public:
    inline void attachMetaData(object* pData)
    {
        mMetaData[typeid(*pData)] = pData;
    }
    template <class T> inline std::enableif<std::is_base_of<object,T>::value, T*>::type getMetaData()
    {
        if (mMetaData.find(typeid(T)) == mMetaData.end())
            return NULL;
        else
            return mMetaData[typeid(T)];
    }
    template <class T> inline std::enableif<std::is_base_of<object,T>::value, void>::type detachMetaData()
    {
        mMetaData.erase(typeid(T));
    }
}

the code above had a compile error : less operator was not defined for std::type_info so I defined some less class specifically for std::type_info and pass it as the third template parameter of map class like this:

struct typeinfoless
{
    bool operator()(std::type_info& left, std::type_info& right)
    {
        return left.hash() < right.hash();
    }
}
std::map <std::type_info, object*, typeinfoless> mMetaData;

but then I encountered another error which I don't know how to resolve, std::type_info has private constructor and even private copy constructor, so I can't even derive some class from it. any idea how can I fix this problem? or any other possible way to create my object class?


Solution

  • Create a wrapper class for std::type_info, similar to the following:

    class TypeWrapper
    {
        private const std::type_info &mInfo;
        public TypeWrapper(const std::type_info &info) : mInfo(info)
        {
        }
        // Functions required by a key into a std::map.
    };
    

    Use TypeWrapper as your key into your map.