简体   繁体   中英

C++ specialization of operator[] in unordered_map

I have been using unordered_map<int, myObject> with myObject* pointers to the objects in the unordered map. This has worked for a while, but I recently dicovered that I wrongly assumed that the memory location of myObject added to the unordered map would always remain the same.

I can solve the problem by using unordered_map<int, myObject*> and new and delete when adding and removing elements from the unordered map.

Since I have quite some code I would not want to add new and delete every place in the code where I am modifying the unordered map, I would rather try to overload the unordered_map::operator[] and unordered_map::erase() such that the usage of new and delete would happen transparently and I would not have to change my existing code. unordered_map::operator[] could then return a reference to the myObject itself rather than the pointer.

I have tried to inherit unordered_map but I am not sure how I should add the template argument list:

using namespace std;

template<class _Kty,
class _Ty,
class _Hasher = hash<_Kty>,
class _Keyeq = equal_to<_Kty>,
class _Alloc = allocator<pair<const _Kty, _Ty> > >
class  my_unordered_map : public unordered_map<_Umap_traits<_Kty, _Ty,
_Uhash_compare<_Kty, _Hasher, _Keyeq>, _Alloc, false> >
{

};

But I am getting errors such as:

error C2976: 'std::unordered_map' : too few template arguments
error C2955: 'std::unordered_map' : use of class template requires template argument list

Then I realized it might be possible to add a specialization to std when using the myObject* type with unordered_map , but I am not sure if it is even possible to overload the operator[] with a specialization.

I apprechiate any help I could get, thank you!

Edit:

I have now created a template <class mapped_type> class with an unordered_map<int, mapped_type*> as an internal structure. The operator[] was fairly straightforward to include:

template <class mapped_type> class MyMap {
public:
    std::unordered_map<int, mapped_type*> internal_map;

    mapped_type& operator[](int&& _Keyval)
    {   // find element matching _Keyval or insert with default mapped
        mapped_type*& ptr = internal_map[_Keyval];
        if (ptr == nullptr) ptr = new mapped_type();
        return *ptr;
    }
}

void erase(const int& _Keyval)
{   // erase and count all that match _Keyval
    mapped_type* ptr = internal_map[_Keyval];
    if (ptr) delete ptr;
    internal_map.erase(_Keyval);
}

void clear()
{   // erase all
    internal_map.clear();
}

Now the problem is the erase methods (default methods are included in std::_Hash ). I do not really need an iterator so I guess the best way might be to use the operator[] method first to find the entry and then use delete before removing it from the internal_map , or do you have any other ideas that might be more suitable?

Edit: Added suggestion for erase. This makes sense right?

To inherit from std::unordered_map it is sufficient to use

template <class T,class V> 
class MyMap : public unordered_map<T, V>

if its ok for you to use the std allocator and hash function. But beware, that there isn't a virtual destructor in the standard containers.

Anyway, what you want to do in the end sounds to me like you want to have an intrusive container. If so, then there is this related SO question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM