rttr  0.9.0
 All Classes Namespaces Files Functions Variables Typedefs Friends Macros Pages
method_accessor.h
Go to the documentation of this file.
1 /************************************************************************************
2 * *
3 * Copyright (c) 2014 Axel Menzel <info@axelmenzel.de> *
4 * *
5 * This file is part of RTTR (Run Time Type Reflection) *
6 * License: MIT License *
7 * *
8 * Permission is hereby granted, free of charge, to any person obtaining *
9 * a copy of this software and associated documentation files (the "Software"), *
10 * to deal in the Software without restriction, including without limitation *
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
12 * and/or sell copies of the Software, and to permit persons to whom the *
13 * Software is furnished to do so, subject to the following conditions: *
14 * *
15 * The above copyright notice and this permission notice shall be included in *
16 * all copies or substantial portions of the Software. *
17 * *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
24 * SOFTWARE. *
25 * *
26 *************************************************************************************/
27 
28 #ifndef __RTTR_METHOD_ACCESSOR__
29 #define __RTTR_METHOD_ACCESSOR__
30 
32 #include "rttr/detail/utility.h"
33 
34 namespace rttr
35 {
36 namespace detail
37 {
38 
39 template<typename F, typename IndexSequence, typename B>
40 struct method_accessor_impl;
41 
42 template<typename F, std::size_t... ArgCount>
43 struct method_accessor_impl<F, index_sequence<ArgCount...>, std::true_type>
44 {
45  static std::vector<bool> get_is_reference()
46  {
47  return { std::is_reference<typename param_types<F, ArgCount>::type>::value... };
48  }
49 
50  static std::vector<bool> get_is_const()
51  {
52  return { std::is_const<typename std::remove_reference<typename param_types<F, ArgCount>::type>::type>::value... };
53  }
54 
55  static std::vector<type> get_parameter_types()
56  {
57  return { type::get<typename param_types<F, ArgCount>::type>()... };
58  }
59 };
60 
61 template<typename F, std::size_t... ArgCount>
62 struct method_accessor_impl<F, index_sequence<ArgCount...>, std::false_type>
63 {
64  static std::vector<bool> get_is_reference()
65  {
66  return std::vector<bool>();
67  }
68 
69  static std::vector<bool> get_is_const()
70  {
71  return std::vector<bool>();
72  }
73 
74  static std::vector<type> get_parameter_types()
75  {
76  return std::vector<type>();
77  }
78 };
79 
80 template<typename F, typename Policy, typename Method_Type, typename IndexSequence, typename ArgCountInRange>
81 struct method_accessor_invoker;
82 
83 template<typename F, std::size_t... ArgCount>
84 struct method_accessor_invoker<F, default_invoke, void_member_func, index_sequence<ArgCount...>, std::true_type>
85 {
86  template<typename... TArgs>
87  RTTR_FORCE_INLINE static variant invoke(const F& func_ptr, const instance& obj, const TArgs&...args)
88  {
89  typedef typename function_traits<F>::class_type C;
90  C* ptr = obj.try_convert<C>();
91  if (ptr && check_all_true(args.template is_type<typename param_types<F, ArgCount>::type>()...))
92  {
93  (ptr->*func_ptr)(args.template get_value<typename param_types<F, ArgCount>::type>()...);
94  return void_variant;
95  }
96  else
97  return variant();
98  }
99 };
100 
101 template<typename F, std::size_t... ArgCount>
102 struct method_accessor_invoker<F, default_invoke, void_func, index_sequence<ArgCount...>, std::true_type>
103 {
104  template<typename... TArgs>
105  RTTR_FORCE_INLINE static variant invoke(const F& func, const instance& obj, const TArgs&...args)
106  {
107  if (check_all_true(args.template is_type<typename param_types<F, ArgCount>::type>()...))
108  {
109  func(args.template get_value<typename param_types<F, ArgCount>::type>()...);
110  return void_variant;
111  }
112  else
113  return variant();
114  }
115 };
116 
117 template<typename F, std::size_t... ArgCount>
118 struct method_accessor_invoker<F, default_invoke, return_member_func, index_sequence<ArgCount...>, std::true_type>
119 {
120  template<typename... TArgs>
121  RTTR_FORCE_INLINE static variant invoke(const F& func_ptr, const instance& obj, const TArgs&...args)
122  {
123  typedef typename function_traits<F>::class_type C;
124  C* ptr = obj.try_convert<C>();
125  if (ptr && check_all_true(args.template is_type<typename param_types<F, ArgCount>::type>()...))
126  return (ptr->*func_ptr)(args.template get_value<typename param_types<F, ArgCount>::type>()...);
127  else
128  return variant();
129  }
130 };
131 
132 template<typename F, std::size_t... ArgCount>
133 struct method_accessor_invoker<F, default_invoke, return_func, index_sequence<ArgCount...>, std::true_type>
134 {
135  template<typename... TArgs>
136  RTTR_FORCE_INLINE static variant invoke(const F& func, const instance& obj, const TArgs&...args)
137  {
138  if (check_all_true(args.template is_type<typename param_types<F, ArgCount>::type>()...))
139  return func(args.template get_value<typename param_types<F, ArgCount>::type>()...);
140  else
141  return variant();
142  }
143 };
144 
145 template<typename F, std::size_t... ArgCount>
146 struct method_accessor_invoker<F, discard_return, return_member_func, index_sequence<ArgCount...>, std::true_type>
147 {
148  template<typename... TArgs>
149  RTTR_FORCE_INLINE static variant invoke(const F& func_ptr, const instance& obj, const TArgs&...args)
150  {
151  typedef typename function_traits<F>::class_type C;
152  C* ptr = obj.try_convert<C>();
153  if (ptr && check_all_true(args.template is_type<typename param_types<F, ArgCount>::type>()...))
154  {
155  (ptr->*func_ptr)(args.template get_value<typename param_types<F, ArgCount>::type>()...);
156  return void_variant;
157  }
158  else
159  return variant();
160  }
161 };
162 
163 template<typename F, std::size_t... ArgCount>
164 struct method_accessor_invoker<F, discard_return, return_func, index_sequence<ArgCount...>, std::true_type>
165 {
166  template<typename... TArgs>
167  RTTR_FORCE_INLINE static variant invoke(const F& func, const instance& obj, const TArgs&...args)
168  {
169  if (check_all_true(args.template is_type<typename param_types<F, ArgCount>::type>()...))
170  {
171  func(args.template get_value<typename param_types<F, ArgCount>::type>()...);
172  return void_variant;
173  }
174  else
175  return variant();
176  }
177 };
178 
179 template<typename F, std::size_t... ArgCount>
180 struct method_accessor_invoker<F, return_as_ptr, return_member_func, index_sequence<ArgCount...>, std::true_type>
181 {
182  template<typename... TArgs>
183  RTTR_FORCE_INLINE static variant invoke(const F& func_ptr, const instance& obj, const TArgs&...args)
184  {
185  typedef typename function_traits<F>::class_type C;
186  C* ptr = obj.try_convert<C>();
187  if (ptr && check_all_true(args.template is_type<typename param_types<F, ArgCount>::type>()...))
188  {
189  return &(ptr->*func_ptr)(args.template get_value<typename param_types<F, ArgCount>::type>()...);
190  }
191  else
192  return variant();
193  }
194 };
195 
196 template<typename F, std::size_t... ArgCount>
197 struct method_accessor_invoker<F, return_as_ptr, return_func, index_sequence<ArgCount...>, std::true_type>
198 {
199  template<typename... TArgs>
200  RTTR_FORCE_INLINE static variant invoke(const F& func, const instance& obj, const TArgs&...args)
201  {
202  if (check_all_true(args.template is_type<typename param_types<F, ArgCount>::type>()...))
203  {
204  return &func(args.template get_value<typename param_types<F, ArgCount>::type>()...);
205  }
206  else
207  return variant();
208  }
209 };
210 
211 template<typename F, typename Policy, typename MethodType, typename IndexSequence>
212 struct method_accessor_invoker<F, Policy, MethodType, IndexSequence, std::false_type>
213 {
214  template<typename... TArgs>
215  RTTR_FORCE_INLINE static variant invoke(const F& func_ptr, const instance& obj, const TArgs&...args)
216  {
217  return variant();
218  }
219 };
220 
221 template<typename F, typename Policy, typename IndexSequence>
222 struct method_accessor_variadic;
223 
224 template<typename F, typename Policy, std::size_t... ArgCount>
225 struct method_accessor_variadic<F, Policy, index_sequence<ArgCount...>>
226 {
227  static variant invoke(const F& func_ptr, const instance& obj, std::vector<argument>& arg_list)
228  {
229  using method_type = typename detail::method_type<F>::type;
230  return method_accessor_invoker<F, Policy, method_type, index_sequence<ArgCount...>, std::true_type>::invoke(func_ptr, obj, arg_list[ArgCount]...);
231  }
232 };
233 
234 template<typename MethodType>
235 struct method_accessor_helper_is_static
236 {
237  static bool is_static() { return true; }
238 };
239 
240 template<>
241 struct method_accessor_helper_is_static<return_member_func>
242 {
243  static bool is_static() { return false; }
244 };
245 
246 template<>
247 struct method_accessor_helper_is_static<void_member_func>
248 {
249  static bool is_static() { return false; }
250 };
251 
252 template<typename F, typename Policy>
253 struct method_accessor_helper_return_type
254 {
255  static type get_return_type() { return type::get<typename function_traits<F>::return_type>(); }
256 };
257 
258 template<typename F>
259 struct method_accessor_helper_return_type<F, return_as_ptr>
260 {
261  using return_type = typename function_traits<F>::return_type;
262  static type get_return_type() { return type::get<typename std::remove_reference<return_type>::type*>(); }
263 };
264 
265 template<typename F>
266 struct method_accessor_helper_return_type<F, discard_return>
267 {
268  static type get_return_type() { return type::get<void>(); }
269 };
270 
271 template<typename F, typename Policy>
272 struct method_accessor
273 {
274  static bool is_static()
275  {
276  using method_type = typename detail::method_type<F>::type;
277  return method_accessor_helper_is_static<method_type>::is_static();
278  }
279 
280  static type get_return_type()
281  {
282  return method_accessor_helper_return_type<F, Policy>::get_return_type();
283  }
284 
285  static std::vector<bool> get_is_reference()
286  {
287  const std::size_t ArgCount = function_traits<F>::arg_count;
288  using has_arguments = typename std::integral_constant<bool, ArgCount != 0>::type;
289  return method_accessor_impl<F, make_index_sequence<ArgCount>, has_arguments>::get_is_reference();
290  }
291 
292  static std::vector<bool> get_is_const()
293  {
294  const std::size_t ArgCount = function_traits<F>::arg_count;
295  using has_arguments = typename std::integral_constant<bool, ArgCount != 0>::type;
296  return method_accessor_impl<F, make_index_sequence<ArgCount>, has_arguments>::get_is_const();
297  }
298 
299  static std::vector<type> get_parameter_types()
300  {
301  const std::size_t ArgCount = function_traits<F>::arg_count;
302  using has_arguments = typename std::integral_constant<bool, ArgCount != 0>::type;
303  return method_accessor_impl<F, make_index_sequence<ArgCount>, has_arguments>::get_parameter_types();
304  }
305 
306  template<typename... TArgs>
307  RTTR_FORCE_INLINE static variant invoke(const F& func_ptr, const instance& obj, const TArgs&...args)
308  {
309  const std::size_t ArgCount = function_traits<F>::arg_count;
310  using method_type = typename detail::method_type<F>::type;
311  using arg_count_in_range = typename std::integral_constant<bool, ArgCount == sizeof...(args)>::type;
312  return method_accessor_invoker<F, Policy, method_type, make_index_sequence<ArgCount>, arg_count_in_range>::invoke(func_ptr, obj, args...);
313  }
314 
315  template<typename... TArgs>
316  RTTR_FORCE_INLINE static variant invoke(const F& func_ptr, const instance& obj, std::vector<argument>& arg_list)
317  {
318  const std::size_t ArgCount = function_traits<F>::arg_count;
319  if (arg_list.size() == ArgCount)
320  return method_accessor_variadic<F, Policy, make_index_sequence<ArgCount>>::invoke(func_ptr, obj, arg_list);
321  else
322  return variant();
323  }
324 };
325 
326 } // end namespace detail
327 } // end namespace rttr
328 
329 #endif // __RTTR_METHOD_ACCESSOR__
#define RTTR_FORCE_INLINE
Definition: core_prerequisites.h:91