2017-12-18 174 views
-2

我想在C++中为std::map实现类似maplistner的东西。所以当在std::map中添加或更新密钥时,它应该触发一个函数或对象。std :: map操作的触发器

应该为:

class MapListener : public std::map 
    { 

    // ----- MapListener methods--- 

    public: 
     // Invoked when a map entry has been inserted.   
      virtual void entryInserted(); 

     // Invoked when a map entry has been updated.   
      virtual void entryUpdated(); 

     // Invoked when a map entry has been removed. 
      virtual void entryDeleted(); 
    }; 

任何帮助将不胜感激。

感谢

+0

你将不得不超负荷其功能插入,更新或删除条目。 –

+5

你确定你需要这个吗? C++不是Java。 – DeiDei

+3

为什么'MapListener'继承自'std :: map'?!? – user463035818

回答

2

解决方案

(我不主张你应该这样做,只是展示了如何做到这一点,因为这听起来非常像X-Y的问题对我来说)。

template<class Key, class T, class Compare = std::less<Key>> 
class EventMap final 
{ 
public: 

    EventMap(): data_{} 
    {} 

    // std::map::insert looks like this: 
    // std::pair<iterator,bool> insert(const value_type& value); 

    using insert_callback = void (const value_type& inserted); 

    void on_insert(insert_callback* cb) 
    { 
     on_insert_ = cb; 
    } 

    // wrapped insert: 
    void insert(const value_type& value) 
    { 
     data_.insert(value); 
     if(on_insert_) 
      (*on_insert_)(value); 
    } 

    // TODO: add similar code for other methods w/ callbacks 
private: 
    std::map<Key, T, Compare> data_; 
    insert_callback *on_insert_ = nullptr; 
}; 

客户端回调:

auto on_insertion(const auto& kv) 
{ 
    std::cout << "inserted: " << kv.first << ", " << kv.second << "\n"; 
} 

int main() 
{ 
    EventMap<std::string, std::string> map; 
    map.on_insert(&on_insertion); 
    map.insert({"123", 123}); // will call on_insertion after inserting 
} 
+0

谢谢你。我明白了。 – Guru

0

你绝对希望在你的类定义: public std::map,因为再有就是没有保存所有的修改的方法的希望包含地图。

你会找到的是,你有一个类型的客户端,包含事件处理程序,另一种类型包装map并委托每个动作,并调用相关的处理函数。

您将无法在很多地方map将努力利用这一点,因为通过迭代器,看看修改值operator[]你不得不使用代理为您reference成员。因此,您的iteratorconst_iterator成员不满足ForwardIterator(和BidirectionalIterator)。因此,您不满足Container(和AssociativeContainer)。

作为替代不是一个Container,你可以改为具有的std::pair<const Key, const Value>value_type,并且只要求修改的发生是“擦除 - 修改 - 插入”序列。

0

对于公然拆解@utnapistim解决方案,我表示歉意,但原文不会编译。不过我觉得很有意思,想分享工作版本:

#include <iostream> 
#include <string> 
#include <map> 

template<class Key, class T, class Compare = std::less<Key>> 
class EventMap final 
{ 
public: 

    EventMap() : data_{} 
    {} 

    // std::map::insert looks like this: 
    // std::pair<iterator,bool> insert(const value_type& value); 

    using insert_callback = void(const std::pair<const Key, T> &inserted); 
    using erase_callback = void(const Key &key); 

    void on_insert(insert_callback* icb) 
    { 
     on_insert_ = icb; 
    } 

    void on_erase(erase_callback *ecb) 
    { 
     on_erase_ = ecb; 
    } 

    // wrapped insert: 
    void insert(const std::pair<const Key, T>&value) 
    { 
     data_.insert(value); 
     if (on_insert_) 
      (*on_insert_)(value); 
    } 

    // wrapped erase: 
    void erase(const Key &key) 
    { 
     data_.erase(key); 
     if (on_erase_) 
      (*on_erase_)(key); 
    } 

    // TODO: add similar code for other methods w/ callbacks 

private: 
    std::map<const Key, T, Compare> data_; 
    insert_callback *on_insert_ = nullptr; 
    erase_callback *on_erase_ = nullptr; 
}; 


int main() 
{ 

    EventMap<const std::string, std::string> map; 

    auto on_insert_fn = [](std::pair<const std::string, std::string> const &kv) 
    { 
     std::cout << "inserted: " << kv.first << ", " << kv.second << "\n"; 
    }; 

    auto on_erase_fn = [](const std::string &key) 
    { 
     std::cout << "erased: " << key << "\n"; 
    }; 

    map.on_insert(on_insert_fn); 
    map.insert({ "123", "456" }); // will call on_insert_fn after inserting 
    map.insert({ "786", "101112" }); // will call on_insert_fn after inserting 

    map.on_erase(on_erase_fn); 
    map.erase("123"); // will call on_erase_fn after erasing 

    system("pause"); 
    return 0; 
} 

enter image description here

+0

谢谢你。 – Guru