#ifndef NALL_FUNCTION_HPP #define NALL_FUNCTION_HPP #include namespace nall { template class function; template class function { struct container { virtual R operator()(P... p) const = 0; virtual container* copy() const = 0; virtual ~container() {} }; container* callback = nullptr; struct global : container { R (*function)(P...); R operator()(P... p) const { return function(forward

(p)...); } container* copy() const { return new global(function); } global(R (*function)(P...)) : function(function) {} }; template struct member : container { R (C::*function)(P...); C* object; R operator()(P... p) const { return (object->*function)(forward

(p)...); } container* copy() const { return new member(function, object); } member(R (C::*function)(P...), C* object) : function(function), object(object) {} }; template struct lambda : container { mutable L object; R operator()(P... p) const { return object(forward

(p)...); } container* copy() const { return new lambda(object); } lambda(const L& object) : object(object) {} }; //value = true if R L::operator()(P...) exists template struct is_compatible { template static const typename is_same().operator()(declval

()...))>::type exists(T*); template static const false_type exists(...); static constexpr bool value = decltype(exists(0))::value; }; public: explicit operator bool() const { return callback; } R operator()(P... p) const { return (*callback)(forward

(p)...); } void reset() { if(callback) { delete callback; callback = nullptr; } } function& operator=(const function& source) { if(this != &source) { if(callback) { delete callback; callback = nullptr; } if(source.callback) callback = source.callback->copy(); } return *this; } function() = default; function(const function& source) { operator=(source); } function(void* function) { if(function) callback = new global((R (*)(P...))function); } function(R (*function)(P...)) { callback = new global(function); } template function(R (C::*function)(P...), C* object) { callback = new member(function, object); } template function(R (C::*function)(P...) const, C* object) { callback = new member((R (C::*)(P...))function, object); } template>> function(const L& object) { callback = new lambda(object); } ~function() { if(callback) delete callback; } }; } #endif