#pragma once #include #include namespace rx { template class FunctionRef; template class FunctionRef { void *context = nullptr; RT (*invoke)(void *, ArgsT...) = nullptr; public: constexpr FunctionRef() = default; template constexpr FunctionRef(T &&object) requires requires(ArgsT... args) { RT(object(args...)); } : context( const_cast> *>(&object)), invoke(+[](void *context, ArgsT... args) -> RT { return (*reinterpret_cast(context))(std::move(args)...); }) {} template constexpr RT operator()(InvokeArgsT &&...args) const requires requires(void *context) { invoke(context, std::forward(args)...); } { return invoke(context, std::forward(args)...); } constexpr explicit operator bool() const { return invoke != nullptr; } constexpr bool operator==(std::nullptr_t) const { return invoke == nullptr; } constexpr auto operator<=>(const FunctionRef &) const = default; }; } // namespace rx