ChaiScript / ChaiScript
1
// This file is distributed under the BSD License.
2
// See "license.txt" for details.
3
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
4
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
5
// http://www.chaiscript.com
6

7
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
8
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
9

10

11
#ifndef CHAISCRIPT_FUNCTION_CALL_HPP_
12
#define CHAISCRIPT_FUNCTION_CALL_HPP_
13

14
#include <functional>
15
#include <string>
16
#include <vector>
17

18
#include "boxed_cast.hpp"
19
#include "function_call_detail.hpp"
20
#include "proxy_functions.hpp"
21

22
namespace chaiscript {
23
class Boxed_Value;
24
class Type_Conversions_State;
25
namespace detail {
26
template <typename T> struct Cast_Helper;
27
}  // namespace detail
28
}  // namespace chaiscript
29

30
namespace chaiscript
31
{
32
  namespace dispatch
33
  {
34
    namespace detail
35
    {
36
      template<typename Ret, typename ... Param>
37 1
        constexpr auto arity(Ret (*)(Param...)) noexcept
38
      {
39 1
        return sizeof...(Param);
40
      }
41
    }
42

43
    /// Build a function caller that knows how to dispatch on a set of functions
44
    /// example:
45
    /// std::function<void (int)> f =
46
    ///      build_function_caller(dispatchkit.get_function("print"));
47
    /// \returns A std::function object for dispatching
48
    /// \param[in] funcs the set of functions to dispatch on.
49
    template<typename FunctionType>
50 1
      std::function<FunctionType> functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
51
      {
52 1
        const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(),
53
            [](const Const_Proxy_Function &f) {
54
              return f->get_arity() == -1 || size_t(f->get_arity()) == detail::arity(static_cast<FunctionType *>(nullptr));
55
            });
56

57 1
        if (!has_arity_match) {
58 0
          throw exception::bad_boxed_cast(user_type<Const_Proxy_Function>(), typeid(std::function<FunctionType>));
59
        }
60

61 1
        FunctionType *p=nullptr;
62 1
        return detail::build_function_caller_helper(p, funcs, t_conversions);
63
      }
64

65
    /// Build a function caller for a particular Proxy_Function object
66
    /// useful in the case that a function is being pass out from scripting back
67
    /// into code
68
    /// example:
69
    /// void my_function(Proxy_Function f)
70
    /// {
71
    ///   std::function<void (int)> local_f =
72
    ///      build_function_caller(f);
73
    /// }
74
    /// \returns A std::function object for dispatching
75
    /// \param[in] func A function to execute.
76
    template<typename FunctionType>
77 1
      std::function<FunctionType> functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions)
78
      {
79 1
        return functor<FunctionType>(std::vector<Const_Proxy_Function>({std::move(func)}), t_conversions);
80
      }
81

82
    /// Helper for automatically unboxing a Boxed_Value that contains a function object
83
    /// and creating a typesafe C++ function caller from it.
84
    template<typename FunctionType>
85 1
      std::function<FunctionType> functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions)
86
      {
87 1
        return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
88
      }
89
  }
90

91
  namespace detail{
92
    /// Cast helper to handle automatic casting to const std::function &
93
    template<typename Signature>
94
      struct Cast_Helper<const std::function<Signature> &>
95
      {
96 1
        static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
97
        {
98 1
          if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
99
          {
100 1
            return dispatch::functor<Signature>(ob, t_conversions);
101
          } else {
102 0
            return Cast_Helper_Inner<const std::function<Signature> &>::cast(ob, t_conversions);
103
          }
104
        }
105
      };
106

107
    /// Cast helper to handle automatic casting to std::function
108
    template<typename Signature>
109
      struct Cast_Helper<std::function<Signature> >
110
      {
111
        static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
112
        {
113
          if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
114
          {
115
            return dispatch::functor<Signature>(ob, t_conversions);
116
          } else {
117 0
            return Cast_Helper_Inner<std::function<Signature> >::cast(ob, t_conversions);
118
          }
119
        }
120
      };
121

122
    /// Cast helper to handle automatic casting to const std::function
123
    template<typename Signature>
124
      struct Cast_Helper<const std::function<Signature> >
125
      {
126
        static std::function<Signature> cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions)
127
        {
128
          if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
129
          {
130
            return dispatch::functor<Signature>(ob, t_conversions);
131
          } else {
132
            return Cast_Helper_Inner<const std::function<Signature> >::cast(ob, t_conversions);
133
          }
134
        }
135
      };
136
  }
137
}
138

139
#endif
140

Read our documentation on viewing source code .

Loading