Thanks to Blue Man (Source message)
Code snippet
struct FancyDelegates
{
struct DelegateBase
{
virtual ~DelegateBase() = default;
};
template<typename T> struct TDelegate : public DelegateBase
{
using TFunction = std::function<void(T*)>;
TFunction Function; TDelegate() = default;
TDelegate(TFunction InFunction) : Function(std::move(InFunction)) { }
};
template<typename T> std::function<void(T*)>& GetDelegate()
{
const std::string TypeName = typeid(T).name();
if (auto It = Delegates.find(TypeName); It != Delegates.end())
{
return static_cast<TDelegate<T>*>(It->second.get())->Function;
}
auto Delegate = std::make_shared<TDelegate<T>>();
Delegates[TypeName] = Delegate;
return Delegate->Function;
}
template<typename T> void Subscribe(std::function<void(T*)> InFunction)
{
auto& Delegate = GetDelegate<T>();
Delegate = std::move(InFunction);
}
template<typename T> void Execute(T* InObject)
{
auto& Delegate = GetDelegate<T>();
if (Delegate)
{
Delegate(InObject);
}
}
private: std::unordered_map<std::string, std::shared_ptr<DelegateBase>> Delegates;
};