/* * Copyright (c) Atmosphère-NX * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. * * This program is distributed in the hope it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #pragma once #include #include namespace ams::util { template class IFunction; namespace impl { template struct GetIFunctionTypeForObject; template struct GetIFunctionTypeForObject { using Type = R(Args...); }; template struct GetIFunctionTypeForObject { using Type = R(Args...); }; template struct GetIFunctionType; template struct GetIFunctionType { using Type = R(Args...); }; template struct GetIFunctionType : public GetIFunctionType{}; template struct GetIFunctionType> : public GetIFunctionType{}; template struct GetIFunctionType : public GetIFunctionTypeForObject{}; template class Function; template class Function::value && !std::is_final::value)>::type> final : public IFunction { private: F m_f; public: constexpr explicit Function(F f) : m_f(std::move(f)) { /* ... */} constexpr virtual R operator()(Args... args) const override final { return m_f(std::forward(args)...); } }; template class Function::value && !std::is_final::value>::type> final : public IFunction, private F { public: constexpr explicit Function(F f) : F(std::move(f)) { /* ... */} constexpr virtual R operator()(Args... args) const override final { return static_cast(*this).operator()(std::forward(args)...); } }; template constexpr ALWAYS_INLINE auto MakeIFunctionExplicitly(F f) { using FunctionType = ::ams::util::impl::Function::type>; return FunctionType{ std::move(f) }; } template constexpr ALWAYS_INLINE auto MakeIFunctionExplicitly(R T::*f) { return MakeIFunctionExplicitly(std::mem_fn(f)); } } template class IFunction { protected: constexpr virtual ~IFunction() = default; public: constexpr virtual R operator()(Args... args) const = 0; template static constexpr ALWAYS_INLINE auto Make(F f) { return ::ams::util::impl::MakeIFunctionExplicitly(std::move(f)); } }; template::value>::type> constexpr ALWAYS_INLINE auto MakeIFunction(F f) { static_assert(!std::is_member_pointer::value); return IFunction::type>::Type>::Make(std::move(f)); } }