#pragma once #include <Geode/DefaultInclude.hpp> #include <memory> namespace geode::utils { template <class FunctionType> class MiniFunction; template <class Ret, class... Args> class MiniFunctionStateBase { public: virtual ~MiniFunctionStateBase() = default; virtual Ret call(Args... args) const = 0; virtual MiniFunctionStateBase* clone() const = 0; }; template <class Type, class Ret, class... Args> class MiniFunctionState final : public MiniFunctionStateBase<Ret, Args...> { public: Type m_func; explicit MiniFunctionState(Type func) : m_func(std::move(func)) {} Ret call(Args... args) const override { return const_cast<Type&>(m_func)(args...); } MiniFunctionStateBase<Ret, Args...>* clone() const override { return new MiniFunctionState(*this); } }; template <class Ret, class... Args> class MiniFunction<Ret(Args...)> { public: using FunctionType = Ret(Args...); using StateType = MiniFunctionStateBase<Ret, Args...>; private: StateType* m_state; public: MiniFunction() : m_state(nullptr) {} MiniFunction(MiniFunction const& other) : m_state(other.m_state ? other.m_state->clone() : nullptr) {} MiniFunction(MiniFunction&& other) : m_state(other.m_state) { other.m_state = nullptr; } ~MiniFunction() { delete m_state; } template <class Callable> requires requires(Callable&& func, Args... args) { { func(args...) } -> std::same_as<Ret>; } MiniFunction(Callable&& func) : m_state(new MiniFunctionState<std::decay_t<Callable>, Ret, Args...>(std::forward<Callable>(func))) {} MiniFunction& operator=(MiniFunction const& other) { delete m_state; m_state = other.m_state ? other.m_state->clone() : nullptr; return *this; } MiniFunction& operator=(MiniFunction&& other) { delete m_state; m_state = other.m_state; other.m_state = nullptr; return *this; } Ret operator()(Args... args) const { return m_state->call(args...); } explicit operator bool() const { return m_state; } }; }