// This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com // This is an open source non-commercial project. Dear PVS-Studio, please check it. // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com #ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_ #define CHAISCRIPT_REGISTER_FUNCTION_HPP_ #include #include "bind_first.hpp" #include "proxy_functions.hpp" #include "function_signature.hpp" namespace chaiscript { namespace dispatch::detail { template Param1 get_first_param(Function_Params, Obj &&obj) { return static_cast(std::forward(obj)); } template auto make_callable_impl(Func &&func, Function_Signature, Is_Noexcept, Is_Member, Is_MemberObject, Is_Object>) { if constexpr (Is_MemberObject) { // we now that the Param pack will have only one element, so we are safe expanding it here return Proxy_Function(chaiscript::make_shared...>>(std::forward(func))); } else if constexpr (Is_Member) { auto call = [func = std::forward(func)](auto && obj, auto && ... param) noexcept(Is_Noexcept) -> decltype(auto) { return (( get_first_param(Function_Params{}, obj).*func )(std::forward(param)...)); }; return Proxy_Function( chaiscript::make_shared>(std::move(call)) ); } else { return Proxy_Function( chaiscript::make_shared>>(std::forward(func)) ); } } // this version peels off the function object itself from the function signature, when used // on a callable object template auto make_callable(Func &&func, Function_Signature, Is_Noexcept, false, false, true>) { return make_callable_impl(std::forward(func), Function_Signature, Is_Noexcept, false, false, true>{}); } template auto make_callable(Func &&func, Function_Signature, Is_Noexcept, Is_Member, Is_MemberObject, false> fs) { return make_callable_impl(std::forward(func), fs); } } /// \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 fun(T &&t) { return dispatch::detail::make_callable(std::forward(t), dispatch::detail::Function_Signature{t}); } /// \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)); } } #endif