#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::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