// This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_ #define CHAISCRIPT_REGISTER_FUNCTION_HPP_ #include #include "bind_first.hpp" #include "proxy_functions.hpp" #include "handle_return.hpp" #include "function_call.hpp" namespace chaiscript { /// \brief Creates a new Proxy_Function object from a free function, member function or data member /// \param[in] t Function / member to expose /// /// \b Example: /// \code /// int myfunction(const std::string &); /// class MyClass /// { /// public: /// void memberfunction(); /// int memberdata; /// }; /// /// chaiscript::ChaiScript chai; /// chai.add(fun(&myfunction), "myfunction"); /// chai.add(fun(&MyClass::memberfunction), "memberfunction"); /// chai.add(fun(&MyClass::memberdata), "memberdata"); /// \endcode /// /// \sa \ref adding_functions // // template Proxy_Function assignable_fun( std::reference_wrapper> t_func, std::shared_ptr> t_ptr, std::index_sequence) { return [t_func, t_ptr](){ class Func final : public dispatch::Assignable_Proxy_Function { public: Func(std::reference_wrapper> t_f, std::shared_ptr> t_p) : Assignable_Proxy_Function({user_type(), user_type()...}), m_f(std::move(t_f)), m_shared_ptr_holder(std::move(t_p)) { assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get()); } bool compare_types_with_cast(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return compare_types_with_cast_impl(params, t_conversions); } void assign(const std::shared_ptr &t_rhs) override { m_f.get() = dispatch::functor(t_rhs, nullptr); } protected: Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { m_f(boxed_cast(params.at(I), &t_conversions)...); return dispatch::detail::Handle_Return::handle(); } private: std::reference_wrapper> m_f; std::shared_ptr> m_shared_ptr_holder; }; return chaiscript::make_shared(t_func, t_ptr); }(); } template Proxy_Function assignable_fun( std::reference_wrapper> t_func, std::shared_ptr> t_ptr, std::index_sequence) { return [t_func, t_ptr](){ class Func final : public dispatch::Assignable_Proxy_Function { public: Func(std::reference_wrapper> t_f, std::shared_ptr> t_p) : Assignable_Proxy_Function({user_type(), user_type()...}), m_f(std::move(t_f)), m_shared_ptr_holder(std::move(t_p)) { assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get()); } bool compare_types_with_cast(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return compare_types_with_cast_impl(params, t_conversions); } void assign(const std::shared_ptr &t_rhs) override { m_f.get() = dispatch::functor(t_rhs, nullptr); } protected: Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return dispatch::detail::Handle_Return::handle(m_f(boxed_cast(params.at(I), &t_conversions)...)); } private: std::reference_wrapper> m_f; std::shared_ptr> m_shared_ptr_holder; }; return chaiscript::make_shared(t_func, t_ptr); }(); } template Proxy_Function assignable_fun( std::reference_wrapper> t_func, std::shared_ptr> t_ptr ) { return assignable_fun(std::move(t_func), std::move(t_ptr), std::make_index_sequence()); } template Proxy_Function fun(const T &t_func, void (*)(Param...), std::index_sequence) { return [t_func](){ class Func final : public dispatch::Proxy_Function_Impl_Base { public: Func(const T &func) : dispatch::Proxy_Function_Impl_Base({user_type(), user_type()...}), m_f(func) { } bool compare_types_with_cast(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return compare_types_with_cast_impl(params, t_conversions); } protected: Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { m_f(boxed_cast(params[I], &t_conversions)...); return dispatch::detail::Handle_Return::handle(); } private: T m_f; }; return chaiscript::make_shared(t_func); }(); } template Proxy_Function fun(const T &t_func, Ret (*)(Param...), std::index_sequence) { return [t_func](){ class Func final : public dispatch::Proxy_Function_Impl_Base { public: Func(const T &func) : dispatch::Proxy_Function_Impl_Base({user_type(), user_type()...}), m_f(func) { } bool compare_types_with_cast(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return compare_types_with_cast_impl(params, t_conversions); } protected: Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return dispatch::detail::Handle_Return::handle(m_f(boxed_cast(params.at(I), &t_conversions)...)); } private: T m_f; }; return chaiscript::make_shared(t_func); }(); } template Proxy_Function fun(const T &t) { typedef typename dispatch::detail::Callable_Traits::Signature Signature; Signature *f = nullptr; return fun(t, f, std::make_index_sequence::arity>()); } template Proxy_Function fun(void (*t_func)(Param...), std::index_sequence) { return [t_func](){ class Func final : public dispatch::Proxy_Function_Impl_Base { public: Func(decltype(t_func) func) : dispatch::Proxy_Function_Impl_Base({user_type(), user_type()...}), m_f(func) { } bool compare_types_with_cast(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return compare_types_with_cast_impl(params, t_conversions); } protected: Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { (*m_f)(boxed_cast(params[I], &t_conversions)...); return dispatch::detail::Handle_Return::handle(); } private: decltype(t_func) m_f; }; return chaiscript::make_shared(t_func); }(); } template Proxy_Function fun(Ret (*t_func)(Param...), std::index_sequence) { return [t_func](){ class Func final : public dispatch::Proxy_Function_Impl_Base { public: Func(decltype(t_func) func) : dispatch::Proxy_Function_Impl_Base({user_type(), user_type()...}), m_f(func) { } bool compare_types_with_cast(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return compare_types_with_cast_impl(params, t_conversions); } protected: Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return dispatch::detail::Handle_Return::handle((*m_f)(boxed_cast(params[I], &t_conversions)...)); } private: decltype(t_func) m_f; }; return chaiscript::make_shared(t_func); }(); } template Proxy_Function fun(void (Class::*t_func)(Param...) const, std::index_sequence) { return [t_func](){ class Func final : public dispatch::Proxy_Function_Impl_Base { public: Func(decltype(t_func) func) : dispatch::Proxy_Function_Impl_Base({user_type(), user_type(), user_type()...}), m_f(func) { } bool compare_types_with_cast(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return compare_types_with_cast_impl(params, t_conversions); } protected: Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { const Class &o = static_cast(boxed_cast(params[0], &t_conversions)); (o.*m_f)(boxed_cast(params[I+1], &t_conversions)...); return dispatch::detail::Handle_Return::handle(); } private: decltype(t_func) m_f; }; return chaiscript::make_shared(t_func); }(); } template Proxy_Function fun(Ret (Class::*t_func)(Param...) const, std::index_sequence) { return [t_func](){ class Func final : public dispatch::Proxy_Function_Impl_Base { public: Func(decltype(t_func) func) : dispatch::Proxy_Function_Impl_Base({user_type(), user_type(), user_type()...}), m_f(func) { } bool compare_types_with_cast(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return compare_types_with_cast_impl(params, t_conversions); } protected: Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { const Class &o = static_cast(boxed_cast(params[0], &t_conversions)); return dispatch::detail::Handle_Return::handle((o.*m_f)(boxed_cast(params[I+1], &t_conversions)...)); } private: decltype(t_func) m_f; }; return chaiscript::make_shared(t_func); }(); } template Proxy_Function fun(void (Class::*t_func)(Param...), std::index_sequence) { return [t_func](){ class Func final : public dispatch::Proxy_Function_Impl_Base { public: Func(decltype(t_func) func) : dispatch::Proxy_Function_Impl_Base({user_type(), user_type(), user_type()...}), m_f(func) { } bool compare_types_with_cast(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return compare_types_with_cast_impl(params, t_conversions); } protected: Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { Class &o = static_cast(boxed_cast(params[0], &t_conversions)); (o.*m_f)(boxed_cast(params[I+1], &t_conversions)...); return dispatch::detail::Handle_Return::handle(); } private: decltype(t_func) m_f; }; return chaiscript::make_shared(t_func); }(); } template Proxy_Function fun(Ret (Class::*t_func)(Param...), std::index_sequence) { return [t_func](){ class Func final : public dispatch::Proxy_Function_Impl_Base { public: Func(decltype(t_func) func) : dispatch::Proxy_Function_Impl_Base({user_type(), user_type(), user_type()...}), m_f(func) { } bool compare_types_with_cast(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { return compare_types_with_cast_impl(params, t_conversions); } protected: Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { Class &o = static_cast(boxed_cast(params[0], &t_conversions)); return dispatch::detail::Handle_Return::handle((o.*m_f)(boxed_cast(params[I+1], &t_conversions)...)); } private: decltype(t_func) m_f; }; return chaiscript::make_shared(t_func); }(); } template Proxy_Function fun(Ret (Class::*t_func)(Param...) const) { return fun(t_func, std::make_index_sequence()); } template Proxy_Function fun(Ret (*func)(Param...)) { return fun(func, std::make_index_sequence()); } template Proxy_Function fun(Ret (Class::*t_func)(Param...)) { return fun(t_func, std::make_index_sequence()); } template::value>::type*/> Proxy_Function fun(T Class::* m /*, typename std::enable_if::value>::type* = 0*/ ) { return Proxy_Function(chaiscript::make_shared>(m)); } /// \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 /// \param[in] q Value to bind to first parameter /// /// \b Example: /// \code /// struct MyClass /// { /// void memberfunction(int); /// }; /// /// MyClass obj; /// chaiscript::ChaiScript chai; /// // Add function taking only one argument, an int, and permanently bound to "obj" /// chai.add(fun(&MyClass::memberfunction, std::ref(obj)), "memberfunction"); /// \endcode /// /// \sa \ref adding_functions template Proxy_Function fun(T &&t, const Q &q) { return fun(detail::bind_first(std::forward(t), q)); } /// \brief Creates a new Proxy_Function object from a free function or member function and binds the first and second parameters of it /// \param[in] t Function / member to expose /// \param[in] q Value to bind to first parameter /// \param[in] r Value to bind to second parameter /// /// \b Example: /// \code /// struct MyClass /// { /// void memberfunction(int); /// }; /// /// MyClass obj; /// chaiscript::ChaiScript chai; /// // Add function taking only no arguments, and permanently bound to "obj" and "1" /// // memberfunction() will be equivalent to obj.memberfunction(1) /// chai.add(fun(&MyClass::memberfunction, std::ref(obj), 1), "memberfunction"); /// \endcode /// /// \sa \ref adding_functions template Proxy_Function fun(T &&t, Q &&q, R &&r) { return fun(detail::bind_first(detail::bind_first(std::forward(t), std::forward(q)), std::forward(r))); } } #endif