function_call.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // This file is distributed under the BSD License.
  2. // See "license.txt" for details.
  3. // Copyright 2009-2012, Jonathan Turner ([email protected])
  4. // Copyright 2009-2017, Jason Turner ([email protected])
  5. // http://www.chaiscript.com
  6. // This is an open source non-commercial project. Dear PVS-Studio, please check it.
  7. // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
  8. #ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
  9. #define CHAISCRIPT_FUNCTION_CALL_HPP_
  10. #include <functional>
  11. #include <string>
  12. #include <vector>
  13. #include "boxed_cast.hpp"
  14. #include "function_call_detail.hpp"
  15. #include "proxy_functions.hpp"
  16. #include "callable_traits.hpp"
  17. namespace chaiscript {
  18. class Boxed_Value;
  19. class Type_Conversions_State;
  20. namespace detail {
  21. template <typename T> struct Cast_Helper;
  22. } // namespace detail
  23. } // namespace chaiscript
  24. namespace chaiscript
  25. {
  26. namespace dispatch
  27. {
  28. /// Build a function caller that knows how to dispatch on a set of functions
  29. /// example:
  30. /// std::function<void (int)> f =
  31. /// build_function_caller(dispatchkit.get_function("print"));
  32. /// \returns A std::function object for dispatching
  33. /// \param[in] funcs the set of functions to dispatch on.
  34. template<typename FunctionType>
  35. std::function<FunctionType> functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
  36. {
  37. const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(),
  38. [](const Const_Proxy_Function &f) {
  39. return f->get_arity() == -1 || size_t(f->get_arity()) == chaiscript::dispatch::detail::Arity<FunctionType>::arity;
  40. });
  41. if (!has_arity_match) {
  42. throw exception::bad_boxed_cast(user_type<Const_Proxy_Function>(), typeid(std::function<FunctionType>));
  43. }
  44. FunctionType *p=nullptr;
  45. return detail::build_function_caller_helper(p, funcs, t_conversions);
  46. }
  47. /// Build a function caller for a particular Proxy_Function object
  48. /// useful in the case that a function is being pass out from scripting back
  49. /// into code
  50. /// example:
  51. /// void my_function(Proxy_Function f)
  52. /// {
  53. /// std::function<void (int)> local_f =
  54. /// build_function_caller(f);
  55. /// }
  56. /// \returns A std::function object for dispatching
  57. /// \param[in] func A function to execute.
  58. template<typename FunctionType>
  59. std::function<FunctionType> functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions)
  60. {
  61. return functor<FunctionType>(std::vector<Const_Proxy_Function>({std::move(func)}), t_conversions);
  62. }
  63. /// Helper for automatically unboxing a Boxed_Value that contains a function object
  64. /// and creating a typesafe C++ function caller from it.
  65. template<typename FunctionType>
  66. std::function<FunctionType> functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions)
  67. {
  68. return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
  69. }
  70. }
  71. namespace detail{
  72. /// Cast helper to handle automatic casting to const std::function &
  73. template<typename Signature>
  74. struct Cast_Helper<const std::function<Signature> &>
  75. {
  76. static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
  77. {
  78. if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
  79. {
  80. return dispatch::functor<Signature>(ob, t_conversions);
  81. } else {
  82. return Cast_Helper_Inner<const std::function<Signature> &>::cast(ob, t_conversions);
  83. }
  84. }
  85. };
  86. /// Cast helper to handle automatic casting to std::function
  87. template<typename Signature>
  88. struct Cast_Helper<std::function<Signature> >
  89. {
  90. static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
  91. {
  92. if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
  93. {
  94. return dispatch::functor<Signature>(ob, t_conversions);
  95. } else {
  96. return Cast_Helper_Inner<std::function<Signature> >::cast(ob, t_conversions);
  97. }
  98. }
  99. };
  100. /// Cast helper to handle automatic casting to const std::function
  101. template<typename Signature>
  102. struct Cast_Helper<const std::function<Signature> >
  103. {
  104. static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
  105. {
  106. if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
  107. {
  108. return dispatch::functor<Signature>(ob, t_conversions);
  109. } else {
  110. return Cast_Helper_Inner<const std::function<Signature> >::cast(ob, t_conversions);
  111. }
  112. }
  113. };
  114. }
  115. }
  116. #endif