#pragma once #include #include #include namespace BAN { template class Function; template class Function { public: Function() = default; 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); } template Function(Lambda lambda) requires requires(Lambda lamda, Args&&... args) { { lambda(forward(args)...) } -> BAN::same_as; } { static_assert(sizeof(CallableLambda) <= m_size); new (m_storage) CallableLambda(lambda); } ~Function() { clear(); } Ret operator()(Args... args) const { ASSERT(*this); return reinterpret_cast(m_storage)->call(forward(args)...); } operator bool() const { for (size_t i = 0; i < m_size; i++) if (m_storage[i]) return true; return false; } void clear() { if (*this) reinterpret_cast(m_storage)->~CallableBase(); memset(m_storage, 0, m_size); } static constexpr size_t size() { return m_size; } private: struct CallableBase { virtual ~CallableBase() {} virtual Ret call(Args...) const = 0; }; struct CallablePointer : public CallableBase { CallablePointer(Ret(*function)(Args...)) : m_function(function) { } virtual Ret call(Args... args) const override { return m_function(forward(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(Args... args) const override { return (m_owner->*m_function)(forward(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(Args... args) const override { return (m_owner->*m_function)(forward(args)...); } private: const Own* m_owner = nullptr; Ret(Own::*m_function)(Args...) const = nullptr; }; template struct CallableLambda : public CallableBase { CallableLambda(Lambda lambda) : m_lambda(lambda) { } virtual Ret call(Args... args) const override { return m_lambda(forward(args)...); } private: Lambda m_lambda; }; private: static constexpr size_t m_size = sizeof(void*) * 8; alignas(CallableBase) uint8_t m_storage[m_size] { 0 }; }; }