diff --git a/CMakeLists.txt b/CMakeLists.txt index 122ad9d..e29a426 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,6 +118,10 @@ IF(BUILD_TESTING) target_link_libraries(functor_creation_test ${DYNAMIC_LOADER} ${Boost_LIBRARIES} ${READLINE_LIB}) add_test(NAME Functor_Creation_Test COMMAND functor_creation_test) + add_executable(functor_cast_test unittests/functor_cast_test.cpp) + target_link_libraries(functor_cast_test ${DYNAMIC_LOADER} ${Boost_LIBRARIES} ${READLINE_LIB}) + add_test(NAME Functor_Cast_Test COMMAND functor_cast_test) + add_library(test_module MODULE src/test_module.cpp) target_link_libraries(test_module ${Boost_LIBRARIES}) diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index 2f056c7..160ec7e 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -19,13 +19,13 @@ namespace chaiscript { namespace detail { - // Cast_Helper helper classes + // Cast_Helper_Inner helper classes /** - * Generic Cast_Helper, for casting to any type + * Generic Cast_Helper_Inner, for casting to any type */ template - struct Cast_Helper + struct Cast_Helper_Inner { typedef typename boost::reference_wrapper::type > Result_Type; @@ -51,10 +51,10 @@ namespace chaiscript }; /** - * Cast_Helper for casting to a const & type + * Cast_Helper_Inner for casting to a const & type */ template - struct Cast_Helper + struct Cast_Helper_Inner { typedef typename boost::reference_wrapper::type > Result_Type; @@ -80,10 +80,10 @@ namespace chaiscript }; /** - * Cast_Helper for casting to a const * type + * Cast_Helper_Inner for casting to a const * type */ template - struct Cast_Helper + struct Cast_Helper_Inner { typedef const Result * Result_Type; @@ -109,10 +109,10 @@ namespace chaiscript }; /** - * Cast_Helper for casting to a * type + * Cast_Helper_Inner for casting to a * type */ template - struct Cast_Helper + struct Cast_Helper_Inner { typedef Result * Result_Type; @@ -128,10 +128,10 @@ namespace chaiscript }; /** - * Cast_Helper for casting to a & type + * Cast_Helper_Inner for casting to a & type */ template - struct Cast_Helper + struct Cast_Helper_Inner { typedef typename boost::reference_wrapper Result_Type; @@ -147,10 +147,10 @@ namespace chaiscript }; /** - * Cast_Helper for casting to a boost::shared_ptr<> type + * Cast_Helper_Inner for casting to a boost::shared_ptr<> type */ template - struct Cast_Helper > + struct Cast_Helper_Inner > { typedef typename boost::shared_ptr Result_Type; @@ -161,10 +161,10 @@ namespace chaiscript }; /** - * Cast_Helper for casting to a boost::shared_ptr type + * Cast_Helper_Inner for casting to a boost::shared_ptr type */ template - struct Cast_Helper > + struct Cast_Helper_Inner > { typedef typename boost::shared_ptr Result_Type; @@ -180,10 +180,10 @@ namespace chaiscript }; /** - * Cast_Helper for casting to a const boost::shared_ptr<> & type + * Cast_Helper_Inner for casting to a const boost::shared_ptr<> & type */ template - struct Cast_Helper &> + struct Cast_Helper_Inner &> { typedef typename boost::shared_ptr Result_Type; @@ -194,10 +194,10 @@ namespace chaiscript }; /** - * Cast_Helper for casting to a const boost::shared_ptr & type + * Cast_Helper_Inner for casting to a const boost::shared_ptr & type */ template - struct Cast_Helper &> + struct Cast_Helper_Inner &> { typedef typename boost::shared_ptr Result_Type; @@ -215,10 +215,10 @@ namespace chaiscript /** - * Cast_Helper for casting to a Boxed_Value type + * Cast_Helper_Inner for casting to a Boxed_Value type */ template<> - struct Cast_Helper + struct Cast_Helper_Inner { typedef const Boxed_Value & Result_Type; @@ -229,10 +229,10 @@ namespace chaiscript }; /** - * Cast_Helper for casting to a const Boxed_Value & type + * Cast_Helper_Inner for casting to a const Boxed_Value & type */ template<> - struct Cast_Helper + struct Cast_Helper_Inner { typedef const Boxed_Value & Result_Type; @@ -241,12 +241,22 @@ namespace chaiscript return ob; } }; + + /** + * The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner + */ + template + struct Cast_Helper + { + typedef typename Cast_Helper_Inner::Result_Type Result_Type; + + static Result_Type cast(const Boxed_Value &ob) + { + return Cast_Helper_Inner::cast(ob); + } + }; } - } - - #endif - diff --git a/include/chaiscript/dispatchkit/boxed_pod_value.hpp b/include/chaiscript/dispatchkit/boxed_pod_value.hpp index e13133e..870a275 100644 --- a/include/chaiscript/dispatchkit/boxed_pod_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_pod_value.hpp @@ -251,8 +251,21 @@ namespace chaiscript return Boxed_POD_Value(ob); } }; - } + + /** + * Cast_Helper for converting from Boxed_Value to Boxed_POD_Value + */ + template<> + struct Cast_Helper + { + typedef Boxed_POD_Value Result_Type; + static Result_Type cast(const Boxed_Value &ob) + { + return Boxed_POD_Value(ob); + } + }; + } } diff --git a/include/chaiscript/dispatchkit/function_call.hpp b/include/chaiscript/dispatchkit/function_call.hpp index 2e3f14e..746f476 100644 --- a/include/chaiscript/dispatchkit/function_call.hpp +++ b/include/chaiscript/dispatchkit/function_call.hpp @@ -15,6 +15,9 @@ #include "proxy_functions.hpp" #include "function_call_detail.hpp" + +#include + namespace chaiscript { /** @@ -66,6 +69,65 @@ namespace chaiscript return functor(boxed_cast(bv)); } + namespace detail{ + /** + * Cast helper to handle automatic casting to const boost::function & + */ + template + struct Cast_Helper &> + { + typedef boost::function Result_Type; + + static Result_Type cast(const Boxed_Value &ob) + { + if (ob.get_type_info().bare_equal(user_type())) + { + return functor(ob); + } else { + return Cast_Helper_Inner &>::cast(ob); + } + } + }; + + /** + * Cast helper to handle automatic casting to boost::function + */ + template + struct Cast_Helper > + { + typedef boost::function Result_Type; + + static Result_Type cast(const Boxed_Value &ob) + { + if (ob.get_type_info().bare_equal(user_type())) + { + return functor(ob); + } else { + return Cast_Helper_Inner >::cast(ob); + } + } + }; + + /** + * Cast helper to handle automatic casting to const boost::function + */ + template + struct Cast_Helper > + { + typedef boost::function Result_Type; + + static Result_Type cast(const Boxed_Value &ob) + { + if (ob.get_type_info().bare_equal(user_type())) + { + return functor(ob); + } else { + return Cast_Helper_Inner >::cast(ob); + } + } + }; + } + } #endif diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 007cbbd..124f714 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -119,6 +119,7 @@ namespace chaiscript && (ti.bare_equal(user_type()) || ti.bare_equal(bv.get_type_info()) || dynamic_cast_converts(ti, bv.get_type_info()) + || bv.get_type_info().bare_equal(user_type >()) ) ) ) diff --git a/unittests/functor_cast_test.cpp b/unittests/functor_cast_test.cpp new file mode 100644 index 0000000..1f6f7ec --- /dev/null +++ b/unittests/functor_cast_test.cpp @@ -0,0 +1,25 @@ +#include + +double test_call(const boost::function &f, int val) +{ + return f(val); +} + +int main() +{ + + chaiscript::ChaiScript chai; + + chai.add(chaiscript::fun(&test_call), "test_call"); + + chai.eval("def func(i) { return i * 3.5; };"); + double d = chai.eval("test_call(func, 3)"); + + if (d == 3 * 3.5) + { + return EXIT_SUCCESS; + } else { + return EXIT_FAILURE; + } + +}