diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 8e45977..6d0fd99 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -35,6 +35,10 @@ #define CHAISCRIPT_HAS_THREAD_LOCAL #endif +#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ >= 6) +#define CHAISCRIPT_GCC_4_6 +#endif + #if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || defined(CHAISCRIPT_MSVC) || defined(__llvm__) #define CHAISCRIPT_OVERRIDE override #else diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index a77376f..a98124b 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -53,6 +53,113 @@ namespace chaiscript { namespace detail { + /** + * Used by Proxy_Function_Impl to return a list of all param types + * it contains. + */ + template + std::vector build_param_type_list(Ret (*)(Params...)) + { + /// \note somehow this is responsible for a large part of the code generation + return { user_type(), user_type()... }; + } + + +#ifdef CHAISCRIPT_GCC_4_6 + /// \todo REMOVE THIS WHEN WE DROP G++4.6 + + // Forward declaration + template + struct Try_Cast; + + template + struct Try_Cast + { + static void do_try(const std::vector ¶ms, size_t generation, const Type_Conversions &t_conversions) + { + boxed_cast(params[generation], &t_conversions); + Try_Cast::do_try(params, generation+1, t_conversions); + } + }; + + // 0th case + template<> + struct Try_Cast<> + { + static void do_try(const std::vector &, size_t, const Type_Conversions &) + { + } + }; + + + /** + * Used by Proxy_Function_Impl to determine if it is equivalent to another + * Proxy_Function_Impl object. This function is primarily used to prevent + * registration of two functions with the exact same signatures + */ + template + bool compare_types_cast(Ret (*)(Params...), + const std::vector ¶ms, const Type_Conversions &t_conversions) + { + try { + Try_Cast::do_try(params, 0, t_conversions); + } catch (const exception::bad_boxed_cast &) { + return false; + } + + return true; + } + + template + struct Call_Func + { + + template + static Ret do_call(const std::function &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]); + } + }; + + template + struct Call_Func + { +#ifdef CHAISCRIPT_MSVC +#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, + const std::vector &, const Type_Conversions &t_conversions, InnerParams &&... innerparams) + { + return f(boxed_cast(std::forward(innerparams), &t_conversions)...); + } +#ifdef CHAISCRIPT_MSVC +#pragma warning(pop) +#endif + }; + + /** + * Used by Proxy_Function_Impl to perform typesafe execution of a function. + * The function attempts to unbox each parameter to the expected type. + * 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, + const std::vector ¶ms, const Type_Conversions &t_conversions) + { + if (params.size() == sizeof...(Params)) + { + return Call_Func::do_call(f, params, t_conversions); + } + + throw exception::arity_error(static_cast(params.size()), sizeof...(Params)); + } + +#else + template struct Indexes { @@ -70,16 +177,6 @@ namespace chaiscript typedef Indexes indexes; }; - /** - * Used by Proxy_Function_Impl to return a list of all param types - * it contains. - */ - template - std::vector build_param_type_list(Ret (*)(Params...)) - { - /// \note somehow this is responsible for a large part of the code generation - return { user_type(), user_type()... }; - } /** @@ -135,6 +232,8 @@ namespace chaiscript throw exception::arity_error(static_cast(params.size()), sizeof...(Params)); } +#endif + } }