触发std :: map操作

时间:2017-12-18 13:24:10

标签: c++ stl

我想在{+ 1}}的c ++中实现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();
    };

任何帮助将不胜感激。

由于

3 个答案:

答案 0 :(得分: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
}

答案 1 :(得分:0)

你绝对希望在你的班级定义中有: public std::map,因为那时没有希望保持所有的方式修改包含的地图。

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

您无法在map可以使用的许多地方使用此功能,以便通过迭代器查看对值的修改,operator[]您将被迫使用代理reference成员。因此,您的iteratorconst_iterator成员不满足ForwardIterator(和BidirectionalIterator)。因此,您不满足Container(和AssociativeContainer)。

作为不是Container的替代方案,您可以改为value_type std::pair<const Key, const Value>,并且只需要使用&#34; erase-modify-insert&进行修改#34;序列

答案 2 :(得分: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