最小限のマルチキャスト デリゲート クラスをコーディングしたいと考えています。そのインターフェースは、デリゲートを呼び出すための 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-= をコーディングすることは可能ですか?
前もって感謝します!