std::unordered_map using a template class pointer as a key

I’m a beginner for cpp,and I have some codes like this:

#include <iostream>
#include <utility>
#include <map>
#include <unordered_map>


template<typename T,typename EX>
class Attachable
{
    
    static std::unordered_map<T*,Attachable<T,EX>> attachCaches;

    std::unordered_map<std::string,EX> datas;

    Attachable(T* sender):m_attachedObj(sender)
    {
    }

    bool operator==(const Attachable& other)const
    {
        return m_attachedObj == other.m_attachedObj;
    }
public:

    static Attachable<T,EX> attach(T* sender)
    {
        if(attachCaches.find(sender)==attachCaches.end())
        {
            attachCaches.insert(std::make_pair((sender),Attachable<T,EX>(sender)));
        }

        return attachCaches[(sender)];
    }


    void set(std::string key,EX properties)
    {
        datas.insert(key,properties);
    }

    EX get(std::string key)
    {
        return datas.at(key);
    }

private:
    T* m_attachedObj;
};


class Tester
{
public :
    Tester(){}
};

int main()
{
    Tester* a =new Tester();

    Attachable<Tester,std::string>::attach(a).set("test","typeOfInt");

    std::cout<< Attachable<Tester,std::string>::attach(a).get("test");

}

**When I try to compile this code , I will receive an error at ,line 952,at the function called

emplace(*_First);

**

    template <class _Iter, class _Sent>
    void _Insert_range_unchecked(_Iter _First, const _Sent _Last) {
        for (; _First != _Last; ++_First) {
            emplace(*_First);
        }
    }

I am trying to using some basic pointer like int,but this still not worked:

int* a =new int(4);

    Attachable<int,std::string>::attach(a).set("test","typeOfInt");

    std::cout<< Attachable<int,std::string>::attach(a).get("test");

>Solution :

attachCaches[(sender)] may need to default-construct an Attachabe object, if it turns out that sender is not in the map. But Attachable doesn’t provide a default constructor. Since you actually know the key is always in the map, you can implement attach this way (also more efficient, as it eliminates redundant lookups):

static Attachable<T,EX>& attach(T* sender)
{
    auto it = attachCaches.find(sender);
    if (it == attachCaches.end())
    {
        it = attachCaches.emplace(sender, Attachable<T,EX>(sender)).first;
    }

    return it->second;
}

Note also how the function now returns Attachable by reference. Your original code returned a temporary copy of the map element; then called set on that copy; then that copy was destroyed. The original in the map was never updated, so a subsequent get didn’t find the value passed to set.

Demo

Leave a Reply