109 lines
No EOL
1.9 KiB
C++
109 lines
No EOL
1.9 KiB
C++
#pragma once
|
|
|
|
#include <functional>
|
|
#include <algorithm>
|
|
#include <vector>
|
|
#include <typeindex>
|
|
|
|
struct Listener
|
|
{
|
|
virtual bool isValid()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
virtual void call() {}
|
|
|
|
virtual std::type_index get_type()
|
|
{
|
|
return typeid(Listener);
|
|
}
|
|
};
|
|
|
|
template<class T>
|
|
struct BindedListener : public Listener
|
|
{
|
|
std::function<void()> func;
|
|
T* caller;
|
|
|
|
bool isValid() override
|
|
{
|
|
return caller != nullptr;
|
|
}
|
|
|
|
void call() override
|
|
{
|
|
return func();
|
|
}
|
|
|
|
std::type_index get_type() override
|
|
{
|
|
return typeid(T);
|
|
}
|
|
};
|
|
|
|
struct FunctionListener : public Listener
|
|
{
|
|
std::function<void()> func;
|
|
|
|
bool isValid() override
|
|
{
|
|
return static_cast<bool>(func);
|
|
}
|
|
|
|
void call() override
|
|
{
|
|
return func();
|
|
}
|
|
};
|
|
|
|
template<class T>
|
|
class EventDispatcher;
|
|
|
|
template<class... Args>
|
|
class EventDispatcher<void(Args...)>
|
|
{
|
|
public:
|
|
void Register(std::function<void(Args...)> func)
|
|
{
|
|
auto listener = new FunctionListener;
|
|
listener->func = func;
|
|
|
|
m_listeners.push_back(listener);
|
|
}
|
|
|
|
template<class T>
|
|
void Unregister(T* t)
|
|
{
|
|
for(size_t i = 0; i < m_listeners.size(); i++)
|
|
{
|
|
if(std::type_index(typeid(T)) == m_listeners[i]->get_type())
|
|
m_listeners.erase(m_listeners.begin() + i);
|
|
}
|
|
}
|
|
|
|
template<class R, class F>
|
|
void Register(F&& f, R* r)
|
|
{
|
|
auto listener = new BindedListener<R>;
|
|
listener->caller = r;
|
|
listener->func = std::bind(f, r);
|
|
|
|
m_listeners.push_back(listener);
|
|
}
|
|
|
|
void operator()(Args&&... args)
|
|
{
|
|
//dispatch
|
|
for(size_t i = 0; i < m_listeners.size(); i++)
|
|
{
|
|
Listener* listener = m_listeners[i];
|
|
|
|
if(listener->isValid())
|
|
listener->call();
|
|
}
|
|
}
|
|
|
|
private:
|
|
std::vector<Listener*> m_listeners;
|
|
}; |