Search code examples
c++containersstd

Is there any way to hook insertion and deletion operations for the std containers?


Let's say, we are going to subclass the std::map and we need to catch all insertions and deletions to/from the container. For example, in order to save some application-specific information about the keys present in the container.

What's the easiest way to do this, if at all possible?

Probably, the most obvious way to do this is to override all methods and operators that perform the insertion and deletion. But I think, something may be easily lost sight of on this way, isn't it?


Solution

  • There is no way to do that in the general case. Inheritance is not a good idea because std::map is not polymorphic and no virtual dispatch will happen when you use a pointer to a map. You might as well use a simple wrapper class at that point and save yourself a lot of hassle:

    #include <iostream>
    #include <map>
    
    template <class Key, class Value> 
    struct Map {
    private:
      std::map<Key, Value> _data;
    
    public:
      template <class Y, class T> 
      void insert(Y &&key, T &&val) {
    
        std::cout << "[" << key << "] = " << val << "\n";
    
        _data.insert_or_assign(std::forward<Y>(key), std::forward<T>(val));
      }
    
      void remove(Key const &key) {
        auto const it = _data.find(key);
    
        if (it == _data.end())
          return;
    
        std::cout << "[" << key << "] -> removed\n";
    
        _data.erase(it);
      }
    
      Value *get(Key const &key) {
        auto const it = _data.find(key);
    
        if (it == _data.end())
          return nullptr;
    
        return &it->second;
      }
    };
    
    int main() {
      Map<int, char const *> map;
      map.insert(10, "hello");
      map.insert(1, "world");
      map.remove(1);
      map.remove(10);
      map.remove(999);
    }