Created
August 15, 2014 21:59
-
-
Save ongamex/45244796d9cc73956008 to your computer and use it in GitHub Desktop.
Events
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// variadic.cpp : Defines the entry point for the console application. | |
// | |
#include "stdafx.h" | |
#include <vector> | |
#include <memory> | |
#include <iostream> | |
#include <functional> | |
#include <algorithm> | |
template<class... Args> | |
class Event; | |
//---------------------------------------------------------------------------- | |
template<class... Args> | |
class IDelegate | |
{ | |
friend class Event<Args...>; | |
public : | |
IDelegate() : event(nullptr) {} | |
virtual ~IDelegate() {} | |
bool is_subscribed() const { return event != nullptr; } | |
Event<Args...>* get_event() const { return event; } | |
//user defined | |
virtual bool operator() (Args... args) = 0;//returns true if unsubscription will be performed | |
virtual void on_unsubscribe() {}; | |
private : | |
void subscribe(Event<Args...> *evt) {event = evt;} | |
void unsubscribe(); | |
Event<Args...> *event; | |
}; | |
//---------------------------------------------------------------------------- | |
template<class... Args> | |
class Event | |
{ | |
public : | |
typedef std::shared_ptr<IDelegate<Args...> > DelegateSptr; | |
~Event() | |
{ | |
for(auto i: m_delegates) if(i) i.reset(); | |
m_delegates.clear(); | |
} | |
void occur(Args... args) | |
{ | |
auto new_end = std::remove_if(begin(m_delegates), end(m_delegates), | |
[&args...](DelegateSptr i) -> bool | |
{ | |
if (i.get() == nullptr) return true; | |
if(i->operator()(args...)) | |
{ | |
i->on_unsubscribe(); | |
return true; | |
} | |
return false; | |
} | |
); | |
m_delegates.erase(new_end, m_delegates.end()); | |
} | |
void add_delegate(DelegateSptr delegate) | |
{ | |
delegate->subscribe(this); | |
m_delegates.push_back(delegate); | |
} | |
std::vector<DelegateSptr> m_delegates; | |
}; | |
template<class... Args> | |
void IDelegate<Args...>::unsubscribe() { event->remove_delegate(this); event = nullptr; } | |
//---------------------------------------------------------------------------- | |
// | |
//---------------------------------------------------------------------------- | |
// | |
//---------------------------------------------------------------------------- | |
enum class DamageType | |
{ | |
Physical, | |
Magic, | |
Nature | |
}; | |
//---------------------------------------------------------------------------- | |
// | |
//---------------------------------------------------------------------------- | |
struct TotalDamageDone: public IDelegate<int, DamageType> | |
{ | |
static int damage; | |
virtual bool operator() (int dmg, DamageType type) | |
{ | |
damage += dmg; | |
return false; | |
} | |
}; | |
int TotalDamageDone::damage = 0; | |
//---------------------------------------------------------------------------- | |
// | |
//---------------------------------------------------------------------------- | |
struct TotalMagicDamageDone: public IDelegate<int, DamageType> | |
{ | |
static int damage; | |
virtual bool operator() (int dmg, DamageType type) | |
{ | |
if(type == DamageType::Magic) | |
damage += dmg; | |
return false; | |
} | |
}; | |
int TotalMagicDamageDone::damage = 0; | |
//---------------------------------------------------------------------------- | |
// | |
//---------------------------------------------------------------------------- | |
struct IsNatureDamageDone: public IDelegate<int, DamageType> | |
{ | |
bool Destroyed = false; | |
~IsNatureDamageDone() | |
{ | |
std::cout <<"Destroyed\n"; | |
Destroyed = true; | |
} | |
bool condition = false; | |
virtual bool operator() (int dmg, DamageType type) | |
{ | |
if(type == DamageType::Nature) condition = true; | |
return condition; | |
} | |
virtual void on_unsubscribe() | |
{ | |
std::cout << "Achievement unlocked: Use an ability that does Nature Damage!\n"; | |
} | |
}; | |
int _tmain(int argc, _TCHAR* argv[]) | |
{ | |
Event<int, DamageType> take_damage_event; | |
take_damage_event.add_delegate(std::make_shared<TotalMagicDamageDone>()); | |
take_damage_event.add_delegate(std::make_shared<TotalDamageDone>()); | |
take_damage_event.add_delegate(std::make_shared<IsNatureDamageDone>()); | |
take_damage_event.occur(10, DamageType::Physical); | |
take_damage_event.occur(15, DamageType::Magic); | |
take_damage_event.occur(1, DamageType::Nature); | |
std::cout << "Total damage delt: " << TotalDamageDone::damage << std::endl; | |
std::cout << "Total magic damage delt: " << TotalMagicDamageDone::damage << std::endl; | |
std::cin.get(); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment