Phase one of getting rid of std::function usage

This commit is contained in:
Jason Turner
2015-05-22 09:30:42 -06:00
parent 33a929ef93
commit 03143a9f83
4 changed files with 102 additions and 13 deletions

View File

@@ -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<typename T>
struct Function_Signature
{
typedef T Signature;
};
template<typename T>
struct Callable_Traits
{
template<typename Ret, typename ... Param>
static Ret deduce_ret_type(Ret (T::*)(Param...) const);
template<typename Ret, typename ... Param>
static Function_Signature<Ret (Param...)> 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

View File

@@ -549,6 +549,45 @@ namespace chaiscript
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
};
/// For any callable object
template<typename Func, typename Callable>
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<Func *>(nullptr))),
m_f(std::move(f)), m_dummy_func(nullptr)
{
}
virtual ~Proxy_Function_Callable_Impl() {}
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &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<const Proxy_Function_Callable_Impl<Func, Callable> *>(&t_func) != nullptr;
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
{
typedef typename detail::Callable_Traits<Callable>::Return_Type Return_Type;
return detail::Do_Call<Return_Type>::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

View File

@@ -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<typename ... InnerParams>
static Ret do_call(const std::function<Ret (Params...)> &f,
template<typename Callable, typename ... InnerParams>
static Ret do_call(const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions, InnerParams &&... innerparams)
{
return Call_Func<Ret, count - 1, Params...>::do_call(f, params, t_conversions, std::forward<InnerParams>(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<typename ... InnerParams>
static Ret do_call(const std::function<Ret (Params...)> &f,
template<typename Callable, typename ... InnerParams>
static Ret do_call(const Callable &f,
const std::vector<Boxed_Value> &, const Type_Conversions &t_conversions, InnerParams &&... innerparams)
{
return f(boxed_cast<Params>(std::forward<InnerParams>(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<typename Ret, typename ... Params>
Ret call_func(const std::function<Ret (Params...)> &f,
template<typename Callable, typename Ret, typename ... Params>
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &, const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
{
if (params.size() == sizeof...(Params))
@@ -170,20 +171,20 @@ namespace chaiscript
template<typename Ret>
struct Do_Call
{
template<typename Fun>
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
template<typename Callable>
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
{
return Handle_Return<Ret>::handle(call_func(fun, params, t_conversions));
return Handle_Return<Ret>::handle(call_func(typename Callable_Traits<Callable>::Signature_Object(), fun, params, t_conversions));
}
};
template<>
struct Do_Call<void>
{
template<typename Fun>
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
template<typename Callable>
static Boxed_Value go(const Callable &fun, const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions)
{
call_func(fun, params, t_conversions);
call_func(typename Callable_Traits<Callable>::Signature_Object(), fun, params, t_conversions);
return Handle_Return<void>::handle();
}
};

View File

@@ -19,6 +19,7 @@ namespace chaiscript
{
namespace detail
{
template<typename T>
struct FunctionSignature
{
@@ -108,8 +109,17 @@ namespace chaiscript
template<typename T>
Proxy_Function fun(const T &t)
{
typedef typename dispatch::detail::Callable_Traits<T>::Signature Signature;
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Impl<typename dispatch::detail::FunctionSignature<decltype(dispatch::detail::to_function(t)) >::Signature>>(dispatch::detail::to_function(t)));
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Signature, T>>(t));
}
template<typename Ret, typename ... Param>
Proxy_Function fun(Ret (*func)(Param...))
{
return Proxy_Function(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Impl<typename dispatch::detail::FunctionSignature<decltype(dispatch::detail::to_function(func)) >::Signature>>(dispatch::detail::to_function(func)));
}
template<typename Ret, typename Class, typename ... Param>