c++stlunordered-multimap

How to have an unordered_multimap of unordered_multimaps


I was practicing through unordered_multimaps and I came across a problem of having an unordered_multimap containing another unordered_multimap.The compiler throws an error saying c++ standard does not provide hash of this type.I guess I have to write a hash function but my understanding is limited since I am new to STL.

I have already tried something like inserting a struct or another multimap to the unordered_multimap but no luck so far.

std::unordered_multimap<long,long>m_Map1;
std::unordered_multimap<CString,m_Map1>m_Map2;    //This line throws 
error
//inserting to the map
m_Map1.insert(std::pair<long,long>(10,20));
m_Map2.insert(_T("ABC"),m_Map1);
//also the compiler does not let me create an object for this map
m_Map1 m_ObjMap;    //error here as well

How should I implement this.What I am trying to achieve here is one person's Name associated with birthdate and date on which he dies.I was hoping of having the dates in one map and mapping it with name to the m_Map2.


Solution

  • Your problem is that there is no specialisation of std::hash available for CString

    Boiling the problem down to its simplest part, this will also not compile:

    std::unordered_multimap<CString , int> m_Map2;    
    

    Because std::unordered_multimap<CString, anything> requires that there exists a class std::hash<CString> which provides std::size_t operator()(CString const&) const (it also requires an implementation of std::equal_to<CString> but this is automatically available if CString supports operator==.

    You can create such a class and legally inject it into the std namespace:

    #include <unordered_map>
    #include <boost/functional/hash.hpp>  // for boost::hash_range, see below
    
    // for exposition
    struct CString
    {
        const char* data() const;
        std::size_t length() const;
    
        bool operator==(CString const& other) const;
    };
    
    namespace std
    {
        // specialise std::hash for type ::CString
        template<> struct hash<::CString>
        {
            std::size_t operator()(CString const& arg) const
            {
                std::size_t seed = 0;
    
                // perform whatever is your hashing function on arg here
                // accumulating the hash into the variable seed
                // in this case, we're doing it in terms of boost::hash_range
    
                auto first = arg.data();
                auto last = first + arg.length();
                boost::hash_range(seed, first, last);
    
                return seed;
            }
        };
    }
    
    std::unordered_multimap<CString , int> m_Map2;