#ifndef CHAISCRIPT_FUNCTION_SIGNATURE_HPP #define CHAISCRIPT_FUNCTION_SIGNATURE_HPP #include namespace chaiscript::dispatch::detail { template struct Function_Params { }; template struct Function_Signature { using Param_Types = Params; using Return_Type = Ret; constexpr static const bool is_object = IsObject; constexpr static const bool is_member_object = IsMemberObject; constexpr static const bool is_noexcept = IsNoExcept; template constexpr Function_Signature(T &&) noexcept {} constexpr Function_Signature() noexcept = default; }; // Free functions template Function_Signature(Ret (*f)(Param...))->Function_Signature>; template Function_Signature(Ret (*f)(Param...) noexcept)->Function_Signature, true>; // no reference specifier template Function_Signature(Ret (Class::*f)(Param...) volatile)->Function_Signature, false, true>; template Function_Signature(Ret (Class::*f)(Param...) volatile noexcept)->Function_Signature, true, true>; template Function_Signature(Ret (Class::*f)(Param...) volatile const)->Function_Signature, false, true>; template Function_Signature(Ret (Class::*f)(Param...) volatile const noexcept)->Function_Signature, true, true>; template Function_Signature(Ret (Class::*f)(Param...))->Function_Signature, false, true>; template Function_Signature(Ret (Class::*f)(Param...) noexcept)->Function_Signature, true, true>; template Function_Signature(Ret (Class::*f)(Param...) const)->Function_Signature, false, true>; template Function_Signature(Ret (Class::*f)(Param...) const noexcept)->Function_Signature, true, true>; // & reference specifier template Function_Signature(Ret (Class::*f)(Param...) volatile &)->Function_Signature, false, true>; template Function_Signature(Ret (Class::*f)(Param...) volatile &noexcept)->Function_Signature, true, true>; template Function_Signature(Ret (Class::*f)(Param...) volatile const &)->Function_Signature, false, true>; template Function_Signature(Ret (Class::*f)(Param...) volatile const &noexcept)->Function_Signature, true, true>; template Function_Signature(Ret (Class::*f)(Param...) &)->Function_Signature, false, true>; template Function_Signature(Ret (Class::*f)(Param...) & noexcept)->Function_Signature, true, true>; template Function_Signature(Ret (Class::*f)(Param...) const &)->Function_Signature, false, true>; template Function_Signature(Ret (Class::*f)(Param...) const &noexcept)->Function_Signature, true, true>; // && reference specifier template Function_Signature(Ret (Class::*f)(Param...) volatile &&)->Function_Signature, false, true>; template Function_Signature(Ret (Class::*f)(Param...) volatile &&noexcept)->Function_Signature, true, true>; template Function_Signature(Ret (Class::*f)(Param...) volatile const &&)->Function_Signature, false, true>; template Function_Signature(Ret (Class::*f)(Param...) volatile const &&noexcept)->Function_Signature, true, true>; template Function_Signature(Ret (Class::*f)(Param...) &&)->Function_Signature, false, true>; template Function_Signature(Ret (Class::*f)(Param...) && noexcept)->Function_Signature, true, true>; template Function_Signature(Ret (Class::*f)(Param...) const &&)->Function_Signature, false, true>; template Function_Signature(Ret (Class::*f)(Param...) const &&noexcept)->Function_Signature, true, true>; template Function_Signature(Ret(Class::*f))->Function_Signature, true, true, true>; // primary template handles types that have no nested ::type member: template> struct has_call_operator : std::false_type { }; // specialization recognizes types that do have a nested ::type member: template struct has_call_operator> : std::true_type { }; template auto function_signature(const Func &f) { if constexpr (has_call_operator::value) { return Function_Signature< typename decltype(Function_Signature{ &std::decay_t::operator() })::Return_Type, typename decltype(Function_Signature{ &std::decay_t::operator() })::Param_Types, decltype(Function_Signature{ &std::decay_t::operator() })::is_noexcept, false, false, true>{}; } else { return Function_Signature{ f }; } } }// namespace chaiscript::dispatch::detail #endif