#ifndef CANVAS_CALLABLE_HPP #define CANVAS_CALLABLE_HPP #include #include namespace ce { /* Base interface template for a member function pointer object */ template struct HiddenCallableBase { virtual ~HiddenCallableBase() = default; virtual Return call(Args... args) const = 0; virtual bool equals(HiddenCallableBase const &other) const; }; template bool HiddenCallableBase::equals(HiddenCallableBase const &other) const { return &other == this; } /* Hidden component of a Callable, specialized for a specific target object */ template struct HiddenCallable : public HiddenCallableBase { typedef Return (Target::*Signature)(Args...); HiddenCallable(Target *target, Signature function); Target *target{nullptr}; Signature function{nullptr}; virtual void call(Args...) const override; virtual bool equals(HiddenCallableBase const &other) const override; }; template bool HiddenCallable::equals(HiddenCallableBase const &other) const { HiddenCallable const *cast{dynamic_cast const *>(&other)}; return cast != nullptr && &other == this && cast->target == this->target && cast->function == this->function; } template HiddenCallable::HiddenCallable(Target *target, Signature function) : target{target}, function{function} {} template void HiddenCallable::call(Args... args) const { std::invoke(this->function, this->target, args...); } /* Class for referring to a callable pointer to a member function. */ template class Callable { public: std::shared_ptr const> hidden; template static Callable make(Target *target, Return (Target::*function)(Args...)); Return call(Args... args); }; template template Callable Callable::make(Target *target, Return (Target::*function)(Args...)) { Callable callable; callable.hidden = std::make_unique>(target, function); return callable; }; template Return Callable::call(Args... args) { return this->hidden->call(args...); } template bool operator==(Callable const &lhs, Callable const &rhs) { return lhs.hidden->equals(*rhs.hidden.get()); } } #endif // !CANVAS_CALLABLE_HPP