0

現在の実験プロジェクトのために、単純なリスナー/コールバックメカニズムを構築しています。そして、私は、ポインタのベクトルのベクトルであるはずのコンテナ構造を実装することに固執しています。ルートベクトルにイベントタイプのKEYを単純に持たせたいので、この方法を選択します。たとえば、列挙型(int)の場合、このキーに、このイベントタイプで使用可能なメソッドへのポインターのベクトルを格納します。論理表現では、次のようになります。

[EVENT_TYPE_QUIT]
                 [ptr1]
                 [ptr2]
                 [ptr3]
                 [ptr4]
                 [....]
[EVENT_TYPE_HELLO]
                 [....]
                 [....]

typedef enum {
   EVENT_TYPE_QUIT,
   EVENT_TYPE_HELLO,
   ...
} EventType;

したがって、簡略化された実装は次のようになります(実際にはテンプレートですが、Tがイベントをマップできる任意のユーザータイプであると想像してください)。

class EventMapper {
    ...

    typedef void (T::*functionPtr)(); // simple pointer to T member function with no args.

    std::vector< std::vector<functionPtr> > eventCallbacks;

    void mapEvent(const EventType type, functionPtr callback) {

        // here i need to map type to callback
        // each type can have multiple callbacks
        // T can have only distinct event types as "key"

        // this i tried but doesn't work

        eventCallbacks[type].push_back(callback);

    }

    ...
}

意図した実装は次のようになります。

EventMapper<SupaDupaClass> mapper;
mapper.mapEvent(EVENT_TYPE_HELLO, &SupaDupaClass::didYouSayHello);

など..。

一意のキーの割り当てを簡単にするために、マップの代わりにベクトルを使用したいですか?ありがとうございました

4

2 に答える 2

1

私があなたのコードを正しく読んだ場合、あなたは初期化されていないエントリにアクセスしています。

まず、eventCallbacksを空のベクトルで初期化する必要があります。

eventCallbacks.assign(10、std :: vector())

于 2013-03-02T20:23:35.443 に答える
1

You can use a std::map to map the event_type to the vector of callbacks. And consider using std::function instead of function pointers for flexibility.

One possible implementation is:

#include <vector>
#include <map>
#include <functional>
#include <iostream>

enum class event_type
{
    event_one,
    event_two
};

void func1() { std::cout << "func1" << std::endl; }
class my_listener { public: void func() { std::cout << "my_listener::func" << std::endl; } };

int main()
{
    std::map<event_type, std::vector<std::function<void ()>>> m;

    my_listener lst;
    m[event_type::event_one].push_back(std::bind(&my_listener::func, lst));
    m[event_type::event_one].push_back(&func1);

    // invoke callbacks (may be used in the code that raises events)
    for(auto& kv : m)
    {
        for(auto& f : kv.second) {
            f();
        }
    }

    return 0;
}

EDIT: You might consider using Boost.Signals2 library.

于 2013-03-02T20:37:20.900 に答える