2017-12-18 12 views
-2

std::mapのC++で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をラップしてすべてのアクションを委譲し、関連するハンドラ関数を呼び出すタイプの2つがあります。

あなたはイテレータを介して値の変更を確認するよう、mapが働くだろう多くの場所でこれを使用することができなくなりますoperator[]あなたがあなたのreferenceメンバーのためのプロキシを使用することを余儀なくされています。したがって、iteratorconst_iteratorのメンバーはForwardIterator(およびBidirectionalIterator)を満たしていません。したがって、あなたはContainer(およびAssociativeContainer)を満足しません。

Containerされていない代わりに、あなたの代わりにstd::pair<const Key, const Value>value_typeを持っている、と単純に変更が「消去・修正・挿入」シーケンスで起こることを必要とする可能性があります。

0

@napistimソリューションを大量にリッピングしてしまったことをお詫びしますが、オリジナルはコンパイルされません。それでも私はそれが面白いと作業バージョンを共有したいと思います:

#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

関連する問題