From 35612572861815d54b3764a8a88332b206bf6f5e Mon Sep 17 00:00:00 2001 From: Bananymous Date: Mon, 16 Jan 2023 14:59:33 +0200 Subject: [PATCH] BAN: Add basic Function for function pointers and member functions --- BAN/include/BAN/Function.h | 110 +++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 BAN/include/BAN/Function.h diff --git a/BAN/include/BAN/Function.h b/BAN/include/BAN/Function.h new file mode 100644 index 00000000..c171d42a --- /dev/null +++ b/BAN/include/BAN/Function.h @@ -0,0 +1,110 @@ +#pragma once + +#include + +namespace BAN +{ + + template + class Function; + template + class Function + { + public: + Function() {} + Function(Ret(*function)(Args...)) + { + static_assert(sizeof(CallablePointer) <= m_size); + new (m_storage) CallablePointer(function); + } + template + Function(Ret(Own::*function)(Args...), Own* owner) + { + static_assert(sizeof(CallableMember) <= m_size); + new (m_storage) CallableMember(function, owner); + } + template + Function(Ret(Own::*function)(Args...) const, const Own* owner) + { + static_assert(sizeof(CallableMemberConst) <= m_size); + new (m_storage) CallableMemberConst(function, owner); + } + + Ret operator()(const Args&... args) + { + ASSERT(HasFunction()); + return ((CallableBase*)m_storage)->call(args...); + } + + bool HasFunction() const + { + for (size_t i = 0; i < m_size; i++) + if (m_storage[i]) + return true; + return false; + } + + private: + struct CallableBase + { + virtual ~CallableBase() {} + virtual Ret call(const Args&...) = 0; + }; + + struct CallablePointer : public CallableBase + { + CallablePointer(Ret(*function)(Args...)) + : m_function(function) + { } + + virtual Ret call(const Args&... args) override + { + return m_function(args...); + } + + private: + Ret(*m_function)(Args...) = nullptr; + }; + + template + struct CallableMember : public CallableBase + { + CallableMember(Ret(Own::*function)(Args...), Own* owner) + : m_owner(owner) + , m_function(function) + { } + + virtual Ret call(const Args&... args) override + { + return (m_owner->*m_function)(args...); + } + + private: + Own* m_owner = nullptr; + Ret(Own::*m_function)(Args...) = nullptr; + }; + + template + struct CallableMemberConst : public CallableBase + { + CallableMemberConst(Ret(Own::*function)(Args...) const, const Own* owner) + : m_owner(owner) + , m_function(function) + { } + + virtual Ret call(const Args&... args) override + { + return (m_owner->*m_function)(args...); + } + + private: + const Own* m_owner = nullptr; + Ret(Own::*m_function)(Args...) const = nullptr; + }; + + private: + static constexpr size_t m_size = sizeof(void*) * 4; + alignas(max_align_t) uint8_t m_storage[m_size] { 0 }; + }; + +} \ No newline at end of file