diff --git a/include/chaiscript/dispatchkit/callable_traits.hpp b/include/chaiscript/dispatchkit/callable_traits.hpp new file mode 100644 index 0000000..447d39c --- /dev/null +++ b/include/chaiscript/dispatchkit/callable_traits.hpp @@ -0,0 +1,39 @@ +// This file is distributed under the BSD License. +// See "license.txt" for details. +// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) +// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) +// http://www.chaiscript.com + +#ifndef CHAISCRIPT_CALLABLE_TRAITS_HPP_ +#define CHAISCRIPT_CALLABLE_TRAITS_HPP_ + +namespace chaiscript { + namespace dispatch { + namespace detail { + + template + struct Function_Signature + { + typedef T Signature; + }; + + template + struct Callable_Traits + { + + template + static Ret deduce_ret_type(Ret (T::*)(Param...) const); + + template + static Function_Signature deduce_sig_type(Ret (T::*)(Param...) const); + + typedef decltype(deduce_ret_type(&T::operator())) Return_Type; + typedef typename decltype(deduce_sig_type(&T::operator()))::Signature Signature; + typedef decltype(deduce_sig_type(&T::operator())) Signature_Object; + }; + } + } +} + +#endif + diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 39011ca..0bd8b7c 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -549,6 +549,45 @@ namespace chaiscript virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions &t_conversions) const = 0; }; + + + /// For any callable object + template + class Proxy_Function_Callable_Impl : public Proxy_Function_Impl_Base + { + public: + Proxy_Function_Callable_Impl(Callable f) + : Proxy_Function_Impl_Base(detail::build_param_type_list(static_cast(nullptr))), + m_f(std::move(f)), m_dummy_func(nullptr) + { + } + + virtual ~Proxy_Function_Callable_Impl() {} + + virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + { + return detail::compare_types_cast(m_dummy_func, vals, t_conversions); + } + + virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE + { + return dynamic_cast *>(&t_func) != nullptr; + } + + + protected: + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + { + typedef typename detail::Callable_Traits::Return_Type Return_Type; + return detail::Do_Call::go(m_f, params, t_conversions); + } + + + private: + Callable m_f; + Func *m_dummy_func; + }; + /// The standard typesafe function call implementation of Proxy_Function /// It takes a std::function<> object and performs runtime /// type checking of Boxed_Value parameters, in a type safe manner diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index b90c8d6..66e7713 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -16,6 +16,7 @@ #include "boxed_value.hpp" #include "handle_return.hpp" #include "type_info.hpp" +#include "callable_traits.hpp" namespace chaiscript { class Type_Conversions; @@ -111,8 +112,8 @@ namespace chaiscript struct Call_Func { - template - static Ret do_call(const std::function &f, + template + static Ret do_call(const Callable &f, const std::vector ¶ms, const Type_Conversions &t_conversions, InnerParams &&... innerparams) { return Call_Func::do_call(f, params, t_conversions, std::forward(innerparams)..., params[sizeof...(Params) - count]); @@ -126,8 +127,8 @@ namespace chaiscript #pragma warning(push) #pragma warning(disable : 4100) /// Disable unreferenced formal parameter warning, which only shows up in MSVC I don't think there's any way around it \todo evaluate this #endif - template - static Ret do_call(const std::function &f, + template + static Ret do_call(const Callable &f, const std::vector &, const Type_Conversions &t_conversions, InnerParams &&... innerparams) { return f(boxed_cast(std::forward(innerparams), &t_conversions)...); @@ -143,8 +144,8 @@ namespace chaiscript * if any unboxing fails the execution of the function fails and * the bad_boxed_cast is passed up to the caller. */ - template - Ret call_func(const std::function &f, + template + Ret call_func(const chaiscript::dispatch::detail::Function_Signature &, const Callable &f, const std::vector ¶ms, const Type_Conversions &t_conversions) { if (params.size() == sizeof...(Params)) @@ -170,20 +171,20 @@ namespace chaiscript template struct Do_Call { - template - static Boxed_Value go(const std::function &fun, const std::vector ¶ms, const Type_Conversions &t_conversions) + template + static Boxed_Value go(const Callable &fun, const std::vector ¶ms, const Type_Conversions &t_conversions) { - return Handle_Return::handle(call_func(fun, params, t_conversions)); + return Handle_Return::handle(call_func(typename Callable_Traits::Signature_Object(), fun, params, t_conversions)); } }; template<> struct Do_Call { - template - static Boxed_Value go(const std::function &fun, const std::vector ¶ms, const Type_Conversions &t_conversions) + template + static Boxed_Value go(const Callable &fun, const std::vector ¶ms, const Type_Conversions &t_conversions) { - call_func(fun, params, t_conversions); + call_func(typename Callable_Traits::Signature_Object(), fun, params, t_conversions); return Handle_Return::handle(); } }; diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index 4998ede..e526de5 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -19,6 +19,7 @@ namespace chaiscript { namespace detail { + template struct FunctionSignature { @@ -108,8 +109,17 @@ namespace chaiscript template Proxy_Function fun(const T &t) { + typedef typename dispatch::detail::Callable_Traits::Signature Signature; + return Proxy_Function( - chaiscript::make_shared::Signature>>(dispatch::detail::to_function(t))); + chaiscript::make_shared>(t)); + } + + template + Proxy_Function fun(Ret (*func)(Param...)) + { + return Proxy_Function( + chaiscript::make_shared::Signature>>(dispatch::detail::to_function(func))); } template