#pragma once #include namespace geode::modifier { template struct MemberFunc { template using with = FunctionType Class::*; }; template struct ConstMemberFunc { template using with = FunctionType Class::*; }; // why template struct ConstMemberFunc { using FunctionType = Return(Parameters...) const; template using with = FunctionType Class::*; }; template struct StaticFunc { using type = FunctionType*; }; /** * The ~unevaluated~ function that gets the appropriate * version of a function type from its return, parameters, and classes. * * nvm its no more unevaluated */ template constexpr auto substitute(typename MemberFunc::template with function) { return function; } template constexpr auto substitute(typename ConstMemberFunc::template with function ) { return function; } template constexpr auto substitute(typename StaticFunc::type function) { return function; } /** * An UUID system that generates an unique comparable * value for every instance. Internally used for comparing member * function pointers. */ template struct FunctionUUID { private: constexpr static void function() {} public: constexpr static inline void (*value)() = &FunctionUUID::function; }; /** * A type trait that removes the class from a member function pointer. */ template struct RemoveClass { using type = Func; }; template struct RemoveClass { using type = Return(Params...); }; template struct RemoveClass { using type = Return(Params...); }; template using RemoveClassType = typename RemoveClass::type; /** * A helper struct that allows for checking if two function pointers * are the same or different. */ struct Unique { using ValueType = void(*)(...); static constexpr auto nvalue = static_cast(nullptr); template struct Impl { static void unique(...) {}; static constexpr auto value = &unique; }; template <> struct Impl { static constexpr auto value = nvalue; }; template static constexpr auto value = Impl::value; /** * Checks if two function pointers are the same. If their types are * different, returns false. */ template static constexpr auto same() { if (!std::is_same_v, RemoveClassType>) return false; auto v1 = value; auto v2 = value; if (v1 == nvalue) return false; if (v2 == nvalue) return false; return v1 == v2; } /** * Checks if two function pointers are different. If their types are * different, returns false. */ template static constexpr auto different() { if (!std::is_same_v, RemoveClassType>) return false; auto v1 = value; auto v2 = value; if (v1 == nvalue) return false; if (v2 == nvalue) return false; return v1 != v2; } }; /** * Helps resolving an overloaded function pointer to a specific function using * its parameter types as the hint. */ template struct Resolve { template static constexpr auto func(Return(*ptr)(std::type_identity_t...)) { return ptr; } template static constexpr auto func(Return(Class::*ptr)(std::type_identity_t...)) { return ptr; } template static constexpr auto func(Return(Class::*ptr)(std::type_identity_t...) const) { return ptr; } static constexpr auto func(...) { return Unique::nvalue; } }; /** * A specialization for giving the variadic types as a single type with the * function type. The return type is ignored. */ template struct Resolve : Resolve { using Resolve::func; }; /** * A type trait that checks if a class has a function called "constructor". */ template concept HasConstructor = requires { &Class::constructor; }; /** * A type trait that checks if a class has a function called "destructor". */ template concept HasDestructor = requires { &Class::destructor; }; template struct AsStaticType { using type = FunctionType; }; template struct AsStaticType { using type = Return(*)(Class*, Params...); }; template struct AsStaticType { using type = Return(*)(Class const*, Params...); }; }