diff --git a/include/chaiscript/dispatchkit/callable_traits.hpp b/include/chaiscript/dispatchkit/callable_traits.hpp deleted file mode 100644 index 0dc92416..00000000 --- a/include/chaiscript/dispatchkit/callable_traits.hpp +++ /dev/null @@ -1,107 +0,0 @@ -// This file is distributed under the BSD License. -// See "license.txt" for details. -// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) -// http://www.chaiscript.com - -#ifndef CHAISCRIPT_CALLABLE_TRAITS_HPP_ -#define CHAISCRIPT_CALLABLE_TRAITS_HPP_ - -#include - -namespace chaiscript { - namespace dispatch { - namespace detail { - - template - struct Constructor - { - template - constexpr Class operator()(Inner&& ... inner) const { - return Class(std::forward(inner)...); - } - }; - - template - struct Const_Caller - { - constexpr explicit Const_Caller(Ret (Class::*t_func)(Param...) const) : m_func(t_func) {} - - template - constexpr Ret operator()(const Class &o, Inner&& ... inner) const { - return (o.*m_func)(std::forward(inner)...); - } - - Ret (Class::*m_func)(Param...) const; - }; - - template - struct Fun_Caller - { - constexpr explicit Fun_Caller(Ret( * t_func)(Param...) ) : m_func(t_func) {} - - template - constexpr Ret operator()(Inner&& ... inner) const { - return (m_func)(std::forward(inner)...); - } - - Ret(*m_func)(Param...); - }; - - template - struct Caller - { - constexpr explicit Caller(Ret (Class::*t_func)(Param...)) : m_func(t_func) {} - - template - constexpr Ret operator()(Class &o, Inner&& ... inner) const { - return (o.*m_func)(std::forward(inner)...); - } - - Ret (Class::*m_func)(Param...); - }; - - template - struct Arity - { - }; - - template - struct Arity - { - static const size_t arity = sizeof...(Params); - }; - - - template - struct Function_Signature - { - }; - - template - struct Function_Signature - { - typedef Ret Return_Type; - typedef Ret (Signature)(Params...); - }; - - template - struct Function_Signature - { - typedef Ret Return_Type; - typedef Ret (Signature)(Params...); - }; - - - template - struct Callable_Traits - { - typedef typename Function_Signature::Signature Signature; - typedef typename Function_Signature::Return_Type Return_Type; - }; - } - } -} - -#endif - diff --git a/include/chaiscript/dispatchkit/function_call.hpp b/include/chaiscript/dispatchkit/function_call.hpp index 1980f35c..796003bf 100644 --- a/include/chaiscript/dispatchkit/function_call.hpp +++ b/include/chaiscript/dispatchkit/function_call.hpp @@ -18,7 +18,6 @@ #include "boxed_cast.hpp" #include "function_call_detail.hpp" #include "proxy_functions.hpp" -#include "callable_traits.hpp" namespace chaiscript { class Boxed_Value; @@ -32,6 +31,15 @@ namespace chaiscript { namespace dispatch { + namespace detail + { + template + constexpr auto arity(Ret (*)(Param...)) noexcept + { + return sizeof...(Param); + } + } + /// Build a function caller that knows how to dispatch on a set of functions /// example: /// std::function f = @@ -43,7 +51,7 @@ namespace chaiscript { const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(), [](const Const_Proxy_Function &f) { - return f->get_arity() == -1 || size_t(f->get_arity()) == chaiscript::dispatch::detail::Arity::arity; + return f->get_arity() == -1 || size_t(f->get_arity()) == detail::arity(static_cast(nullptr)); }); if (!has_arity_match) { diff --git a/include/chaiscript/dispatchkit/function_signature.hpp b/include/chaiscript/dispatchkit/function_signature.hpp new file mode 100644 index 00000000..11c780a4 --- /dev/null +++ b/include/chaiscript/dispatchkit/function_signature.hpp @@ -0,0 +1,124 @@ +#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>; + + template + Function_Signature(Func &&) -> 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 + >; +} + +#endif diff --git a/include/chaiscript/dispatchkit/proxy_constructors.hpp b/include/chaiscript/dispatchkit/proxy_constructors.hpp index 10b72cf5..3ccdcdf7 100644 --- a/include/chaiscript/dispatchkit/proxy_constructors.hpp +++ b/include/chaiscript/dispatchkit/proxy_constructors.hpp @@ -19,11 +19,12 @@ namespace chaiscript { namespace detail { - template Proxy_Function build_constructor_(Class (*)(Params...)) { - auto call = dispatch::detail::Constructor(); + auto call = [](auto && ... param){ + return Class(std::forward(param)...); + }; return Proxy_Function( chaiscript::make_shared>(call)); diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 8fcffb28..b2383ce1 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -664,7 +664,7 @@ namespace chaiscript protected: Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { - return detail::call_func(detail::Function_Signature(), m_f, params, t_conversions); + return detail::call_func(static_cast(nullptr), m_f, params, t_conversions); } private: @@ -716,7 +716,7 @@ namespace chaiscript protected: Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { - return detail::call_func(detail::Function_Signature(), m_f.get(), params, t_conversions); + return detail::call_func(static_cast(nullptr), m_f.get(), params, t_conversions); } diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index 8db9b509..e24ebc92 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -21,7 +21,6 @@ #include "boxed_value.hpp" #include "handle_return.hpp" #include "type_info.hpp" -#include "callable_traits.hpp" namespace chaiscript { class Type_Conversions_State; @@ -91,7 +90,7 @@ namespace chaiscript template - Ret call_func(const chaiscript::dispatch::detail::Function_Signature &, + Ret call_func(Ret (*)(Params...), std::index_sequence, const Callable &f, const std::vector ¶ms, const Type_Conversions_State &t_conversions) { @@ -105,7 +104,7 @@ namespace chaiscript /// if any unboxing fails the execution of the function fails and /// the bad_boxed_cast is passed up to the caller. template - Boxed_Value call_func(const chaiscript::dispatch::detail::Function_Signature &sig, const Callable &f, + Boxed_Value call_func(Ret (*sig)(Params...), const Callable &f, const std::vector ¶ms, const Type_Conversions_State &t_conversions) { if constexpr (std::is_same_v) { diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index e660790d..07445375 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -15,9 +15,54 @@ #include "bind_first.hpp" #include "proxy_functions.hpp" +#include "function_signature.hpp" namespace chaiscript { + namespace dispatch::detail + { + template + Param1 get_first_param(Function_Params, Obj &&obj) + { + return static_cast(std::forward(obj)); + } + + template + auto make_callable_impl(Func &&func, Function_Signature, Is_Noexcept, Is_Member, Is_MemberObject, Is_Object>) + { + if constexpr (Is_MemberObject) { + // we now that the Param pack will have only one element, so we are safe expanding it here + return Proxy_Function(chaiscript::make_shared...>>(std::forward(func))); + } else if constexpr (Is_Member) { + auto call = [func = std::forward(func)](auto && obj, auto && ... param) noexcept(Is_Noexcept) -> decltype(auto) { + return (( get_first_param(Function_Params{}, obj).*func )(std::forward(param)...)); + }; + return Proxy_Function( + chaiscript::make_shared>(std::move(call)) + ); + } else { + return Proxy_Function( + chaiscript::make_shared>>(std::forward(func)) + ); + } + } + + // this version peels off the function object itself from the function signature, when used + // on a callable object + template + auto make_callable(Func &&func, Function_Signature, Is_Noexcept, false, false, true>) + { + return make_callable_impl(std::forward(func), Function_Signature, Is_Noexcept, false, false, true>{}); + } + + template + auto make_callable(Func &&func, Function_Signature, Is_Noexcept, Is_Member, Is_MemberObject, false> fs) + { + return make_callable_impl(std::forward(func), fs); + } + } /// \brief Creates a new Proxy_Function object from a free function, member function or data member /// \param[in] t Function / member to expose @@ -40,85 +85,12 @@ namespace chaiscript /// /// \sa \ref adding_functions template - Proxy_Function fun(const T &t) + Proxy_Function fun(T &&t) { - typedef typename dispatch::detail::Callable_Traits::Signature Signature; - - return Proxy_Function( - chaiscript::make_shared>(t)); + return dispatch::detail::make_callable(std::forward(t), dispatch::detail::Function_Signature{t}); } - template - Proxy_Function fun(Ret (*func)(Param...)) - { - auto fun_call = dispatch::detail::Fun_Caller(func); - - return Proxy_Function( - chaiscript::make_shared>(fun_call)); - - } - - template - Proxy_Function fun(Ret (Class::*t_func)(Param...) const) - { - auto call = dispatch::detail::Const_Caller(t_func); - - return Proxy_Function( - chaiscript::make_shared>(call)); - } - - template - Proxy_Function fun(Ret (Class::*t_func)(Param...)) - { - auto call = dispatch::detail::Caller(t_func); - - return Proxy_Function( - chaiscript::make_shared>(call)); - - } - - template::value>::type*/> - Proxy_Function fun(T Class::* m /*, typename std::enable_if::value>::type* = 0*/ ) - { - return Proxy_Function(chaiscript::make_shared>(m)); - } - -// only compile this bit if noexcept is part of the type system -// -#if __cpp_noexcept_function_type >= 201510 - template - Proxy_Function fun(Ret (*func)(Param...) noexcept) - { - auto fun_call = dispatch::detail::Fun_Caller(func); - - return Proxy_Function( - chaiscript::make_shared>(fun_call)); - - } - - template - Proxy_Function fun(Ret (Class::*t_func)(Param...) const noexcept) - { - auto call = dispatch::detail::Const_Caller(t_func); - - return Proxy_Function( - chaiscript::make_shared>(call)); - } - - template - Proxy_Function fun(Ret (Class::*t_func)(Param...) noexcept) - { - auto call = dispatch::detail::Caller(t_func); - - return Proxy_Function( - chaiscript::make_shared>(call)); - - } -#endif - - - /// \brief Creates a new Proxy_Function object from a free function, member function or data member and binds the first parameter of it /// \param[in] t Function / member to expose @@ -145,6 +117,7 @@ namespace chaiscript } + }