1

最小限のマルチキャスト デリゲート クラスをコーディングしたいと考えています。そのインターフェースは、デリゲートを呼び出すための operator() と、関数、メソッド、ラムダ、ファンクターなどの呼び出し可能な型を追加/削除するための operator+=/operator-= の 3 つの演算子で構成されます。

除去のために関数ターゲットのアドレスを比較する必要があるところに operator-= を実装するのに問題があります。これが私がこれまでに思いついたものです(私はg ++ 4.6.3を使用しています):

#include <functional>
#include <list>

template <typename ... EventArgs>
class Event
{
public:
    typedef std::function<void (EventArgs...)> EventHandler;

    Event() = default;
    ~Event() = default;
    Event(const Event &) = delete;
    Event & operator=(const Event &) = delete;

    void operator()(EventArgs... eventArgs)
    {
        for (auto eventHandler : m_eventHandlers)
            eventHandler(eventArgs...);
    }

    Event & operator+=(const EventHandler &eventHandler)
    {
        m_eventHandlers.push_back(eventHandler);
        return *this;
    }

    Event & operator-=(const EventHandler &eventHandler)
    {
        m_eventHandlers.remove_if([&](const EventHandler &_eventHandler)
        {
            return false; // TODO: Compare event handlers
        });

        return *this;
    }

private:
    std::list<EventHandler> m_eventHandlers;
};

operator-= は、TODO 行を次のコードに置き換えると、関数に対して機能します。

return * eventHandler.template target<void (*)(EventArgs...)>() ==
       *_eventHandler.template target<void (*)(EventArgs...)>();

最小限の例を次に示します。

void eventHandler() { /* ... */ }

Event<> event;
event += eventHandler;
event();
event -= eventHandler; // works

ただし、 std::function.target() が null ポインターを返すため、他の呼び出し可能な型ではクラッシュします。明らかに、テンプレートはもう適合しないため、Event::operator-= をテンプレート化しようとしましたが、「不完全な型」のため、最も呼び出し可能な型に対してコンパイルされません。

template<typename T>
Event & operator-=(const T &eventHandler)
{
    m_eventHandlers.remove_if([&](const EventHandler &_eventHandler)
    {
        if (_eventHandler.template target<T>() != null_ptr) // <- ERROR
        {
            // ...
        }
    });

    return *this;
}    

target() のテンプレート パラメータとして T* も試しましたが、行き詰まりました。呼び出し可能な型を正しく比較できるジェネリック operator-= をコーディングすることは可能ですか?

前もって感謝します!

4

1 に答える 1

3

問題は、比較演算子andstd::function<>がサポートされていないことです。にはその説明があります。==!=boost::function

1 つの解決策は、関数をマップまたは整数をキーとするハッシュに格納することです。登録すると、その整数キーが返されます。登録を解除するには、キーを渡す必要があります。例:

typedef int handler_id_t;
handler_id_t add(const EventHandler &eventHandler);
void del(handler_id_t);
于 2012-05-16T08:17:10.940 に答える