enum CNULLer { CNULL }; // Deprecated, use plain Null template class Function : Moveable> { struct WrapperBase { Atomic refcount; virtual Res Execute(ArgTypes... args) = 0; WrapperBase() { refcount = 1; } virtual ~WrapperBase() {} }; template struct Wrapper : WrapperBase { F fn; virtual Res Execute(ArgTypes... args) { return fn(args...); } Wrapper(F&& fn) : fn(pick(fn)) {} }; template struct Wrapper2 : WrapperBase { Function l; F fn; virtual Res Execute(ArgTypes... args) { l(args...); return fn(args...); } Wrapper2(const Function& l, F&& fn) : l(l), fn(pick(fn)) {} Wrapper2(const Function& l, const F& fn) : l(l), fn(fn) {} }; WrapperBase *ptr; static void Free(WrapperBase *ptr) { if(ptr && AtomicDec(ptr->refcount) == 0) delete ptr; } void Copy(const Function& a) { ptr = a.ptr; if(ptr) AtomicInc(ptr->refcount); } void Pick(Function&& src) { ptr = src.ptr; src.ptr = NULL; } public: Function() { ptr = NULL; } Function(CNULLer) { ptr = NULL; } Function(const Nuller&) { ptr = NULL; } template Function(F fn) { ptr = new Wrapper(pick(fn)); } Function(const Function& src) { Copy(src); } Function& operator=(const Function& src) { auto b = ptr; Copy(src); Free(b); return *this; } Function(Function&& src) { Pick(pick(src)); } Function& operator=(Function&& src) { if(&src != this) { Free(ptr); ptr = src.ptr; src.ptr = NULL; } return *this; } Function Proxy() const { return [=] (ArgTypes... args) { return (*this)(args...); }; } template Function& operator<<(F fn) { if(!ptr) { Pick(pick(fn)); return *this; } WrapperBase *b = ptr; ptr = new Wrapper2(*this, pick(fn)); Free(b); return *this; } Function& operator<<(const Function& fn) { if(!ptr) { Copy(fn); return *this; } WrapperBase *b = ptr; ptr = new Wrapper2(*this, fn); Free(b); return *this; } Function& operator<<(Function&& fn) { if(!ptr) { Pick(pick(fn)); return *this; } WrapperBase *b = ptr; ptr = new Wrapper2(*this, pick(fn)); Free(b); return *this; } Res operator()(ArgTypes... args) const { return ptr ? ptr->Execute(args...) : Res(); } operator bool() const { return ptr; } void Clear() { Free(ptr); ptr = NULL; } ~Function() { Free(ptr); } friend Function Proxy(const Function& a) { return a.Proxy(); } friend void Swap(Function& a, Function& b) { UPP::Swap(a.ptr, b.ptr); } }; template using Event = Function; template using Gate = Function; template Function MemFn(Ptr object, Res (Class::*method)(ArgTypes...)) { return [=](ArgTypes... args) { return (object->*method)(args...); }; } #define THISFN(x) MemFn(this, &CLASSNAME::x)